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()) {
5710 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5720 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5721 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5724 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5726 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5729 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5731 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5733 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5734 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5743 MI.eraseFromParent();
5757 Register SrcCond =
MI.getOperand(3).getReg();
5765 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5767 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5769 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5771 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5774 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5776 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5779 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5781 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5784 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5786 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5808 MI.eraseFromParent();
5813 case AMDGPU::S_MIN_U32:
5814 return std::numeric_limits<uint32_t>::max();
5815 case AMDGPU::S_MIN_I32:
5816 return std::numeric_limits<int32_t>::max();
5817 case AMDGPU::S_MAX_U32:
5818 return std::numeric_limits<uint32_t>::min();
5819 case AMDGPU::S_MAX_I32:
5820 return std::numeric_limits<int32_t>::min();
5821 case AMDGPU::V_ADD_F32_e64:
5823 case AMDGPU::V_SUB_F32_e64:
5825 case AMDGPU::S_ADD_I32:
5826 case AMDGPU::S_SUB_I32:
5827 case AMDGPU::S_OR_B32:
5828 case AMDGPU::S_XOR_B32:
5829 return std::numeric_limits<uint32_t>::min();
5830 case AMDGPU::S_AND_B32:
5831 return std::numeric_limits<uint32_t>::max();
5832 case AMDGPU::V_MIN_F32_e64:
5833 case AMDGPU::V_MAX_F32_e64:
5835 case AMDGPU::V_CMP_LT_U64_e64:
5836 return std::numeric_limits<uint64_t>::max();
5837 case AMDGPU::V_CMP_LT_I64_e64:
5838 return std::numeric_limits<int64_t>::max();
5839 case AMDGPU::V_CMP_GT_U64_e64:
5840 return std::numeric_limits<uint64_t>::min();
5841 case AMDGPU::V_CMP_GT_I64_e64:
5842 return std::numeric_limits<int64_t>::min();
5843 case AMDGPU::V_MIN_F64_e64:
5844 case AMDGPU::V_MAX_F64_e64:
5845 case AMDGPU::V_MIN_NUM_F64_e64:
5846 case AMDGPU::V_MAX_NUM_F64_e64:
5847 return 0x7FF8000000000000;
5848 case AMDGPU::S_ADD_U64_PSEUDO:
5849 case AMDGPU::S_SUB_U64_PSEUDO:
5850 case AMDGPU::S_OR_B64:
5851 case AMDGPU::S_XOR_B64:
5852 return std::numeric_limits<uint64_t>::min();
5853 case AMDGPU::S_AND_B64:
5854 return std::numeric_limits<uint64_t>::max();
5855 case AMDGPU::V_ADD_F64_e64:
5856 case AMDGPU::V_ADD_F64_pseudo_e64:
5857 return 0x8000000000000000;
5864 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5865 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5866 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5867 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5868 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5869 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5870 Opc == AMDGPU::V_SUB_F32_e64;
5874 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5875 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5876 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5877 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5878 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5881static std::tuple<unsigned, unsigned>
5885 case AMDGPU::S_MIN_U32:
5886 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5888 case AMDGPU::S_MIN_I32:
5889 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5891 case AMDGPU::S_MAX_U32:
5892 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5894 case AMDGPU::S_MAX_I32:
5895 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5897 case AMDGPU::S_ADD_I32:
5898 case AMDGPU::S_SUB_I32:
5899 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5900 : AMDGPU::V_ADD_CO_U32_dpp;
5902 case AMDGPU::S_AND_B32:
5903 DPPOpc = AMDGPU::V_AND_B32_dpp;
5905 case AMDGPU::S_OR_B32:
5906 DPPOpc = AMDGPU::V_OR_B32_dpp;
5908 case AMDGPU::S_XOR_B32:
5909 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5911 case AMDGPU::V_ADD_F32_e64:
5912 case AMDGPU::V_SUB_F32_e64:
5913 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5915 case AMDGPU::V_MIN_F32_e64:
5916 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5918 case AMDGPU::V_MAX_F32_e64:
5919 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5921 case AMDGPU::V_CMP_LT_U64_e64:
5922 case AMDGPU::V_CMP_LT_I64_e64:
5923 case AMDGPU::V_CMP_GT_U64_e64:
5924 case AMDGPU::V_CMP_GT_I64_e64:
5925 case AMDGPU::S_ADD_U64_PSEUDO:
5926 case AMDGPU::S_SUB_U64_PSEUDO:
5927 case AMDGPU::S_AND_B64:
5928 case AMDGPU::S_OR_B64:
5929 case AMDGPU::S_XOR_B64:
5930 case AMDGPU::V_MIN_NUM_F64_e64:
5931 case AMDGPU::V_MIN_F64_e64:
5932 case AMDGPU::V_MAX_NUM_F64_e64:
5933 case AMDGPU::V_MAX_F64_e64:
5934 case AMDGPU::V_ADD_F64_pseudo_e64:
5935 case AMDGPU::V_ADD_F64_e64:
5936 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5941 unsigned ClampOpc =
Opc;
5942 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5943 if (
Opc == AMDGPU::S_SUB_I32)
5944 ClampOpc = AMDGPU::S_ADD_I32;
5945 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5946 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5947 else if (
Opc == AMDGPU::S_AND_B64)
5948 ClampOpc = AMDGPU::V_AND_B32_e64;
5949 else if (
Opc == AMDGPU::S_OR_B64)
5950 ClampOpc = AMDGPU::V_OR_B32_e64;
5951 else if (
Opc == AMDGPU::S_XOR_B64)
5952 ClampOpc = AMDGPU::V_XOR_B32_e64;
5954 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5956 return {DPPOpc, ClampOpc};
5959static std::pair<Register, Register>
5966 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5968 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5970 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5971 return {Op1L, Op1H};
5987 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
5988 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
5990 unsigned MIOpc =
MI.getOpcode();
6004 case AMDGPU::S_MIN_U32:
6005 case AMDGPU::S_MIN_I32:
6006 case AMDGPU::V_MIN_F32_e64:
6007 case AMDGPU::S_MAX_U32:
6008 case AMDGPU::S_MAX_I32:
6009 case AMDGPU::V_MAX_F32_e64:
6010 case AMDGPU::S_AND_B32:
6011 case AMDGPU::S_OR_B32: {
6017 case AMDGPU::V_CMP_LT_U64_e64:
6018 case AMDGPU::V_CMP_LT_I64_e64:
6019 case AMDGPU::V_CMP_GT_U64_e64:
6020 case AMDGPU::V_CMP_GT_I64_e64:
6021 case AMDGPU::V_MIN_F64_e64:
6022 case AMDGPU::V_MIN_NUM_F64_e64:
6023 case AMDGPU::V_MAX_F64_e64:
6024 case AMDGPU::V_MAX_NUM_F64_e64:
6025 case AMDGPU::S_AND_B64:
6026 case AMDGPU::S_OR_B64: {
6032 case AMDGPU::S_XOR_B32:
6033 case AMDGPU::S_XOR_B64:
6034 case AMDGPU::S_ADD_I32:
6035 case AMDGPU::S_ADD_U64_PSEUDO:
6036 case AMDGPU::V_ADD_F32_e64:
6037 case AMDGPU::V_ADD_F64_e64:
6038 case AMDGPU::V_ADD_F64_pseudo_e64:
6039 case AMDGPU::S_SUB_I32:
6040 case AMDGPU::S_SUB_U64_PSEUDO:
6041 case AMDGPU::V_SUB_F32_e64: {
6048 bool IsWave32 = ST.isWave32();
6049 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6050 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6051 unsigned BitCountOpc =
6052 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6056 auto NewAccumulator =
6061 case AMDGPU::S_XOR_B32:
6062 case AMDGPU::S_XOR_B64: {
6071 .
addReg(NewAccumulator->getOperand(0).getReg())
6074 if (
Opc == AMDGPU::S_XOR_B32) {
6091 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6095 case AMDGPU::S_SUB_I32: {
6104 .
addReg(NewAccumulator->getOperand(0).getReg());
6107 case AMDGPU::S_ADD_I32: {
6110 .
addReg(NewAccumulator->getOperand(0).getReg());
6113 case AMDGPU::S_ADD_U64_PSEUDO:
6114 case AMDGPU::S_SUB_U64_PSEUDO: {
6130 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6133 .
addReg(NewAccumulator->getOperand(0).getReg())
6143 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6145 : NewAccumulator->getOperand(0).getReg();
6149 if (ST.hasScalarMulHiInsts()) {
6160 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6163 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6170 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6176 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6182 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6185 case AMDGPU::V_ADD_F32_e64:
6186 case AMDGPU::V_ADD_F64_e64:
6187 case AMDGPU::V_ADD_F64_pseudo_e64:
6188 case AMDGPU::V_SUB_F32_e64: {
6195 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6196 : AMDGPU::V_CVT_F64_I32_e64),
6198 .
addReg(NewAccumulator->getOperand(0).getReg())
6203 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6204 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6207 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6209 ? AMDGPU::V_MUL_F64_pseudo_e64
6210 : AMDGPU::V_MUL_F64_e64;
6220 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6237 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6249 bool NeedsMovDPP = !is32BitOpc;
6254 bool IsWave32 = ST.isWave32();
6255 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6256 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6257 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6283 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6287 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6288 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6297 I = ComputeLoop->begin();
6299 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6303 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6307 I = ComputeLoop->end();
6311 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6316 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6317 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6318 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6319 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6321 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6323 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6325 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6326 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6330 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6334 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6336 OpDstReg = VgprResultReg;
6337 LaneValueReg = LaneValVgpr;
6340 if (hasSrc0Modifier)
6342 OpInstr.addReg(AccumulatorReg);
6343 if (hasSrc1Modifier)
6345 OpInstr.addReg(LaneValueReg);
6352 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6353 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6367 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6371 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6375 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6376 LaneValueLoReg, LaneValueHiReg);
6378 case AMDGPU::S_OR_B64:
6379 case AMDGPU::S_AND_B64:
6380 case AMDGPU::S_XOR_B64: {
6383 .
addReg(LaneValue->getOperand(0).getReg())
6387 case AMDGPU::V_CMP_GT_I64_e64:
6388 case AMDGPU::V_CMP_GT_U64_e64:
6389 case AMDGPU::V_CMP_LT_I64_e64:
6390 case AMDGPU::V_CMP_LT_U64_e64: {
6395 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6397 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6401 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6404 .
addReg(LaneValue->getOperand(0).getReg())
6405 .
addReg(AccumulatorVReg);
6407 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6408 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6412 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6413 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6414 .
addReg(LaneValue->getOperand(0).getReg())
6418 case AMDGPU::V_MIN_F64_e64:
6419 case AMDGPU::V_MIN_NUM_F64_e64:
6420 case AMDGPU::V_MAX_F64_e64:
6421 case AMDGPU::V_MAX_NUM_F64_e64:
6422 case AMDGPU::V_ADD_F64_e64:
6423 case AMDGPU::V_ADD_F64_pseudo_e64: {
6425 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6427 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6434 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6437 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6443 .
addReg(LaneValue->getOperand(0).getReg())
6450 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6453 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6455 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6457 ReadLaneLo.addReg(Op1L);
6458 ReadLaneHi.addReg(Op1H);
6460 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6463 case AMDGPU::S_ADD_U64_PSEUDO:
6464 case AMDGPU::S_SUB_U64_PSEUDO: {
6467 .
addReg(LaneValue->getOperand(0).getReg());
6475 unsigned BITSETOpc =
6476 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6477 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6483 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6487 if (!ST.hasScalarCompareEq64()) {
6490 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6492 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6495 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6496 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6498 SetSCCInstr.
addReg(NewActiveBitsReg);
6499 if (ST.hasScalarCompareEq64())
6502 SetSCCInstr.
addReg(NewActiveBitsReg);
6503 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6508 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6525 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6529 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6530 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6533 auto IdentityCopyInstr =
6537 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6538 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6553 if (isFPOp && !NeedsMovDPP)
6556 if (isFPOp && !NeedsMovDPP)
6560 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6569 bool isAddSub =
false,
6570 bool needsCarryIn =
false,
6572 unsigned InstrOpc = ClampOpc;
6575 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6576 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6581 ClampInstr.addReg(CarryOutReg,
6587 ClampInstr.addReg(Src0);
6590 ClampInstr.addReg(Src1);
6593 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6594 ClampInstr.addImm(0);
6596 ClampInstr.addImm(0);
6597 LastBcastInstr = ClampInstr;
6602 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6603 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6604 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6606 if (isAddSubOpc || isBitWiseOpc) {
6613 auto [Src0Lo, Src0Hi] =
6615 auto [Src1Lo, Src1Hi] =
6617 Register CarryReg = BuildClampInstr(
6618 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6619 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6620 isAddSubOpc, CarryReg);
6621 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6650 SrcWithIdentityInstr =
6651 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6658 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6659 auto [SrcReg0Sub0, SrcReg0Sub1] =
6662 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6664 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6665 SrcWithIdentityInstr =
6666 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6673 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6676 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6678 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6681 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6683 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6686 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6688 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6691 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6693 if (ST.hasDPPBroadcasts()) {
6696 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6711 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6732 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6735 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6737 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6740 FinalDPPResult = RowBcast15;
6742 if (ST.hasDPPBroadcasts()) {
6745 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6761 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6765 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6771 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6779 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6784 .
addReg(ShiftedThreadID);
6789 .
addReg(PermuteByteOffset)
6799 auto [RowBcast15Lo, RowBcast15Hi] =
6803 .
addReg(PermuteByteOffset)
6808 .
addReg(PermuteByteOffset)
6811 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6815 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6817 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6819 FinalDPPResult = RowBcast31;
6821 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6822 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6832 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6835 FinalDPPResult = NegatedValVGPR;
6842 .
addImm(ST.getWavefrontSize() - 1);
6857 .
addImm(ST.getWavefrontSize() - 1);
6861 .
addImm(ST.getWavefrontSize() - 1);
6862 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6865 if (
Opc == AMDGPU::S_SUB_I32) {
6866 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6869 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6870 auto NegatedValInstr =
6878 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6884 MI.eraseFromParent();
6899 switch (
MI.getOpcode()) {
6900 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6902 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6904 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6906 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6908 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6910 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6913 ? AMDGPU::V_MIN_NUM_F64_e64
6914 : AMDGPU::V_MIN_F64_e64);
6915 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6917 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6919 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6921 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6923 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6925 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6928 ? AMDGPU::V_MAX_NUM_F64_e64
6929 : AMDGPU::V_MAX_F64_e64);
6930 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6932 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6934 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6936 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6939 ? AMDGPU::V_ADD_F64_pseudo_e64
6940 : AMDGPU::V_ADD_F64_e64);
6941 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6943 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6945 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6947 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6952 ? AMDGPU::V_ADD_F64_pseudo_e64
6953 : AMDGPU::V_ADD_F64_e64);
6954 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
6956 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
6958 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
6960 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
6962 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
6964 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
6966 case AMDGPU::S_UADDO_PSEUDO:
6967 case AMDGPU::S_USUBO_PSEUDO: {
6973 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
6975 : AMDGPU::S_SUB_U32;
6983 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
6986 MI.eraseFromParent();
6989 case AMDGPU::S_ADD_U64_PSEUDO:
6990 case AMDGPU::S_SUB_U64_PSEUDO: {
6993 case AMDGPU::V_ADD_U64_PSEUDO:
6994 case AMDGPU::V_SUB_U64_PSEUDO: {
6995 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7001 if (ST.hasAddSubU64Insts()) {
7003 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7004 : AMDGPU::V_SUB_U64_e64),
7009 TII->legalizeOperands(*
I);
7010 MI.eraseFromParent();
7014 if (IsAdd && ST.hasLshlAddU64Inst()) {
7020 TII->legalizeOperands(*
Add);
7021 MI.eraseFromParent();
7025 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7035 : &AMDGPU::VReg_64RegClass;
7038 : &AMDGPU::VReg_64RegClass;
7041 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7043 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7046 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7048 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7051 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7053 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7056 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7063 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7077 TII->legalizeOperands(*LoHalf);
7078 TII->legalizeOperands(*HiHalf);
7079 MI.eraseFromParent();
7082 case AMDGPU::S_ADD_CO_PSEUDO:
7083 case AMDGPU::S_SUB_CO_PSEUDO: {
7095 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7101 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7106 if (
TRI->isVectorRegister(MRI, Src2.
getReg())) {
7107 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7112 if (ST.isWave64()) {
7113 if (ST.hasScalarCompareEq64()) {
7120 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7122 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7124 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7127 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7141 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7142 ? AMDGPU::S_ADDC_U32
7143 : AMDGPU::S_SUBB_U32;
7148 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7154 MI.eraseFromParent();
7157 case AMDGPU::SI_INIT_M0: {
7160 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7163 MI.eraseFromParent();
7166 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7169 TII->get(AMDGPU::S_CMP_EQ_U32))
7174 case AMDGPU::GET_GROUPSTATICSIZE: {
7178 .
add(
MI.getOperand(0))
7180 MI.eraseFromParent();
7183 case AMDGPU::GET_SHADERCYCLESHILO: {
7198 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7201 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7204 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7213 .
add(
MI.getOperand(0))
7218 MI.eraseFromParent();
7221 case AMDGPU::SI_INDIRECT_SRC_V1:
7222 case AMDGPU::SI_INDIRECT_SRC_V2:
7223 case AMDGPU::SI_INDIRECT_SRC_V3:
7224 case AMDGPU::SI_INDIRECT_SRC_V4:
7225 case AMDGPU::SI_INDIRECT_SRC_V5:
7226 case AMDGPU::SI_INDIRECT_SRC_V6:
7227 case AMDGPU::SI_INDIRECT_SRC_V7:
7228 case AMDGPU::SI_INDIRECT_SRC_V8:
7229 case AMDGPU::SI_INDIRECT_SRC_V9:
7230 case AMDGPU::SI_INDIRECT_SRC_V10:
7231 case AMDGPU::SI_INDIRECT_SRC_V11:
7232 case AMDGPU::SI_INDIRECT_SRC_V12:
7233 case AMDGPU::SI_INDIRECT_SRC_V16:
7234 case AMDGPU::SI_INDIRECT_SRC_V32:
7236 case AMDGPU::SI_INDIRECT_DST_V1:
7237 case AMDGPU::SI_INDIRECT_DST_V2:
7238 case AMDGPU::SI_INDIRECT_DST_V3:
7239 case AMDGPU::SI_INDIRECT_DST_V4:
7240 case AMDGPU::SI_INDIRECT_DST_V5:
7241 case AMDGPU::SI_INDIRECT_DST_V6:
7242 case AMDGPU::SI_INDIRECT_DST_V7:
7243 case AMDGPU::SI_INDIRECT_DST_V8:
7244 case AMDGPU::SI_INDIRECT_DST_V9:
7245 case AMDGPU::SI_INDIRECT_DST_V10:
7246 case AMDGPU::SI_INDIRECT_DST_V11:
7247 case AMDGPU::SI_INDIRECT_DST_V12:
7248 case AMDGPU::SI_INDIRECT_DST_V16:
7249 case AMDGPU::SI_INDIRECT_DST_V32:
7251 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7252 case AMDGPU::SI_KILL_I1_PSEUDO:
7254 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7258 case AMDGPU::SI_BR_UNDEF: {
7260 .
add(
MI.getOperand(0));
7262 MI.eraseFromParent();
7265 case AMDGPU::ADJCALLSTACKUP:
7266 case AMDGPU::ADJCALLSTACKDOWN: {
7273 case AMDGPU::SI_CALL_ISEL: {
7274 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7277 MIB =
BuildMI(*BB,
MI,
DL,
TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7283 MI.eraseFromParent();
7286 case AMDGPU::V_ADD_CO_U32_e32:
7287 case AMDGPU::V_SUB_CO_U32_e32:
7288 case AMDGPU::V_SUBREV_CO_U32_e32: {
7290 unsigned Opc =
MI.getOpcode();
7292 bool NeedClampOperand =
false;
7293 if (
TII->pseudoToMCOpcode(
Opc) == -1) {
7295 NeedClampOperand =
true;
7299 if (
TII->isVOP3(*
I)) {
7302 I.add(
MI.getOperand(1)).add(
MI.getOperand(2));
7303 if (NeedClampOperand)
7306 TII->legalizeOperands(*
I);
7308 MI.eraseFromParent();
7311 case AMDGPU::V_ADDC_U32_e32:
7312 case AMDGPU::V_SUBB_U32_e32:
7313 case AMDGPU::V_SUBBREV_U32_e32:
7316 TII->legalizeOperands(
MI);
7318 case AMDGPU::DS_GWS_INIT:
7319 case AMDGPU::DS_GWS_SEMA_BR:
7320 case AMDGPU::DS_GWS_BARRIER:
7321 case AMDGPU::DS_GWS_SEMA_V:
7322 case AMDGPU::DS_GWS_SEMA_P:
7323 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7331 case AMDGPU::S_SETREG_B32: {
7341 auto [ID,
Offset, Width] =
7347 const unsigned SetMask = WidthMask <<
Offset;
7350 unsigned SetDenormOp = 0;
7351 unsigned SetRoundOp = 0;
7359 SetRoundOp = AMDGPU::S_ROUND_MODE;
7360 SetDenormOp = AMDGPU::S_DENORM_MODE;
7362 SetRoundOp = AMDGPU::S_ROUND_MODE;
7364 SetDenormOp = AMDGPU::S_DENORM_MODE;
7367 if (SetRoundOp || SetDenormOp) {
7369 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7370 unsigned ImmVal = Def->getOperand(1).getImm();
7384 MI.eraseFromParent();
7393 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7397 case AMDGPU::S_INVERSE_BALLOT_U32:
7398 case AMDGPU::S_INVERSE_BALLOT_U64:
7401 MI.setDesc(
TII->get(AMDGPU::COPY));
7403 case AMDGPU::ENDPGM_TRAP: {
7405 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7425 MI.eraseFromParent();
7428 case AMDGPU::SIMULATED_TRAP: {
7429 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7431 TII->insertSimulatedTrap(MRI, *BB,
MI,
MI.getDebugLoc());
7432 MI.eraseFromParent();
7435 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7436 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7442 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7443 Register OriginalExec = Setup->getOperand(0).getReg();
7445 MI.getOperand(0).setReg(OriginalExec);
7448 case AMDGPU::V_DOT2_F32_F16:
7449 case AMDGPU::V_DOT2_F32_BF16: {
7456 case AMDGPU::SCHED_BARRIER:
7457 case AMDGPU::SCHED_GROUP_BARRIER:
7458 MI.getOperand(0).setImm(
MI.getOperand(0).getImm() &
7495 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7499 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7528 if (!Subtarget->hasMadMacF32Insts())
7529 return Subtarget->hasFastFMAF32();
7535 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7538 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7544 return Subtarget->has16BitInsts() &&
7562 F.getDenormalFPEnv());
7567 switch (Ty.getScalarSizeInBits()) {
7585 return Subtarget->hasMadMacF32Insts() &&
7588 return Subtarget->hasMadF16() &&
7599 if (Ty.getScalarSizeInBits() == 16)
7601 if (Ty.getScalarSizeInBits() == 32)
7616 F.getDenormalFPEnv());
7627 unsigned Opc =
Op.getOpcode();
7628 EVT VT =
Op.getValueType();
7640 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7641 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7654 [[maybe_unused]]
EVT VT =
Op.getValueType();
7656 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7657 VT == MVT::v16i32) &&
7658 "Unexpected ValueType.");
7667 unsigned Opc =
Op.getOpcode();
7668 EVT VT =
Op.getValueType();
7677 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7679 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7686 unsigned Opc =
Op.getOpcode();
7687 EVT VT =
Op.getValueType();
7704 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7706 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7712 switch (
Op.getOpcode()) {
7716 return LowerBRCOND(
Op, DAG);
7718 return LowerRETURNADDR(
Op, DAG);
7720 return LowerSPONENTRY(
Op, DAG);
7723 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7724 "Load should return a value and a chain");
7728 EVT VT =
Op.getValueType();
7730 return lowerFSQRTF32(
Op, DAG);
7732 return lowerFSQRTF64(
Op, DAG);
7737 return LowerTrig(
Op, DAG);
7739 return LowerSELECT(
Op, DAG);
7741 return LowerFDIV(
Op, DAG);
7743 return LowerFFREXP(
Op, DAG);
7745 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7747 return LowerSTORE(
Op, DAG);
7751 return LowerGlobalAddress(MFI,
Op, DAG);
7756 return LowerExternalSymbol(
Op, DAG);
7758 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7760 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7762 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7764 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7766 return LowerINTRINSIC_VOID(
Op, DAG);
7768 return lowerADDRSPACECAST(
Op, DAG);
7770 return lowerINSERT_SUBVECTOR(
Op, DAG);
7772 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7774 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7776 return lowerVECTOR_SHUFFLE(
Op, DAG);
7778 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7780 return lowerBUILD_VECTOR(
Op, DAG);
7783 return lowerFP_ROUND(
Op, DAG);
7785 return lowerTRAP(
Op, DAG);
7787 return lowerDEBUGTRAP(
Op, DAG);
7796 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7797 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7801 if (
Op.getValueType() == MVT::bf16) {
7831 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7834 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7837 return lowerFLDEXP(
Op, DAG);
7842 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7843 Op.getOperand(0).getValueType() == MVT::f32) {
7869 return lowerFCOPYSIGN(
Op, DAG);
7871 return lowerMUL(
Op, DAG);
7874 return lowerXMULO(
Op, DAG);
7877 return lowerXMUL_LOHI(
Op, DAG);
7898 return LowerINLINEASM(
Op, DAG);
7904static std::pair<SDValue, SDValue>
7934 EVT FittingLoadVT = LoadVT;
7966SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7969 bool IsIntrinsic)
const {
7972 bool IsTFE =
M->getNumValues() == 3;
7973 bool Unpacked = Subtarget->hasUnpackedD16VMem();
7974 EVT LoadVT =
M->getValueType(0);
7976 EVT EquivLoadVT = LoadVT;
7993 SDVTList VTList = DAG.
getVTList(LoadDWordsVT, MVT::Other);
7995 Opcode,
DL, VTList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
8003 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
8007 M->getMemoryVT(),
M->getMemOperand());
8018 EVT LoadVT =
M->getValueType(0);
8027 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
8031 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
8032 bool IsTFE =
M->getNumValues() == 3;
8034 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8037 "TFE D16 format buffer load is not supported on this GPU",
8040 M->getOperand(0),
DL);
8043 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8044 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8045 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8046 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8047 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8048 : AMDGPUISD::BUFFER_LOAD;
8051 return adjustLoadValueType(
Opc, M, DAG,
Ops);
8055 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
8059 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
8060 M->getMemOperand(), DAG);
8064 SDVTList VTList = IsTFE ? DAG.
getVTList(CastVT, MVT::i32, MVT::Other)
8066 SDValue MemNode = getMemIntrinsicNode(
Opc,
DL, VTList,
Ops, CastVT,
8067 M->getMemOperand(), DAG);
8077 EVT VT =
N->getValueType(0);
8101 Exec = AMDGPU::EXEC_LO;
8103 Exec = AMDGPU::EXEC;
8120 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8122 EVT VT =
Op.getValueType();
8127 if (VT != MVT::i32) {
8135 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8144 EVT VT =
N->getValueType(0);
8146 unsigned IID =
N->getConstantOperandVal(0);
8147 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8148 IID == Intrinsic::amdgcn_permlanex16;
8149 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8150 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8151 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8152 IID == Intrinsic::amdgcn_permlane_up ||
8153 IID == Intrinsic::amdgcn_permlane_down ||
8154 IID == Intrinsic::amdgcn_permlane_xor;
8159 unsigned SplitSize = 32;
8160 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8161 ST->hasDPALU_DPP() &&
8169 case Intrinsic::amdgcn_permlane16:
8170 case Intrinsic::amdgcn_permlanex16:
8171 case Intrinsic::amdgcn_update_dpp:
8176 case Intrinsic::amdgcn_writelane:
8177 case Intrinsic::amdgcn_permlane_bcast:
8178 case Intrinsic::amdgcn_permlane_up:
8179 case Intrinsic::amdgcn_permlane_down:
8180 case Intrinsic::amdgcn_permlane_xor:
8183 case Intrinsic::amdgcn_readlane:
8184 case Intrinsic::amdgcn_set_inactive:
8185 case Intrinsic::amdgcn_set_inactive_chain_arg:
8186 case Intrinsic::amdgcn_mov_dpp8:
8189 case Intrinsic::amdgcn_readfirstlane:
8190 case Intrinsic::amdgcn_permlane64:
8200 if (
SDNode *GL =
N->getGluedNode()) {
8202 GL = GL->getOperand(0).getNode();
8212 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8213 IID == Intrinsic::amdgcn_mov_dpp8 ||
8214 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8215 IsPermlaneShuffle) {
8216 Src1 =
N->getOperand(2);
8217 if (IID == Intrinsic::amdgcn_writelane ||
8218 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8220 Src2 =
N->getOperand(3);
8223 if (ValSize == SplitSize) {
8233 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8238 if (IID == Intrinsic::amdgcn_writelane) {
8243 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8245 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8248 if (ValSize % SplitSize != 0)
8252 EVT VT =
N->getValueType(0);
8256 unsigned NumOperands =
N->getNumOperands();
8258 SDNode *GL =
N->getGluedNode();
8263 for (
unsigned i = 0; i != NE; ++i) {
8264 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8266 SDValue Operand =
N->getOperand(j);
8296 if (SplitSize == 32) {
8298 return unrollLaneOp(LaneOp.
getNode());
8304 unsigned SubVecNumElt =
8308 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8309 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8313 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8319 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8320 }
else if (IID == Intrinsic::amdgcn_writelane) {
8324 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8326 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8329 EltIdx += SubVecNumElt;
8343 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8346 if (IID == Intrinsic::amdgcn_writelane)
8349 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8356 EVT VT =
N->getValueType(0);
8374 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8384 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8385 {ShiftedIndex, ValueI32});
8395 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8396 {ValueI32, PoisonVal});
8397 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8398 {ShiftedIndex, PoisonVal});
8401 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8404 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8405 {WWMIndex, WWMValue});
8406 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8407 MVT::i32, {WWMIndex, Swapped});
8409 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8417 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8425 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8435 switch (
N->getOpcode()) {
8452 unsigned IID =
N->getConstantOperandVal(0);
8454 case Intrinsic::amdgcn_wave_reduce_min:
8455 case Intrinsic::amdgcn_wave_reduce_umin:
8456 case Intrinsic::amdgcn_wave_reduce_max:
8457 case Intrinsic::amdgcn_wave_reduce_umax:
8458 case Intrinsic::amdgcn_wave_reduce_add:
8459 case Intrinsic::amdgcn_wave_reduce_sub:
8460 case Intrinsic::amdgcn_wave_reduce_and:
8461 case Intrinsic::amdgcn_wave_reduce_or:
8462 case Intrinsic::amdgcn_wave_reduce_xor: {
8463 EVT VT =
N->getValueType(0);
8467 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8468 IID == Intrinsic::amdgcn_wave_reduce_max ||
8469 IID == Intrinsic::amdgcn_wave_reduce_add ||
8470 IID == Intrinsic::amdgcn_wave_reduce_sub;
8474 N->getOperand(0), ExtSrc,
N->getOperand(2));
8478 case Intrinsic::amdgcn_make_buffer_rsrc:
8479 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8481 case Intrinsic::amdgcn_cvt_pkrtz: {
8486 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8490 case Intrinsic::amdgcn_cvt_pknorm_i16:
8491 case Intrinsic::amdgcn_cvt_pknorm_u16:
8492 case Intrinsic::amdgcn_cvt_pk_i16:
8493 case Intrinsic::amdgcn_cvt_pk_u16: {
8499 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8500 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8501 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8502 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8503 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8504 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8506 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8508 EVT VT =
N->getValueType(0);
8517 case Intrinsic::amdgcn_s_buffer_load: {
8519 EVT VT =
Op.getValueType();
8521 Op.getOperand(1),
Op.getOperand(2),
8522 Op.getOperand(3), DAG));
8525 case Intrinsic::amdgcn_dead: {
8526 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8534 if (
N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8535 N->getValueType(0).isSimple() &&
8536 SBufferLoadDiagnosticVTs[
N->getSimpleValueType(0).SimpleTy])
8541 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8542 Results.push_back(Res.getOperand(
I));
8545 for (
unsigned I = 0;
I <
N->getNumValues(); ++
I)
8546 Results.push_back(Res.getValue(
I));
8555 EVT VT =
N->getValueType(0);
8560 EVT SelectVT = NewVT;
8561 if (NewVT.
bitsLT(MVT::i32)) {
8564 SelectVT = MVT::i32;
8570 if (NewVT != SelectVT)
8576 if (
N->getValueType(0) != MVT::v2f16)
8588 if (
N->getValueType(0) != MVT::v2f16)
8600 if (
N->getValueType(0) != MVT::f16)
8615 if (U.get() !=
Value)
8618 if (U.getUser()->getOpcode() == Opcode)
8624unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8627 case Intrinsic::amdgcn_if:
8628 return AMDGPUISD::IF;
8629 case Intrinsic::amdgcn_else:
8630 return AMDGPUISD::ELSE;
8631 case Intrinsic::amdgcn_loop:
8632 return AMDGPUISD::LOOP;
8633 case Intrinsic::amdgcn_end_cf:
8653 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8677 assert(GVar->isDeclaration() &&
8678 "AS 3 & 13 GVs should be declaration here "
8679 "when object linking is enabled");
8694 SDNode *Intr = BRCOND.getOperand(1).getNode();
8711 Intr =
LHS.getNode();
8719 assert(BR &&
"brcond missing unconditional branch user");
8724 unsigned CFNode = isCFIntrinsic(Intr);
8744 Ops.push_back(Target);
8752 SDValue
Ops[] = {SDValue(Result, 0),
BRCOND.getOperand(0)};
8759 SDValue
Ops[] = {
BR->getOperand(0),
BRCOND.getOperand(2)};
8764 SDValue Chain = SDValue(Result,
Result->getNumValues() - 1);
8767 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8773 SDValue(Result, i - 1), SDValue());
8786 MVT VT =
Op.getSimpleValueType();
8789 if (
Op.getConstantOperandVal(0) != 0)
8793 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8795 if (
Info->isEntryFunction())
8812 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8826 return Op.getValueType().bitsLE(VT)
8834 EVT DstVT =
Op.getValueType();
8841 unsigned Opc =
Op.getOpcode();
8842 SDValue
Flags =
Op.getOperand(1);
8852 bool IsStrict =
Op->isStrictFPOpcode();
8853 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8854 EVT SrcVT = Src.getValueType();
8855 EVT DstVT =
Op.getValueType();
8858 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8861 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8868 if (DstVT == MVT::f16) {
8873 if (!Subtarget->has16BitInsts()) {
8878 if (
Op->getFlags().hasApproximateFuncs()) {
8879 SDValue
Flags =
Op.getOperand(1);
8889 "custom lower FP_ROUND for f16 or bf16");
8890 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8907 EVT VT =
Op.getValueType();
8909 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8910 bool IsIEEEMode =
Info->getMode().IEEE;
8916 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8919 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8920 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8921 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8922 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8928SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8930 EVT VT =
Op.getValueType();
8932 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8933 bool IsIEEEMode =
Info->getMode().IEEE;
8935 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8938 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8939 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8940 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8941 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8948 EVT VT =
Op.getValueType();
8951 SDValue
Exp =
Op.getOperand(IsStrict ? 2 : 1);
8952 EVT ExpVT =
Exp.getValueType();
8953 if (ExpVT == MVT::i16)
8974 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
8981 switch (
Op->getOpcode()) {
9014SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
9015 DAGCombinerInfo &DCI)
const {
9016 EVT OpTy =
Op.getValueType();
9017 SelectionDAG &DAG = DCI.DAG;
9024 SDValue Input =
Op.getOperand(0);
9026 Input = DAG.
getNode(ExtOp,
DL, ExtTy, Input);
9028 SDValue NewVal = DAG.
getNode(
Op.getOpcode(),
DL, ExtTy, Input);
9034 DAGCombinerInfo &DCI)
const {
9035 const unsigned Opc =
Op.getOpcode();
9044 :
Op->getOperand(0).getValueType();
9045 auto &DAG = DCI.DAG;
9048 if (DCI.isBeforeLegalizeOps() ||
9056 LHS =
Op->getOperand(1);
9057 RHS =
Op->getOperand(2);
9059 LHS =
Op->getOperand(0);
9060 RHS =
Op->getOperand(1);
9095 SDValue Mag =
Op.getOperand(0);
9101 SDValue Sign =
Op.getOperand(1);
9104 if (MagVT == SignVT)
9114 SDValue SignShifted =
9125 EVT VT =
Op.getValueType();
9131 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9158 if (
Op->isDivergent())
9161 SDValue Op0 =
Op.getOperand(0);
9162 SDValue Op1 =
Op.getOperand(1);
9171 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9173 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9176 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9178 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9184 EVT VT =
Op.getValueType();
9186 SDValue
LHS =
Op.getOperand(0);
9187 SDValue
RHS =
Op.getOperand(1);
9191 const APInt &
C = RHSC->getAPIntValue();
9193 if (
C.isPowerOf2()) {
9195 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9196 SDValue ShiftAmt = DAG.
getConstant(
C.logBase2(), SL, MVT::i32);
9222 if (
Op->isDivergent()) {
9226 if (Subtarget->hasSMulHi()) {
9237 if (!Subtarget->hasTrapHandler() ||
9239 return lowerTrapEndpgm(
Op, DAG);
9241 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9242 : lowerTrapHsaQueuePtr(
Op, DAG);
9247 SDValue Chain =
Op.getOperand(0);
9248 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9252SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9254 ImplicitParameter Param)
const {
9258 MachinePointerInfo PtrInfo =
9268 SDValue Chain =
Op.getOperand(0);
9275 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9278 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9281 if (UserSGPR == AMDGPU::NoRegister) {
9292 SDValue SGPR01 = DAG.
getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9293 SDValue ToReg = DAG.
getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9298 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9303 SDValue Chain =
Op.getOperand(0);
9307 if (Subtarget->hasPrivEnabledTrap2NopBug())
9308 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9312 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9317 SDValue Chain =
Op.getOperand(0);
9320 if (!Subtarget->hasTrapHandler() ||
9324 "debugtrap handler not supported",
9332 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9342 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9343 SmallSet<Register, 8> SGPRInputRegs;
9345 unsigned NumVals = 0;
9348 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9349 NumVals =
Flags.getNumOperandRegisters();
9353 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9354 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9356 for (
unsigned J = 0; J < NumVals; ++J) {
9357 SDValue Val =
Op.getOperand(
I + 1 + J);
9358 if (
const RegisterSDNode *RegNode =
9367 if (SGPRInputRegs.
empty())
9372 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9376 SDValue SrcVal =
N->getOperand(2);
9380 SDValue ReadFirstLaneID =
9382 SDValue ReadFirstLane =
9384 ReadFirstLaneID, SrcVal);
9388 if (
N->getNumOperands() > 3)
9389 Ops.push_back(
N->getOperand(3));
9395 SDNode *
Next =
nullptr;
9396 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9397 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9398 Next =
N->getOperand(
I).getNode();
9408SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9410 unsigned BaseAS = AS;
9415 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9425SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9429 if (Subtarget->hasApertureRegs()) {
9430 const unsigned ApertureRegNo =
9431 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9432 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9433 !Subtarget->hasGloballyAddressableScratch()) &&
9434 "Cannot use src_private_base with globally addressable scratch!");
9454 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9458 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9460 if (UserSGPR == AMDGPU::NoRegister) {
9471 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9505 const AMDGPUTargetMachine &TM =
9509 unsigned SrcAS = ASC->getSrcAddressSpace();
9510 SDValue Src = ASC->getOperand(0);
9511 unsigned DestAS = ASC->getDestAddressSpace();
9512 bool IsNonNull = ASC->getFlags().hasNonNull();
9514 SDValue FlatNullPtr = DAG.
getConstant(0, SL, MVT::i64);
9523 Subtarget->hasGloballyAddressableScratch()) {
9526 SDValue FlatScratchBaseLo(
9528 AMDGPU::S_MOV_B32, SL, MVT::i32,
9529 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9538 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9552 Subtarget->hasGloballyAddressableScratch()) {
9556 SDValue ThreadID = DAG.
getConstant(0, SL, MVT::i32);
9561 if (Subtarget->isWave64())
9567 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9573 SDValue FlatScratchBase = {
9575 AMDGPU::S_MOV_B64, SL, MVT::i64,
9576 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9578 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9580 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9590 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9601 Op.getValueType() == MVT::i64) {
9602 const SIMachineFunctionInfo *
Info =
9604 if (
Info->get32BitAddressHighBits() == 0)
9613 Src.getValueType() == MVT::i64)
9629 SDValue Vec =
Op.getOperand(0);
9630 SDValue Ins =
Op.getOperand(1);
9631 SDValue Idx =
Op.getOperand(2);
9641 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9646 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9648 MVT::i32, InsNumElts / 2);
9653 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9655 if (InsNumElts == 2) {
9668 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9679 SDValue Vec =
Op.getOperand(0);
9680 SDValue InsVal =
Op.getOperand(1);
9681 SDValue Idx =
Op.getOperand(2);
9691 if (NumElts == 4 && EltSize == 16 && KIdx) {
9702 unsigned Idx = KIdx->getZExtValue();
9703 bool InsertLo = Idx < 2;
9704 SDValue InsHalf = DAG.
getNode(
9707 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9713 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9726 assert(VecSize <= 64 &&
"Expected target vector size to be <= 64 bits");
9734 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9761 EVT ResultVT =
Op.getValueType();
9762 SDValue Vec =
Op.getOperand(0);
9763 SDValue Idx =
Op.getOperand(1);
9774 if (SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9777 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9781 if (VecSize == 128) {
9782 SDValue V2 = DAG.
getBitcast(MVT::v2i64, Vec);
9789 }
else if (VecSize == 256) {
9790 SDValue V2 = DAG.
getBitcast(MVT::v4i64, Vec);
9792 for (
unsigned P = 0;
P < 4; ++
P) {
9798 Parts[0], Parts[1]));
9800 Parts[2], Parts[3]));
9804 SDValue V2 = DAG.
getBitcast(MVT::v8i64, Vec);
9806 for (
unsigned P = 0;
P < 8; ++
P) {
9813 Parts[0], Parts[1], Parts[2], Parts[3]));
9816 Parts[4], Parts[5], Parts[6], Parts[7]));
9822 SDValue IdxMask = DAG.
getConstant(NElem / 2 - 1, SL, IdxVT);
9836 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9846 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9851 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9861 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9866 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9867 !(Mask[Elt + 1] & 1);
9873 EVT ResultVT =
Op.getValueType();
9876 const int NewSrcNumElts = 2;
9878 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9894 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9916 if (ShouldUseConsecutiveExtract &&
9919 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9920 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9931 SDValue SrcOp1 = SrcOp0;
9932 if (Idx0 >= SrcNumElts) {
9937 if (Idx1 >= SrcNumElts) {
9942 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9943 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9951 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9952 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9954 SDValue Result0 = SubVec0;
9955 SDValue Result1 = SubVec0;
9957 if (SubVec0 != SubVec1) {
9958 NewMaskIdx1 += NewSrcNumElts;
9965 {NewMaskIdx0, NewMaskIdx1});
9970 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
9971 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
9972 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
9973 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
9991 SDValue SVal =
Op.getOperand(0);
9992 EVT ResultVT =
Op.getValueType();
9994 SDValue UndefVal = DAG.
getPOISON(SValVT);
10008 EVT VT =
Op.getValueType();
10010 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10011 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10013 SDValue
Lo =
Op.getOperand(0);
10014 SDValue
Hi =
Op.getOperand(1);
10017 if (
Hi.isUndef()) {
10045 for (
unsigned P = 0;
P < NumParts; ++
P) {
10047 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10073 if (!Subtarget->isAmdHsaOS())
10116 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10125 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10133 EVT PtrVT =
Op.getValueType();
10135 const GlobalValue *GV = GSD->
getGlobal();
10148 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10163 return SDValue(DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, GA), 0);
10169 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10172 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10173 if (Subtarget->has64BitLiterals()) {
10182 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10186 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10204 MachinePointerInfo PtrInfo =
10217 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10239 unsigned Offset)
const {
10241 SDValue Param = lowerKernargMemParameter(
10252 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10260 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10268 unsigned NumElts = Elts.
size();
10270 if (NumElts <= 12) {
10274 Type = MVT::v16f32;
10279 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10285 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10294 SDValue Src,
int ExtraElts) {
10295 EVT SrcVT = Src.getValueType();
10305 while (ExtraElts--)
10316 bool Unpacked,
bool IsD16,
int DMaskPop,
10317 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10321 EVT ReqRetVT = ResultTypes[0];
10323 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10324 ? (ReqRetNumElts + 1) / 2
10327 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10330 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10333 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10338 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10342 SDValue(Result, 0), ZeroIdx);
10345 SDValue(Result, 0), ZeroIdx);
10349 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10351 NumDataDwords - MaskPopDwords);
10356 EVT LegalReqRetVT = ReqRetVT;
10358 if (!
Data.getValueType().isInteger())
10360 Data.getValueType().changeTypeToInteger(),
Data);
10381 if (Result->getNumValues() == 1)
10388 SDValue *LWE,
bool &IsTexFail) {
10408 unsigned DimIdx,
unsigned EndIdx,
10409 unsigned NumGradients) {
10411 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10419 if (((
I + 1) >= EndIdx) ||
10420 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10421 I == DimIdx + NumGradients - 1))) {
10453 !
Op.getNode()->hasAnyUseOfValue(0))
10455 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10466 ResultTypes.erase(&ResultTypes[0]);
10468 bool IsD16 =
false;
10469 bool IsG16 =
false;
10470 bool IsA16 =
false;
10472 int NumVDataDwords = 0;
10473 bool AdjustRetType =
false;
10474 bool IsAtomicPacked16Bit =
false;
10477 const unsigned ArgOffset = WithChain ? 2 : 1;
10480 unsigned DMaskLanes = 0;
10482 if (BaseOpcode->
Atomic) {
10483 VData =
Op.getOperand(2);
10485 IsAtomicPacked16Bit =
10486 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10487 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10488 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10489 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10494 "unsupported image atomic data type");
10499 SDValue VData2 =
Op.getOperand(3);
10506 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10508 DMask = Is64Bit ? 0xf : 0x3;
10509 NumVDataDwords = Is64Bit ? 4 : 2;
10511 DMask = Is64Bit ? 0x3 : 0x1;
10512 NumVDataDwords = Is64Bit ? 2 : 1;
10515 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10518 if (BaseOpcode->
Store) {
10519 VData =
Op.getOperand(2);
10523 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10526 "unsupported image store data type");
10528 if (StoreScalarVT == MVT::f16) {
10529 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10533 VData = handleD16VData(VData, DAG,
true);
10536 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10537 }
else if (!BaseOpcode->
NoReturn) {
10542 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10545 "unsupported image load data type");
10547 if (LoadScalarVT == MVT::f16) {
10548 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10556 (!LoadVT.
isVector() && DMaskLanes > 1))
10562 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10563 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10564 NumVDataDwords = (DMaskLanes + 1) / 2;
10566 NumVDataDwords = DMaskLanes;
10568 AdjustRetType =
true;
10572 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10579 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10580 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10582 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10584 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10585 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10589 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10595 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10599 "Bias needs to be converted to 16 bit in A16 mode");
10604 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10608 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10609 "require 16 bit args for both gradients and addresses");
10614 if (!
ST->hasA16()) {
10615 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10616 "support 16 bit addresses\n");
10626 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10628 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10630 IntrOpcode = G16MappingInfo->
G16;
10653 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10671 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10672 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10673 const bool UseNSA =
ST->hasNSAEncoding() &&
10674 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10675 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10676 const bool UsePartialNSA =
10677 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10680 if (UsePartialNSA) {
10682 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10683 }
else if (!UseNSA) {
10694 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10696 Unorm = UnormConst ? True : False;
10702 bool IsTexFail =
false;
10703 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10712 NumVDataDwords = 1;
10714 NumVDataDwords += 1;
10715 AdjustRetType =
true;
10720 if (AdjustRetType) {
10723 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10732 MVT::i32, NumVDataDwords)
10735 ResultTypes[0] = NewVT;
10736 if (ResultTypes.size() == 3) {
10740 ResultTypes.erase(&ResultTypes[1]);
10754 Ops.push_back(VData);
10755 if (UsePartialNSA) {
10757 Ops.push_back(VAddr);
10761 Ops.push_back(VAddr);
10762 SDValue Rsrc =
Op.getOperand(ArgOffset + Intr->
RsrcIndex);
10764 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10766 Ops.push_back(Rsrc);
10768 SDValue Samp =
Op.getOperand(ArgOffset + Intr->
SampIndex);
10771 Ops.push_back(Samp);
10776 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10777 Ops.push_back(Unorm);
10779 Ops.push_back(IsA16 &&
10780 ST->hasFeature(AMDGPU::FeatureR128A16)
10784 Ops.push_back(IsA16 ? True : False);
10786 if (!Subtarget->hasGFX90AInsts())
10787 Ops.push_back(TFE);
10791 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10794 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10795 Ops.push_back(LWE);
10797 Ops.push_back(DimInfo->
DA ? True : False);
10799 Ops.push_back(IsD16 ? True : False);
10801 Ops.push_back(
Op.getOperand(0));
10803 int NumVAddrDwords =
10809 NumVDataDwords, NumVAddrDwords);
10810 }
else if (IsGFX12Plus) {
10812 NumVDataDwords, NumVAddrDwords);
10813 }
else if (IsGFX11Plus) {
10815 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10816 : AMDGPU::MIMGEncGfx11Default,
10817 NumVDataDwords, NumVAddrDwords);
10818 }
else if (IsGFX10Plus) {
10820 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10821 : AMDGPU::MIMGEncGfx10Default,
10822 NumVDataDwords, NumVAddrDwords);
10824 if (Subtarget->hasGFX90AInsts()) {
10826 NumVDataDwords, NumVAddrDwords);
10827 if (Opcode == -1) {
10829 DAG,
Op, OrigResultTypes,
DL,
10830 "requested image instruction is not supported on this GPU");
10833 if (Opcode == -1 &&
10836 NumVDataDwords, NumVAddrDwords);
10839 NumVDataDwords, NumVAddrDwords);
10846 MachineMemOperand *MemRef = MemOp->getMemOperand();
10853 {DAG.
getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)},
DL);
10855 return SDValue(NewNode, 0);
10865 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10866 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10875 bool HasChainResult = MMO !=
nullptr;
10879 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10880 Subtarget->hasScalarSubwordLoads();
10883 MF.
getFunction(),
"unsupported s_buffer_load result type",
10884 DL.getDebugLoc()));
10885 EVT ResultTypes[] = {VT, MVT::Other};
10887 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain,
DL);
10890 if (!HasChainResult) {
10902 if (!
Offset->isDivergent()) {
10903 SDValue
Ops[] = {Chain, Rsrc,
Offset, CachePolicy};
10910 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) -> SDValue {
10912 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10915 if (HasChainResult)
10919 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10920 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10922 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10923 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10928 !Subtarget->hasScalarDwordx3Loads()) {
10932 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10937 if (HasChainResult)
10959 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10960 Subtarget->hasScalarSubwordLoads()) {
10962 SDValue
Load = handleByteShortBufferLoads(DAG, MemVT,
DL,
Ops, MMO);
10964 if (HasChainResult)
10970 unsigned NumLoads = 1;
10976 if (NumElts == 8 || NumElts == 16) {
10977 NumLoads = NumElts / 4;
10981 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
10986 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
10990 for (
unsigned i = 0; i < NumLoads; ++i) {
10993 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
10994 LoadVT, LoadMMO, DAG));
10997 if (NumElts == 8 || NumElts == 16) {
10999 if (HasChainResult) {
11001 for (SDValue
Load : Loads)
11014 if (!Subtarget->hasArchitectedSGPRs())
11019 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11026 unsigned Width)
const {
11028 using namespace AMDGPU::Hwreg;
11030 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11050 SDValue Val =
loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11069 SDValue Src =
Op.getOperand(0);
11070 EVT DstVT =
Op.getValueType();
11072 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11073 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11077 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11079 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11092SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11101 const bool HasE5M3ConversionInsts =
11102 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11103 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11107 EVT DstVT =
Op.getValueType();
11113 SDValue Src =
Op.getOperand(0);
11115 "only the v2f32 vector result is custom lowered");
11121 auto ConvertByte = [&](
unsigned ByteSel) {
11122 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11127 return ConvertByte(0);
11128 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11132 SDValue Src =
Op.getOperand(0);
11133 if (Src.getValueType() != MVT::i32) {
11143 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11144 return lowerFromFP8(
Op, IsBF8, DAG);
11151 SDValue Src =
Op.getOperand(0);
11152 EVT ResVT =
Op.getValueType();
11153 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11154 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11155 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11157 "only the v2i8 vector result is custom lowered");
11161 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11162 SDValue Bytes = DAG.
getNode(
Opc, SL, MVT::i16, Src);
11166 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11167 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11168 : AMDGPUISD::CVT_PK_FP8_F32;
11169 SDValue PoisonI32 = DAG.
getPOISON(MVT::i32);
11176 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11188SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11197 const bool HasE5M3ConversionInsts =
11198 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11199 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11209 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11212 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11215 if (SrcEltVT == MVT::f32)
11216 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11217 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11218 Subtarget->hasF16FP8ConversionInsts()) {
11221 if (!
Op.getValueType().isVector())
11223 return lowerToFP8(
Op, IsBF8,
false, DAG);
11231 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11233 EVT VT =
Op.getValueType();
11235 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11239 switch (IntrinsicID) {
11240 case Intrinsic::amdgcn_wave_reduce_min:
11241 case Intrinsic::amdgcn_wave_reduce_umin:
11242 case Intrinsic::amdgcn_wave_reduce_fmin:
11243 case Intrinsic::amdgcn_wave_reduce_max:
11244 case Intrinsic::amdgcn_wave_reduce_umax:
11245 case Intrinsic::amdgcn_wave_reduce_fmax:
11246 case Intrinsic::amdgcn_wave_reduce_add:
11247 case Intrinsic::amdgcn_wave_reduce_fadd:
11248 case Intrinsic::amdgcn_wave_reduce_sub:
11249 case Intrinsic::amdgcn_wave_reduce_fsub:
11250 case Intrinsic::amdgcn_wave_reduce_and:
11251 case Intrinsic::amdgcn_wave_reduce_or:
11252 case Intrinsic::amdgcn_wave_reduce_xor: {
11253 EVT SrcVT =
Op.getOperand(1).getValueType();
11256 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11257 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11258 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11259 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11263 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11264 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11265 SDValue ExtendedSrc = DAG.
getNode(ExtOpc,
DL, ExtType,
Op.getOperand(1));
11266 SDValue Strategy =
Op.getOperand(2);
11268 Op.getOperand(0), ExtendedSrc, Strategy);
11277 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11280 return getPreloadedValue(DAG, *MFI, VT,
11283 case Intrinsic::amdgcn_dispatch_ptr:
11284 case Intrinsic::amdgcn_queue_ptr: {
11285 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11287 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11288 DL.getDebugLoc()));
11292 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11295 return getPreloadedValue(DAG, *MFI, VT, RegID);
11297 case Intrinsic::amdgcn_implicitarg_ptr: {
11299 return getImplicitArgPtr(DAG,
DL);
11300 return getPreloadedValue(DAG, *MFI, VT,
11303 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11309 return getPreloadedValue(DAG, *MFI, VT,
11312 case Intrinsic::amdgcn_dispatch_id: {
11315 case Intrinsic::amdgcn_rcp:
11316 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11317 case Intrinsic::amdgcn_rsq:
11318 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11319 case Intrinsic::amdgcn_rsq_legacy:
11323 case Intrinsic::amdgcn_rcp_legacy:
11326 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11327 case Intrinsic::amdgcn_fma_legacy:
11328 case Intrinsic::amdgcn_sudot4:
11329 case Intrinsic::amdgcn_sudot8:
11330 case Intrinsic::amdgcn_tanh:
11332 case Intrinsic::amdgcn_rsq_clamp: {
11334 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11340 SDValue Rsq = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11346 case Intrinsic::r600_read_ngroups_x:
11347 if (Subtarget->isAmdHsaOS())
11350 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11353 case Intrinsic::r600_read_ngroups_y:
11354 if (Subtarget->isAmdHsaOS())
11357 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11360 case Intrinsic::r600_read_ngroups_z:
11361 if (Subtarget->isAmdHsaOS())
11364 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11367 case Intrinsic::r600_read_local_size_x:
11368 if (Subtarget->isAmdHsaOS())
11371 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11373 case Intrinsic::r600_read_local_size_y:
11374 if (Subtarget->isAmdHsaOS())
11377 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11379 case Intrinsic::r600_read_local_size_z:
11380 if (Subtarget->isAmdHsaOS())
11383 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11385 case Intrinsic::amdgcn_workgroup_id_x:
11386 return lowerWorkGroupId(DAG, *MFI, VT,
11390 case Intrinsic::amdgcn_workgroup_id_y:
11391 return lowerWorkGroupId(DAG, *MFI, VT,
11395 case Intrinsic::amdgcn_workgroup_id_z:
11396 return lowerWorkGroupId(DAG, *MFI, VT,
11400 case Intrinsic::amdgcn_cluster_id_x:
11401 return Subtarget->hasClusters()
11402 ? getPreloadedValue(DAG, *MFI, VT,
11404 : DAG.getPOISON(VT);
11405 case Intrinsic::amdgcn_cluster_id_y:
11406 return Subtarget->hasClusters()
11407 ? getPreloadedValue(DAG, *MFI, VT,
11410 case Intrinsic::amdgcn_cluster_id_z:
11411 return Subtarget->hasClusters()
11412 ? getPreloadedValue(DAG, *MFI, VT,
11415 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11416 return Subtarget->hasClusters()
11417 ? getPreloadedValue(
11421 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11422 return Subtarget->hasClusters()
11423 ? getPreloadedValue(
11427 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11428 return Subtarget->hasClusters()
11429 ? getPreloadedValue(
11433 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11434 return Subtarget->hasClusters()
11437 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11438 return Subtarget->hasClusters()
11439 ? getPreloadedValue(
11443 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11444 return Subtarget->hasClusters()
11445 ? getPreloadedValue(
11449 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11450 return Subtarget->hasClusters()
11451 ? getPreloadedValue(
11455 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11456 return Subtarget->hasClusters()
11457 ? getPreloadedValue(
11461 case Intrinsic::amdgcn_wave_id:
11462 return lowerWaveID(DAG,
Op);
11463 case Intrinsic::amdgcn_lds_kernel_id: {
11465 return getLDSKernelId(DAG,
DL);
11466 return getPreloadedValue(DAG, *MFI, VT,
11469 case Intrinsic::amdgcn_workitem_id_x:
11470 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11471 case Intrinsic::amdgcn_workitem_id_y:
11472 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11473 case Intrinsic::amdgcn_workitem_id_z:
11474 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11475 case Intrinsic::amdgcn_wavefrontsize:
11477 SDLoc(
Op), MVT::i32);
11478 case Intrinsic::amdgcn_s_buffer_load: {
11479 unsigned CPol =
Op.getConstantOperandVal(3);
11487 Op.getOperand(2),
Op.getOperand(3), DAG);
11489 case Intrinsic::amdgcn_fdiv_fast:
11490 return lowerFDIV_FAST(
Op, DAG);
11491 case Intrinsic::amdgcn_sin:
11492 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11494 case Intrinsic::amdgcn_cos:
11495 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11497 case Intrinsic::amdgcn_mul_u24:
11498 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11500 case Intrinsic::amdgcn_mul_i24:
11501 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11504 case Intrinsic::amdgcn_log_clamp: {
11510 case Intrinsic::amdgcn_fract:
11511 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11513 case Intrinsic::amdgcn_class: {
11514 SDValue Src =
Op.getOperand(1);
11515 EVT SrcVT = Src.getValueType();
11516 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11517 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11521 "llvm.amdgcn.class only supports f16, f32, and f64",
11522 DL.getDebugLoc()));
11525 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11527 case Intrinsic::amdgcn_div_fmas:
11528 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11529 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11531 case Intrinsic::amdgcn_div_fixup:
11532 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11533 Op.getOperand(2),
Op.getOperand(3));
11535 case Intrinsic::amdgcn_div_scale: {
11540 SDValue Numerator =
Op.getOperand(1);
11541 SDValue Denominator =
Op.getOperand(2);
11548 SDValue Src0 =
Param->isAllOnes() ? Numerator : Denominator;
11550 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11551 Denominator, Numerator);
11553 case Intrinsic::amdgcn_ballot:
11555 case Intrinsic::amdgcn_fmed3:
11556 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11557 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11558 case Intrinsic::amdgcn_fdot2:
11559 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11560 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11561 case Intrinsic::amdgcn_fmul_legacy:
11562 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11564 case Intrinsic::amdgcn_sbfe:
11565 case Intrinsic::amdgcn_ubfe:
11567 case Intrinsic::amdgcn_cvt_pkrtz:
11568 case Intrinsic::amdgcn_cvt_pknorm_i16:
11569 case Intrinsic::amdgcn_cvt_pknorm_u16:
11570 case Intrinsic::amdgcn_cvt_pk_i16:
11571 case Intrinsic::amdgcn_cvt_pk_u16: {
11573 EVT VT =
Op.getValueType();
11576 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11577 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11578 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11579 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11580 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11581 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11582 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11583 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11585 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11588 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11591 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11594 case Intrinsic::amdgcn_fmad_ftz:
11595 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11596 Op.getOperand(2),
Op.getOperand(3));
11598 case Intrinsic::amdgcn_if_break:
11600 Op->getOperand(1),
Op->getOperand(2)),
11603 case Intrinsic::amdgcn_groupstaticsize: {
11609 const GlobalValue *GV =
11615 case Intrinsic::amdgcn_is_shared:
11616 case Intrinsic::amdgcn_is_private: {
11623 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11627 Subtarget->hasGloballyAddressableScratch()) {
11628 SDValue FlatScratchBaseHi(
11630 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11631 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11640 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11643 case Intrinsic::amdgcn_perm:
11644 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11645 Op.getOperand(2),
Op.getOperand(3));
11646 case Intrinsic::amdgcn_reloc_constant: {
11656 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11657 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11658 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11659 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11660 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11661 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11662 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11663 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11664 if (
Op.getOperand(4).getValueType() == MVT::i32)
11670 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11671 Op.getOperand(3), IndexKeyi32);
11673 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11674 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11675 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11676 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11677 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11678 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11679 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11680 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11681 if (
Op.getOperand(4).getValueType() == MVT::i64)
11686 Op.getOperand(4).getValueType() == MVT::v2i32
11690 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11691 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11692 Op.getOperand(6)});
11694 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11695 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11696 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11697 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11698 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11699 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11700 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11703 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11708 Op.getOperand(6).getValueType().isVector()
11712 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11713 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11714 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11715 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11716 Args.push_back(
Op.getOperand(9));
11719 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11720 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11721 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11722 if (
Op.getOperand(6).getValueType() == MVT::i32)
11728 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11729 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11730 IndexKeyi32, Op.getOperand(7)});
11732 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11733 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11734 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11735 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11736 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11737 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11741 "invalid matrix and scale format combination in wmma call");
11747 case Intrinsic::amdgcn_readlane:
11748 case Intrinsic::amdgcn_readfirstlane:
11749 case Intrinsic::amdgcn_writelane:
11750 case Intrinsic::amdgcn_permlane16:
11751 case Intrinsic::amdgcn_permlanex16:
11752 case Intrinsic::amdgcn_permlane64:
11753 case Intrinsic::amdgcn_set_inactive:
11754 case Intrinsic::amdgcn_set_inactive_chain_arg:
11755 case Intrinsic::amdgcn_mov_dpp8:
11756 case Intrinsic::amdgcn_update_dpp:
11757 case Intrinsic::amdgcn_permlane_bcast:
11758 case Intrinsic::amdgcn_permlane_up:
11759 case Intrinsic::amdgcn_permlane_down:
11760 case Intrinsic::amdgcn_permlane_xor:
11762 case Intrinsic::amdgcn_dead: {
11764 for (
const EVT ValTy :
Op.getNode()->values())
11768 case Intrinsic::amdgcn_wave_shuffle:
11771 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11773 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11783 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(SOffset))
11784 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11790 unsigned NewOpcode)
const {
11793 SDValue VData =
Op.getOperand(2);
11797 "unsupported buffer atomic data type");
11799 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11800 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11818 M->getMemOperand());
11823 unsigned NewOpcode)
const {
11826 SDValue VData =
Op.getOperand(2);
11830 "unsupported buffer atomic data type");
11832 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11833 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11851 M->getMemOperand());
11858 unsigned NumOperands =
N->getNumOperands();
11859 if (
N->getOperand(NumOperands - 1) == Zero)
11862 Ops[NumOperands - 1] = Zero;
11868 unsigned IntrID =
Op.getConstantOperandVal(1);
11872 case Intrinsic::amdgcn_cluster_load_b32:
11873 case Intrinsic::amdgcn_cluster_load_b64:
11874 case Intrinsic::amdgcn_cluster_load_b128: {
11875 if (Subtarget->hasGFX1250_STRICT())
11879 case Intrinsic::amdgcn_ds_ordered_add:
11880 case Intrinsic::amdgcn_ds_ordered_swap: {
11882 SDValue Chain =
M->getOperand(0);
11883 SDValue
M0 =
M->getOperand(2);
11884 SDValue
Value =
M->getOperand(3);
11885 unsigned IndexOperand =
M->getConstantOperandVal(7);
11886 unsigned WaveRelease =
M->getConstantOperandVal(8);
11887 unsigned WaveDone =
M->getConstantOperandVal(9);
11889 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11890 IndexOperand &= ~0x3f;
11891 unsigned CountDw = 0;
11894 CountDw = (IndexOperand >> 24) & 0xf;
11895 IndexOperand &= ~(0xf << 24);
11897 if (CountDw < 1 || CountDw > 4) {
11900 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11901 DL.getDebugLoc()));
11906 if (IndexOperand) {
11909 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11912 if (WaveDone && !WaveRelease) {
11916 Fn,
"ds_ordered_count: wave_done requires wave_release",
11917 DL.getDebugLoc()));
11920 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11921 unsigned ShaderType =
11923 unsigned Offset0 = OrderedCountIndex << 2;
11924 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11927 Offset1 |= (CountDw - 1) << 6;
11930 Offset1 |= ShaderType << 2;
11932 unsigned Offset = Offset0 | (Offset1 << 8);
11939 M->getVTList(),
Ops,
M->getMemoryVT(),
11940 M->getMemOperand());
11942 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11943 unsigned CPol =
Op.getConstantOperandVal(4);
11950 return lowerSBuffer(
11951 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
11952 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
11953 Op.getOperand(4), DAG,
M->getMemOperand());
11955 case Intrinsic::amdgcn_raw_buffer_load:
11956 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11957 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11958 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11959 case Intrinsic::amdgcn_raw_buffer_load_format:
11960 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11961 const bool IsFormat =
11962 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11963 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11965 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11966 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
11980 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
11982 case Intrinsic::amdgcn_struct_buffer_load:
11983 case Intrinsic::amdgcn_struct_ptr_buffer_load:
11984 case Intrinsic::amdgcn_struct_buffer_load_format:
11985 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
11986 case Intrinsic::amdgcn_struct_atomic_buffer_load:
11987 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
11988 const bool IsFormat =
11989 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
11990 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
11992 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11993 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12008 case Intrinsic::amdgcn_raw_tbuffer_load:
12009 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12011 EVT LoadVT =
Op.getValueType();
12012 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12013 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12029 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12031 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12032 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12035 case Intrinsic::amdgcn_struct_tbuffer_load:
12036 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12038 EVT LoadVT =
Op.getValueType();
12039 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12040 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12056 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12058 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12059 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12062 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12063 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12064 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12065 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12066 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12067 return lowerStructBufferAtomicIntrin(
Op, DAG,
12068 AMDGPUISD::BUFFER_ATOMIC_FADD);
12069 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12070 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12071 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12072 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12073 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12074 return lowerStructBufferAtomicIntrin(
Op, DAG,
12075 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12076 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12077 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12078 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12079 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12080 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12081 return lowerStructBufferAtomicIntrin(
Op, DAG,
12082 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12083 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12084 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12085 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12086 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12087 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12088 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12089 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12090 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12091 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12092 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12093 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12094 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12095 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12096 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12097 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12098 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12099 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12100 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12101 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12102 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12103 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12104 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12105 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12106 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12107 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12108 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12109 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12110 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12111 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12112 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12113 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12114 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12115 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12116 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12117 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12118 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12119 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12120 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12121 return lowerStructBufferAtomicIntrin(
Op, DAG,
12122 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12123 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12124 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12125 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12126 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12127 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12128 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12129 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12130 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12131 return lowerStructBufferAtomicIntrin(
Op, DAG,
12132 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12133 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12134 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12135 return lowerStructBufferAtomicIntrin(
Op, DAG,
12136 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12137 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12138 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12139 return lowerStructBufferAtomicIntrin(
Op, DAG,
12140 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12141 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12142 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12143 return lowerStructBufferAtomicIntrin(
Op, DAG,
12144 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12145 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12146 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12147 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12148 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12149 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12150 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12151 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12152 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12153 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12154 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12155 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12156 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12157 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12158 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12159 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12160 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12161 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12162 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12163 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12164 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12165 return lowerStructBufferAtomicIntrin(
Op, DAG,
12166 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12167 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12168 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12169 return lowerRawBufferAtomicIntrin(
Op, DAG,
12170 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12171 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12172 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12173 return lowerStructBufferAtomicIntrin(
Op, DAG,
12174 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12175 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12176 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12177 SDValue Src =
Op.getOperand(2);
12178 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12181 "unsupported buffer atomic data type");
12183 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12184 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12198 EVT VT =
Op.getValueType();
12202 Op->getVTList(),
Ops, VT,
12203 M->getMemOperand());
12205 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12206 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12207 SDValue Src =
Op.getOperand(2);
12208 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12211 "unsupported buffer atomic data type");
12213 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12214 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12228 EVT VT =
Op.getValueType();
12232 Op->getVTList(),
Ops, VT,
12233 M->getMemOperand());
12235 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12236 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12238 SDValue NodePtr =
M->getOperand(2);
12239 SDValue RayExtent =
M->getOperand(3);
12240 SDValue InstanceMask =
M->getOperand(4);
12241 SDValue RayOrigin =
M->getOperand(5);
12242 SDValue RayDir =
M->getOperand(6);
12243 SDValue
Offsets =
M->getOperand(7);
12244 SDValue TDescr =
M->getOperand(8);
12249 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12250 const unsigned NumVDataDwords = 10;
12251 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12253 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12254 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12255 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12259 Ops.push_back(NodePtr);
12262 {DAG.getBitcast(MVT::i32, RayExtent),
12263 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12264 Ops.push_back(RayOrigin);
12265 Ops.push_back(RayDir);
12266 Ops.push_back(Offsets);
12267 Ops.push_back(TDescr);
12268 Ops.push_back(
M->getChain());
12271 MachineMemOperand *MemRef =
M->getMemOperand();
12273 return SDValue(NewNode, 0);
12275 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12277 SDValue NodePtr =
M->getOperand(2);
12278 SDValue RayExtent =
M->getOperand(3);
12279 SDValue RayOrigin =
M->getOperand(4);
12280 SDValue RayDir =
M->getOperand(5);
12281 SDValue RayInvDir =
M->getOperand(6);
12282 SDValue TDescr =
M->getOperand(7);
12294 const unsigned NumVDataDwords = 4;
12295 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12296 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12297 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12300 const unsigned BaseOpcodes[2][2] = {
12301 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12302 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12303 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12307 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12308 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12309 : AMDGPU::MIMGEncGfx10NSA,
12310 NumVDataDwords, NumVAddrDwords);
12314 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12315 : AMDGPU::MIMGEncGfx10Default,
12316 NumVDataDwords, NumVAddrDwords);
12322 auto packLanes = [&DAG, &
Ops, &
DL](SDValue
Op,
bool IsAligned) {
12325 if (Lanes[0].getValueSizeInBits() == 32) {
12326 for (
unsigned I = 0;
I < 3; ++
I)
12333 Ops.push_back(Lanes[2]);
12335 SDValue Elt0 =
Ops.pop_back_val();
12345 if (UseNSA && IsGFX11Plus) {
12346 Ops.push_back(NodePtr);
12348 Ops.push_back(RayOrigin);
12353 for (
unsigned I = 0;
I < 3; ++
I) {
12356 {DirLanes[I], InvDirLanes[I]})));
12360 Ops.push_back(RayDir);
12361 Ops.push_back(RayInvDir);
12368 Ops.push_back(NodePtr);
12371 packLanes(RayOrigin,
true);
12372 packLanes(RayDir,
true);
12373 packLanes(RayInvDir,
false);
12378 if (NumVAddrDwords > 12) {
12383 SDValue MergedOps =
12386 Ops.push_back(MergedOps);
12389 Ops.push_back(TDescr);
12391 Ops.push_back(
M->getChain());
12394 MachineMemOperand *MemRef =
M->getMemOperand();
12396 return SDValue(NewNode, 0);
12398 case Intrinsic::amdgcn_global_atomic_fmin_num:
12399 case Intrinsic::amdgcn_global_atomic_fmax_num:
12400 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12401 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12408 unsigned Opcode = 0;
12410 case Intrinsic::amdgcn_global_atomic_fmin_num:
12411 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12415 case Intrinsic::amdgcn_global_atomic_fmax_num:
12416 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12423 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12424 Ops,
M->getMemOperand());
12426 case Intrinsic::amdgcn_s_alloc_vgpr: {
12431 SDValue ReadFirstLaneID =
12434 ReadFirstLaneID, NumVGPRs);
12437 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12439 case Intrinsic::amdgcn_s_get_barrier_state:
12440 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12441 SDValue Chain =
Op->getOperand(0);
12447 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12448 BarID = BarID & 0x3F;
12449 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12452 Ops.push_back(Chain);
12454 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12455 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12464 return SDValue(NewMI, 0);
12466 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12467 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12468 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12470 SDValue Chain =
Op->getOperand(0);
12471 SDValue Ptr =
Op->getOperand(2);
12472 EVT VT =
Op->getValueType(0);
12476 case Intrinsic::amdgcn_av_load_b128: {
12478 SDValue Chain =
Op->getOperand(0);
12479 SDValue Ptr =
Op->getOperand(2);
12480 EVT VT =
Op->getValueType(0);
12487 case Intrinsic::amdgcn_flat_load_monitor_b32:
12488 case Intrinsic::amdgcn_flat_load_monitor_b64:
12489 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12491 SDValue Chain =
Op->getOperand(0);
12492 SDValue Ptr =
Op->getOperand(2);
12494 Op->getVTList(), {Chain, Ptr},
12497 case Intrinsic::amdgcn_global_load_monitor_b32:
12498 case Intrinsic::amdgcn_global_load_monitor_b64:
12499 case Intrinsic::amdgcn_global_load_monitor_b128: {
12501 SDValue Chain =
Op->getOperand(0);
12502 SDValue Ptr =
Op->getOperand(2);
12504 Op->getVTList(), {Chain, Ptr},
12509 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12511 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12519SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12526 EVT VT = VTList.
VTs[0];
12529 bool IsTFE = VTList.
NumVTs == 3;
12532 unsigned NumOpDWords = NumValueDWords + 1;
12534 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12535 MachineMemOperand *OpDWordsMMO =
12537 SDValue
Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12538 OpDWordsVT, OpDWordsMMO, DAG);
12543 if (!Subtarget->hasDwordx3LoadStores() &&
12544 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12548 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12550 WidenedMemVT, WidenedMMO);
12560 bool ImageStore)
const {
12570 if (Subtarget->hasUnpackedD16VMem()) {
12584 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12595 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12601 if ((NumElements % 2) == 1) {
12603 unsigned I = Elts.
size() / 2;
12619 if (NumElements == 3) {
12638 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12639 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12640 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12641 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12642 case Intrinsic::amdgcn_load_async_to_lds:
12643 case Intrinsic::amdgcn_global_load_async_lds:
12652 SDValue Chain =
Op.getOperand(0);
12653 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12655 switch (IntrinsicID) {
12656 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12657 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12658 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12659 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12660 if (Subtarget->hasGFX1250_STRICT())
12664 case Intrinsic::amdgcn_exp_compr: {
12665 SDValue Src0 =
Op.getOperand(4);
12666 SDValue Src1 =
Op.getOperand(5);
12673 const SDValue
Ops[] = {
12685 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12689 case Intrinsic::amdgcn_struct_tbuffer_store:
12690 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12691 SDValue VData =
Op.getOperand(2);
12694 VData = handleD16VData(VData, DAG);
12695 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12696 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12710 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12711 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12714 M->getMemoryVT(),
M->getMemOperand());
12717 case Intrinsic::amdgcn_raw_tbuffer_store:
12718 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12719 SDValue VData =
Op.getOperand(2);
12722 VData = handleD16VData(VData, DAG);
12723 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12724 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12738 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12739 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12742 M->getMemoryVT(),
M->getMemOperand());
12745 case Intrinsic::amdgcn_raw_buffer_store:
12746 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12747 case Intrinsic::amdgcn_raw_buffer_store_format:
12748 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12749 const bool IsFormat =
12750 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12751 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12753 SDValue VData =
Op.getOperand(2);
12761 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12766 VData = handleD16VData(VData, DAG);
12776 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12777 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12791 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12792 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12797 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12800 M->getMemoryVT(),
M->getMemOperand());
12803 case Intrinsic::amdgcn_struct_buffer_store:
12804 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12805 case Intrinsic::amdgcn_struct_buffer_store_format:
12806 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12807 const bool IsFormat =
12808 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12809 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12811 SDValue VData =
Op.getOperand(2);
12819 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12824 VData = handleD16VData(VData, DAG);
12834 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12835 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12849 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12850 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12854 EVT VDataType = VData.getValueType().getScalarType();
12856 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12859 M->getMemoryVT(),
M->getMemOperand());
12861 case Intrinsic::amdgcn_raw_buffer_load_lds:
12862 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12863 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12864 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12865 case Intrinsic::amdgcn_struct_buffer_load_lds:
12866 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12867 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12868 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12871 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12872 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12873 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12874 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12875 unsigned OpOffset = HasVIndex ? 1 : 0;
12876 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12878 unsigned Size =
Op->getConstantOperandVal(4);
12884 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12885 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12886 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12887 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12890 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12891 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12892 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12893 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12896 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12897 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12898 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12899 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12902 if (!Subtarget->hasLDSLoadB96_B128())
12904 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12905 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12906 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12907 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12910 if (!Subtarget->hasLDSLoadB96_B128())
12912 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12913 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12914 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12915 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12919 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
12923 if (HasVIndex && HasVOffset)
12927 else if (HasVIndex)
12928 Ops.push_back(
Op.getOperand(5));
12929 else if (HasVOffset)
12930 Ops.push_back(VOffset);
12932 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12933 Ops.push_back(Rsrc);
12934 Ops.push_back(
Op.getOperand(6 + OpOffset));
12935 Ops.push_back(
Op.getOperand(7 + OpOffset));
12937 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
12955 return SDValue(
Load, 0);
12960 case Intrinsic::amdgcn_load_to_lds:
12961 case Intrinsic::amdgcn_load_async_to_lds:
12962 case Intrinsic::amdgcn_global_load_lds:
12963 case Intrinsic::amdgcn_global_load_async_lds: {
12964 if (!Subtarget->hasVMemToLDSLoad())
12968 unsigned Size =
Op->getConstantOperandVal(4);
12973 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
12976 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
12979 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
12982 if (!Subtarget->hasLDSLoadB96_B128())
12984 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
12987 if (!Subtarget->hasLDSLoadB96_B128())
12989 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
12993 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
12997 SDValue Addr =
Op.getOperand(2);
13005 if (
LHS->isDivergent())
13009 RHS.getOperand(0).getValueType() == MVT::i32) {
13012 VOffset =
RHS.getOperand(0);
13016 Ops.push_back(Addr);
13024 Ops.push_back(VOffset);
13027 Ops.push_back(
Op.getOperand(5));
13029 unsigned Aux =
Op.getConstantOperandVal(6);
13042 return SDValue(
Load, 0);
13044 case Intrinsic::amdgcn_end_cf:
13046 Op->getOperand(2), Chain),
13048 case Intrinsic::amdgcn_s_barrier_signal_var: {
13053 SDValue CntOp =
Op->getOperand(3);
13055 if (CntC && CntC->isZero()) {
13056 SDValue Chain =
Op->getOperand(0);
13057 SDValue BarOp =
Op->getOperand(2);
13060 std::optional<uint64_t> BarVal;
13062 BarVal =
C->getZExtValue();
13066 BarVal = *Addr + GA->getOffset();
13069 unsigned BarID = *BarVal & 0x3F;
13071 Ops.push_back(Chain);
13073 Op->getVTList(),
Ops);
13074 return SDValue(NewMI, 0);
13079 case Intrinsic::amdgcn_s_barrier_init: {
13081 SDValue Chain =
Op->getOperand(0);
13083 SDValue BarOp =
Op->getOperand(2);
13084 SDValue CntOp =
Op->getOperand(3);
13086 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13087 ? AMDGPU::S_BARRIER_INIT_M0
13088 : AMDGPU::S_BARRIER_SIGNAL_M0;
13096 constexpr unsigned ShAmt = 16;
13105 return SDValue(NewMI, 0);
13107 case Intrinsic::amdgcn_s_wakeup_barrier: {
13108 if (!Subtarget->hasSWakeupBarrier())
13112 case Intrinsic::amdgcn_s_barrier_join: {
13114 SDValue Chain =
Op->getOperand(0);
13116 SDValue BarOp =
Op->getOperand(2);
13121 switch (IntrinsicID) {
13124 case Intrinsic::amdgcn_s_barrier_join:
13125 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13127 case Intrinsic::amdgcn_s_wakeup_barrier:
13128 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13132 unsigned BarID = BarVal & 0x3F;
13135 Ops.push_back(Chain);
13137 switch (IntrinsicID) {
13140 case Intrinsic::amdgcn_s_barrier_join:
13141 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13143 case Intrinsic::amdgcn_s_wakeup_barrier:
13144 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13154 return SDValue(NewMI, 0);
13156 case Intrinsic::amdgcn_s_prefetch_data:
13157 case Intrinsic::amdgcn_s_prefetch_inst: {
13160 return Op.getOperand(0);
13163 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13165 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13172 Op->getVTList(),
Ops,
M->getMemoryVT(),
13173 M->getMemOperand());
13175 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13176 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13177 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13179 SDValue Chain =
Op->getOperand(0);
13180 SDValue Ptr =
Op->getOperand(2);
13181 SDValue Val =
Op->getOperand(3);
13185 case Intrinsic::amdgcn_av_store_b128: {
13187 SDValue Chain =
Op->getOperand(0);
13188 SDValue Ptr =
Op->getOperand(2);
13189 SDValue Val =
Op->getOperand(3);
13193 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13195 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13211 return PtrVT == MVT::i64;
13225std::pair<SDValue, SDValue>
13238 bool CheckNUW = Subtarget->hasGFX1250Insts();
13255 unsigned Overflow = ImmOffset & ~MaxImm;
13256 ImmOffset -= Overflow;
13257 if ((int32_t)Overflow < 0) {
13258 Overflow += ImmOffset;
13263 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13267 SDValue
Ops[] = {N0, OverflowVal};
13276 return {N0, SDValue(C1, 0)};
13282void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13284 Align Alignment)
const {
13286 SDLoc
DL(CombinedOffset);
13288 uint32_t
Imm =
C->getZExtValue();
13289 uint32_t SOffset, ImmOffset;
13290 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13301 bool CheckNUW = Subtarget->hasGFX1250Insts();
13304 uint32_t SOffset, ImmOffset;
13307 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13315 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13324SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13327 return MaybePointer;
13329 SDValue Rsrc = DAG.
getBitcast(MVT::v4i32, MaybePointer);
13340 SDValue Stride =
Op->getOperand(2);
13341 SDValue NumRecords =
Op->getOperand(3);
13342 SDValue
Flags =
Op->getOperand(4);
13347 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13350 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13355 SDValue NumRecordsLHS =
13363 SDValue NumRecordsRHS =
13366 SDValue ShiftedStride =
13369 SDValue ExtShiftedStrideVec =
13371 SDValue ExtShiftedStride =
13373 SDValue ShiftedFlags =
13376 SDValue ExtShiftedFlagsVec =
13378 SDValue ExtShiftedFlags =
13380 SDValue CombinedFields =
13381 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13383 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13388 auto [LowHalf, HighHalf] =
13389 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13392 SDValue ShiftedStride =
13395 SDValue NewHighHalf =
13399 NumRecords, Flags);
13411 bool IsTFE)
const {
13416 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13417 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13420 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13421 SDValue
Op = getMemIntrinsicNode(
Opc,
DL, VTs,
Ops, MVT::v2i32, OpMMO, DAG);
13432 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13433 : AMDGPUISD::BUFFER_LOAD_USHORT;
13435 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13436 SDValue BufferLoad =
13449 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13453 Ops[1] = BufferStoreExt;
13454 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13455 : AMDGPUISD::BUFFER_STORE_SHORT;
13458 M->getMemOperand());
13483 DAGCombinerInfo &DCI)
const {
13484 SelectionDAG &DAG = DCI.DAG;
13485 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13489 unsigned AS = Ld->getAddressSpace();
13498 EVT MemVT = Ld->getMemoryVT();
13499 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13506 "unexpected vector extload");
13509 SDValue Ptr = Ld->getBasePtr();
13510 SDValue NewLoad = DAG.
getLoad(
13512 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13513 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13518 "unexpected fp extload");
13522 SDValue Cvt = NewLoad;
13533 EVT VT = Ld->getValueType(0);
13536 DCI.AddToWorklist(Cvt.
getNode());
13541 DCI.AddToWorklist(Cvt.
getNode());
13552 if (Info.isEntryFunction())
13553 return Info.getUserSGPRInfo().hasFlatScratchInit();
13561 EVT MemVT =
Load->getMemoryVT();
13562 MachineMemOperand *MMO =
Load->getMemOperand();
13571 SDValue Chain =
Load->getChain();
13574 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13602 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13603 "Custom lowering for non-i32 vectors hasn't been implemented.");
13606 unsigned AS =
Load->getAddressSpace();
13607 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13614 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13618 !Subtarget->hasMultiDwordFlatScratchAddressing())
13628 Subtarget->getScalarizeGlobalBehavior() &&
Load->isSimple() &&
13631 Alignment >=
Align(4) && NumElements < 32) {
13633 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13645 if (NumElements > 4)
13648 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13658 switch (Subtarget->getMaxPrivateElementSize()) {
13664 if (NumElements > 2)
13669 if (NumElements > 4)
13672 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13681 auto Flags =
Load->getMemOperand()->getFlags();
13683 Load->getAlign(), Flags, &
Fast) &&
13692 MemVT, *
Load->getMemOperand())) {
13701 EVT VT =
Op.getValueType();
13736 SDValue
LHS =
Op.getOperand(0);
13737 SDValue
RHS =
Op.getOperand(1);
13738 EVT VT =
Op.getValueType();
13739 const SDNodeFlags
Flags =
Op->getFlags();
13741 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13747 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13750 if (CLHS->isOne()) {
13763 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13767 if (CLHS->isMinusOne()) {
13770 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13776 if (!AllowInaccurateRcp &&
13777 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13782 SDValue Recip = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13789 SDValue
X =
Op.getOperand(0);
13790 SDValue
Y =
Op.getOperand(1);
13791 EVT VT =
Op.getValueType();
13792 const SDNodeFlags
Flags =
Op->getFlags();
13794 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13795 if (!AllowInaccurateDiv)
13808 SDValue
R = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
Y);
13819 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13831 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13841 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13845 return DAG.
getNode(Opcode, SL, VTList,
13854 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13864 Opcode = AMDGPUISD::FMA_W_CHAIN;
13868 return DAG.
getNode(Opcode, SL, VTList,
13874 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13875 return FastLowered;
13878 EVT VT =
Op.getValueType();
13879 SDValue
LHS =
Op.getOperand(0);
13880 SDValue
RHS =
Op.getOperand(1);
13885 if (VT == MVT::bf16) {
13908 unsigned FMADOpCode =
13912 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
13915 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13917 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
13918 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13928 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
13934 SDNodeFlags
Flags =
Op->getFlags();
13936 SDValue
LHS =
Op.getOperand(1);
13937 SDValue
RHS =
Op.getOperand(2);
13944 const APFloat K0Val(0x1p+96f);
13947 const APFloat K1Val(0x1p-32f);
13962 SDValue
r0 = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32,
r1, Flags);
13974 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
13975 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
13976 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
13981 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13982 return FastLowered;
13988 SDNodeFlags
Flags =
Op->getFlags();
13989 Flags.setNoFPExcept(
true);
13992 SDValue
LHS =
Op.getOperand(0);
13993 SDValue
RHS =
Op.getOperand(1);
13997 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
13999 SDValue DenominatorScaled =
14001 SDValue NumeratorScaled =
14005 SDValue ApproxRcp =
14006 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14007 SDValue NegDivScale0 =
14010 using namespace AMDGPU::Hwreg;
14011 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14015 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
14016 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
14019 const bool HasDynamicDenormals =
14023 SDValue SavedDenormMode;
14025 if (!PreservesDenormals) {
14030 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14033 if (HasDynamicDenormals) {
14037 SavedDenormMode = SDValue(GetReg, 0);
14040 {DAG.
getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14043 SDNode *EnableDenorm;
14044 if (Subtarget->hasDenormModeInst()) {
14045 const SDValue EnableDenormValue =
14048 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14052 const SDValue EnableDenormValue =
14054 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14055 {EnableDenormValue,
BitField, Glue});
14058 SDValue
Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14059 SDValue(EnableDenorm, 1)};
14065 ApproxRcp, One, NegDivScale0, Flags);
14068 ApproxRcp, Fma0, Flags);
14074 NumeratorScaled,
Mul, Flags);
14080 NumeratorScaled, Fma3, Flags);
14082 if (!PreservesDenormals) {
14083 SDNode *DisableDenorm;
14084 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14088 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14090 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14094 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14095 const SDValue DisableDenormValue =
14096 HasDynamicDenormals
14101 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14106 SDValue(DisableDenorm, 0), DAG.
getRoot());
14110 SDValue Scale = NumeratorScaled.
getValue(1);
14111 SDValue Fmas = DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14112 {Fma4, Fma1, Fma3, Scale},
Flags);
14114 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14118 if (SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14119 return FastLowered;
14122 SDValue
X =
Op.getOperand(0);
14123 SDValue
Y =
Op.getOperand(1);
14127 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14129 SDValue DivScale0 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
Y,
Y,
X);
14133 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14135 SDValue Fma0 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14139 SDValue Fma2 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14141 SDValue DivScale1 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
X,
Y,
X);
14143 SDValue Fma3 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14151 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14181 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14183 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14187 EVT VT =
Op.getValueType();
14189 if (VT == MVT::f32)
14190 return LowerFDIV32(
Op, DAG);
14192 if (VT == MVT::f64)
14193 return LowerFDIV64(
Op, DAG);
14195 if (VT == MVT::f16 || VT == MVT::bf16)
14196 return LowerFDIV16(
Op, DAG);
14203 SDValue Val =
Op.getOperand(0);
14205 EVT ResultExpVT =
Op->getValueType(1);
14206 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14216 if (Subtarget->hasFractBug()) {
14234 EVT VT =
Store->getMemoryVT();
14236 if (VT == MVT::i1) {
14240 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14244 Store->getValue().getValueType().getScalarType() == MVT::i32);
14246 unsigned AS =
Store->getAddressSpace();
14247 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14255 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14259 !Subtarget->hasMultiDwordFlatScratchAddressing())
14266 if (NumElements > 4)
14269 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14273 VT, *
Store->getMemOperand()))
14279 switch (Subtarget->getMaxPrivateElementSize()) {
14283 if (NumElements > 2)
14287 if (NumElements > 4 ||
14288 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14296 auto Flags =
Store->getMemOperand()->getFlags();
14315 assert(!Subtarget->has16BitInsts());
14316 SDNodeFlags
Flags =
Op->getFlags();
14330 SDNodeFlags
Flags =
Op->getFlags();
14331 MVT VT =
Op.getValueType().getSimpleVT();
14332 const SDValue
X =
Op.getOperand(0);
14358 SDValue SqrtSNextDownInt =
14363 SDValue NegSqrtSNextDown =
14387 SDValue SqrtR = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT, SqrtX, Flags);
14407 SDValue ScaledDown =
14411 SDValue IsZeroOrInf =
14439 SDNodeFlags
Flags =
Op->getFlags();
14443 SDValue
X =
Op.getOperand(0);
14448 if (!
Flags.hasApproximateFuncs()) {
14453 SDValue ScaleUpFactor = DAG.
getConstant(256,
DL, MVT::i32);
14459 SDValue SqrtY = DAG.
getNode(AMDGPUISD::RSQ,
DL, MVT::f64, SqrtX);
14479 SDValue SqrtRet = SqrtS2;
14480 if (!
Flags.hasApproximateFuncs()) {
14489 ScaleDownFactor, ZeroInt);
14495 SDValue IsZeroOrInf;
14496 if (
Flags.hasNoInfs()) {
14512 EVT VT =
Op.getValueType();
14513 SDValue Arg =
Op.getOperand(0);
14522 auto UnrollIfVec = [&DAG](SDValue
V) -> SDValue {
14523 if (!
V.getValueType().isVector())
14531 if (Subtarget->hasTrigReducedRange()) {
14533 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14538 switch (
Op.getOpcode()) {
14540 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14543 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14549 return UnrollIfVec(TrigVal);
14565 SDValue ChainIn =
Op.getOperand(0);
14566 SDValue Addr =
Op.getOperand(1);
14567 SDValue Old =
Op.getOperand(2);
14568 SDValue
New =
Op.getOperand(3);
14569 EVT VT =
Op.getValueType();
14574 SDValue
Ops[] = {ChainIn, Addr, NewOld};
14577 Op->getVTList(),
Ops, VT,
14586SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14587 DAGCombinerInfo &DCI)
const {
14588 EVT VT =
N->getValueType(0);
14590 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14593 SelectionDAG &DAG = DCI.DAG;
14596 SDValue Src =
N->getOperand(0);
14597 EVT SrcVT = Src.getValueType();
14603 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14605 SDValue Cvt = DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0,
DL, MVT::f32, Src);
14606 DCI.AddToWorklist(Cvt.
getNode());
14609 if (ScalarVT != MVT::f32) {
14621 DAGCombinerInfo &DCI)
const {
14632 SelectionDAG &DAG = DCI.DAG;
14651 for (
unsigned I = 0;
I != NumElts; ++
I) {
14659 SDValue SignOpElt =
14675 if (NewElts.
size() == 1)
14697 for (
unsigned I = 0;
I != NumElts; ++
I) {
14699 SDValue SignAsF32 =
14732SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14734 DAGCombinerInfo &DCI)
const {
14751 SelectionDAG &DAG = DCI.DAG;
14764 AM.BaseOffs =
Offset.getSExtValue();
14769 EVT VT =
N->getValueType(0);
14775 Flags.setNoUnsignedWrap(
14776 N->getFlags().hasNoUnsignedWrap() &&
14788 switch (
N->getOpcode()) {
14799 DAGCombinerInfo &DCI)
const {
14800 SelectionDAG &DAG = DCI.DAG;
14807 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14808 N->getMemoryVT(), DCI);
14812 NewOps[PtrIdx] = NewPtr;
14821 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14822 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14831SDValue SITargetLowering::splitBinaryBitConstantOp(
14835 uint32_t ValLo =
Lo_32(Val);
14836 uint32_t ValHi =
Hi_32(Val);
14843 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14857 if (V.getValueType() != MVT::i1)
14859 switch (V.getOpcode()) {
14864 case AMDGPUISD::FP_CLASS:
14876 return V.getResNo() == 1;
14878 unsigned IntrinsicID = V.getConstantOperandVal(0);
14879 switch (IntrinsicID) {
14880 case Intrinsic::amdgcn_is_shared:
14881 case Intrinsic::amdgcn_is_private:
14898 if (!(
C & 0x000000ff))
14899 ZeroByteMask |= 0x000000ff;
14900 if (!(
C & 0x0000ff00))
14901 ZeroByteMask |= 0x0000ff00;
14902 if (!(
C & 0x00ff0000))
14903 ZeroByteMask |= 0x00ff0000;
14904 if (!(
C & 0xff000000))
14905 ZeroByteMask |= 0xff000000;
14906 uint32_t NonZeroByteMask = ~ZeroByteMask;
14907 if ((NonZeroByteMask &
C) != NonZeroByteMask)
14920 assert(V.getValueSizeInBits() == 32);
14922 if (V.getNumOperands() != 2)
14931 switch (V.getOpcode()) {
14936 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14941 return (0x03020100 & ~ConstMask) | ConstMask;
14948 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
14954 return uint32_t(0x0c0c0c0c03020100ull >>
C);
14961 DAGCombinerInfo &DCI)
const {
14962 if (DCI.isBeforeLegalize())
14965 SelectionDAG &DAG = DCI.DAG;
14966 EVT VT =
N->getValueType(0);
14967 SDValue
LHS =
N->getOperand(0);
14968 SDValue
RHS =
N->getOperand(1);
14971 if (VT == MVT::i64 && CRHS) {
14972 if (SDValue Split =
14973 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
14977 if (CRHS && VT == MVT::i32) {
14987 unsigned Shift = CShift->getZExtValue();
14989 unsigned Offset = NB + Shift;
14990 if ((
Offset & (Bits - 1)) == 0) {
14993 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
15014 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15016 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15027 SDValue
X =
LHS.getOperand(0);
15028 SDValue
Y =
RHS.getOperand(0);
15029 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
15034 if (
X !=
LHS.getOperand(1))
15038 const ConstantFPSDNode *C1 =
15055 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15061 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15064 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15072 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15073 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15075 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15076 :
Mask->getZExtValue() & OrdMask;
15079 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15097 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15100 if (LHSMask != ~0u && RHSMask != ~0u) {
15103 if (LHSMask > RHSMask) {
15110 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15111 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15114 if (!(LHSUsedLanes & RHSUsedLanes) &&
15117 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15123 uint32_t
Mask = LHSMask & RHSMask;
15124 for (
unsigned I = 0;
I < 32;
I += 8) {
15125 uint32_t ByteSel = 0xff <<
I;
15126 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15127 Mask &= (0x0c <<
I) & 0xffffffff;
15132 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15135 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15185static const std::optional<ByteProvider<SDValue>>
15187 unsigned Depth = 0) {
15190 return std::nullopt;
15192 if (
Op.getValueSizeInBits() < 8)
15193 return std::nullopt;
15195 if (
Op.getValueType().isVector())
15198 switch (
Op->getOpcode()) {
15211 NarrowVT = VTSign->getVT();
15214 return std::nullopt;
15217 if (SrcIndex >= NarrowByteWidth)
15218 return std::nullopt;
15226 return std::nullopt;
15228 uint64_t BitShift = ShiftOp->getZExtValue();
15230 if (BitShift % 8 != 0)
15231 return std::nullopt;
15233 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15234 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15235 return std::nullopt;
15254static const std::optional<ByteProvider<SDValue>>
15256 unsigned StartingIndex = 0) {
15260 return std::nullopt;
15262 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15264 return std::nullopt;
15266 return std::nullopt;
15268 bool IsVec =
Op.getValueType().isVector();
15269 switch (
Op.getOpcode()) {
15272 return std::nullopt;
15277 return std::nullopt;
15281 return std::nullopt;
15284 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15285 return std::nullopt;
15286 if (!
LHS ||
LHS->isConstantZero())
15288 if (!
RHS ||
RHS->isConstantZero())
15290 return std::nullopt;
15295 return std::nullopt;
15299 return std::nullopt;
15301 uint32_t BitMask = BitMaskOp->getZExtValue();
15303 uint32_t IndexMask = 0xFF << (Index * 8);
15305 if ((IndexMask & BitMask) != IndexMask) {
15308 if (IndexMask & BitMask)
15309 return std::nullopt;
15318 return std::nullopt;
15322 if (!ShiftOp ||
Op.getValueType().isVector())
15323 return std::nullopt;
15325 uint64_t BitsProvided =
Op.getValueSizeInBits();
15326 if (BitsProvided % 8 != 0)
15327 return std::nullopt;
15329 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15331 return std::nullopt;
15333 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15334 uint64_t ByteShift = BitShift / 8;
15336 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15337 uint64_t BytesProvided = BitsProvided / 8;
15338 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15339 NewIndex %= BytesProvided;
15346 return std::nullopt;
15350 return std::nullopt;
15352 uint64_t BitShift = ShiftOp->getZExtValue();
15354 return std::nullopt;
15356 auto BitsProvided =
Op.getScalarValueSizeInBits();
15357 if (BitsProvided % 8 != 0)
15358 return std::nullopt;
15360 uint64_t BytesProvided = BitsProvided / 8;
15361 uint64_t ByteShift = BitShift / 8;
15362 if (Index + ByteShift < BytesProvided)
15364 Index + ByteShift);
15367 return std::nullopt;
15373 return std::nullopt;
15377 return std::nullopt;
15379 uint64_t BitShift = ShiftOp->getZExtValue();
15380 if (BitShift % 8 != 0)
15381 return std::nullopt;
15382 uint64_t ByteShift = BitShift / 8;
15388 return Index < ByteShift
15391 Depth + 1, StartingIndex);
15400 return std::nullopt;
15408 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15410 if (NarrowBitWidth % 8 != 0)
15411 return std::nullopt;
15412 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15414 if (Index >= NarrowByteWidth)
15416 ? std::optional<ByteProvider<SDValue>>(
15424 return std::nullopt;
15428 if (NarrowByteWidth >= Index) {
15433 return std::nullopt;
15440 return std::nullopt;
15446 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15447 if (NarrowBitWidth % 8 != 0)
15448 return std::nullopt;
15449 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15454 if (Index >= NarrowByteWidth) {
15456 ? std::optional<ByteProvider<SDValue>>(
15461 if (NarrowByteWidth > Index) {
15465 return std::nullopt;
15470 return std::nullopt;
15473 Depth + 1, StartingIndex);
15479 return std::nullopt;
15480 auto VecIdx = IdxOp->getZExtValue();
15481 auto ScalarSize =
Op.getScalarValueSizeInBits();
15482 if (ScalarSize < 32)
15483 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15485 StartingIndex, Index);
15488 case AMDGPUISD::PERM: {
15490 return std::nullopt;
15494 return std::nullopt;
15497 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15498 if (IdxMask > 0x07 && IdxMask != 0x0c)
15499 return std::nullopt;
15501 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15502 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15504 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15510 return std::nullopt;
15525 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15532 auto MemVT = L->getMemoryVT();
15535 return L->getMemoryVT().getSizeInBits() == 16;
15545 int Low8 = Mask & 0xff;
15546 int Hi8 = (Mask & 0xff00) >> 8;
15548 assert(Low8 < 8 && Hi8 < 8);
15550 bool IsConsecutive = (Hi8 - Low8 == 1);
15555 bool Is16Aligned = !(Low8 % 2);
15557 return IsConsecutive && Is16Aligned;
15565 int Low16 = PermMask & 0xffff;
15566 int Hi16 = (PermMask & 0xffff0000) >> 16;
15576 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15578 if (!OtherOpIs16Bit)
15586 unsigned DWordOffset) {
15591 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15596 if (Src.getValueType().isVector()) {
15597 auto ScalarTySize = Src.getScalarValueSizeInBits();
15598 auto ScalarTy = Src.getValueType().getScalarType();
15599 if (ScalarTySize == 32) {
15603 if (ScalarTySize > 32) {
15606 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15607 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15614 assert(ScalarTySize < 32);
15623 auto NumElements =
TypeSize / ScalarTySize;
15624 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15625 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15626 auto NumElementsIn32 = 32 / ScalarTySize;
15627 auto NumAvailElements = DWordOffset < Trunc32Elements
15629 : NumElements - NormalizedTrunc;
15642 auto ShiftVal = 32 * DWordOffset;
15650 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15655 for (
int i = 0; i < 4; i++) {
15657 std::optional<ByteProvider<SDValue>>
P =
15660 if (!
P ||
P->isConstantZero())
15665 if (PermNodes.
size() != 4)
15668 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15669 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15671 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15672 auto PermOp = PermNodes[i];
15675 int SrcByteAdjust = 4;
15679 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15680 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15682 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15683 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15687 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15688 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15691 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15693 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15696 SDValue Op = *PermNodes[FirstSrc.first].Src;
15698 assert(
Op.getValueSizeInBits() == 32);
15702 int Low16 = PermMask & 0xffff;
15703 int Hi16 = (PermMask & 0xffff0000) >> 16;
15705 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15706 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15709 if (WellFormedLow && WellFormedHi)
15713 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15722 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15723 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15728 assert(
Op.getValueType().isByteSized() &&
15739 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15746 DAGCombinerInfo &DCI)
const {
15747 SelectionDAG &DAG = DCI.DAG;
15748 SDValue
LHS =
N->getOperand(0);
15749 SDValue
RHS =
N->getOperand(1);
15751 EVT VT =
N->getValueType(0);
15752 if (VT == MVT::i1) {
15754 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15755 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15756 SDValue Src =
LHS.getOperand(0);
15757 if (Src !=
RHS.getOperand(0))
15762 if (!CLHS || !CRHS)
15766 static const uint32_t MaxMask = 0x3ff;
15771 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15780 LHS.getOpcode() == AMDGPUISD::PERM &&
15786 Sel |=
LHS.getConstantOperandVal(2);
15788 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15795 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15799 auto usesCombinedOperand = [](SDNode *OrUse) {
15802 !OrUse->getValueType(0).isVector())
15806 for (
auto *VUser : OrUse->users()) {
15807 if (!VUser->getValueType(0).isVector())
15814 if (VUser->getOpcode() == VectorwiseOp)
15820 if (!
any_of(
N->users(), usesCombinedOperand))
15826 if (LHSMask != ~0u && RHSMask != ~0u) {
15829 if (LHSMask > RHSMask) {
15836 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15837 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15840 if (!(LHSUsedLanes & RHSUsedLanes) &&
15843 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15845 LHSMask &= ~RHSUsedLanes;
15846 RHSMask &= ~LHSUsedLanes;
15848 LHSMask |= LHSUsedLanes & 0x04040404;
15850 uint32_t Sel = LHSMask | RHSMask;
15853 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15858 if (LHSMask == ~0u || RHSMask == ~0u) {
15889 SDValue LEVE =
LHS->getOperand(0);
15890 SDValue REVE =
RHS->getOperand(1);
15899 return IdentitySrc;
15905 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15918 SDValue ExtSrc =
RHS.getOperand(0);
15920 if (SrcVT == MVT::i32) {
15923 SDValue LowOr = DAG.
getNode(
ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
15925 DCI.AddToWorklist(LowOr.
getNode());
15926 DCI.AddToWorklist(HiBits.getNode());
15936 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::OR,
15937 N->getOperand(0), CRHS))
15945 DAGCombinerInfo &DCI)
const {
15946 if (SDValue RV = reassociateScalarOps(
N, DCI.DAG))
15949 SDValue
LHS =
N->getOperand(0);
15950 SDValue
RHS =
N->getOperand(1);
15953 SelectionDAG &DAG = DCI.DAG;
15955 EVT VT =
N->getValueType(0);
15956 if (CRHS && VT == MVT::i64) {
15957 if (SDValue Split =
15958 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
15965 unsigned Opc =
LHS.getOpcode();
15969 SDValue CC =
LHS->getOperand(0);
15970 SDValue TRUE =
LHS->getOperand(1);
15971 SDValue FALSE =
LHS->getOperand(2);
15995 LHS->getOperand(0), FNegLHS, FNegRHS);
16004SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
16005 DAGCombinerInfo &DCI)
const {
16006 if (!Subtarget->has16BitInsts() ||
16010 EVT VT =
N->getValueType(0);
16011 if (VT != MVT::i32)
16014 SDValue Src =
N->getOperand(0);
16015 if (Src.getValueType() != MVT::i16)
16018 if (!Src->hasOneUse())
16025 std::optional<ByteProvider<SDValue>> BP0 =
16027 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16029 SDValue
V0 = *BP0->Src;
16031 std::optional<ByteProvider<SDValue>> BP1 =
16033 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16036 SDValue
V1 = *BP1->Src;
16041 SelectionDAG &DAG = DCI.DAG;
16043 uint32_t PermMask = 0x0c0c0c0c;
16046 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16051 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16054 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16059SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16060 DAGCombinerInfo &DCI)
const {
16061 SDValue Src =
N->getOperand(0);
16066 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16067 VTSign->getVT() == MVT::i8) ||
16068 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16069 VTSign->getVT() == MVT::i16))) {
16070 assert(Subtarget->hasScalarSubwordLoads() &&
16071 "s_buffer_load_{u8, i8} are supported "
16072 "in GFX12 (or newer) architectures.");
16073 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16074 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16075 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16078 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16086 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16087 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16088 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16090 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16091 VTSign->getVT() == MVT::i8) ||
16092 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16093 VTSign->getVT() == MVT::i16)) &&
16096 SDValue
Ops[] = {Src.getOperand(0),
16102 Src.getOperand(6), Src.getOperand(7)};
16105 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16106 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16107 ? AMDGPUISD::BUFFER_LOAD_BYTE
16108 : AMDGPUISD::BUFFER_LOAD_SHORT;
16109 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16110 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16111 return DCI.DAG.getMergeValues(
16112 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16118 DAGCombinerInfo &DCI)
const {
16119 SelectionDAG &DAG = DCI.DAG;
16120 SDValue
Mask =
N->getOperand(1);
16126 if (
N->getOperand(0).isUndef())
16133 DAGCombinerInfo &DCI)
const {
16134 EVT VT =
N->getValueType(0);
16145 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16154 unsigned MaxDepth)
const {
16155 EVT VT =
Op.getValueType();
16157 "expected a floating-point value to query canonicality of");
16163 unsigned MaxDepth)
const {
16165 "QueryVT must be a floating-point scalar type");
16166 EVT VT =
Op.getValueType();
16170 unsigned Opcode =
Op.getOpcode();
16175 const auto &
F = CFP->getValueAPF();
16176 if (
F.isNaN() &&
F.isSignaling())
16178 if (!
F.isDenormal())
16210 case AMDGPUISD::FMUL_LEGACY:
16211 case AMDGPUISD::FMAD_FTZ:
16212 case AMDGPUISD::RCP:
16213 case AMDGPUISD::RSQ:
16214 case AMDGPUISD::RSQ_CLAMP:
16215 case AMDGPUISD::RCP_LEGACY:
16216 case AMDGPUISD::RCP_IFLAG:
16217 case AMDGPUISD::LOG:
16218 case AMDGPUISD::EXP:
16219 case AMDGPUISD::DIV_SCALE:
16220 case AMDGPUISD::DIV_FMAS:
16221 case AMDGPUISD::DIV_FIXUP:
16222 case AMDGPUISD::FRACT:
16223 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16224 case AMDGPUISD::CVT_F32_UBYTE0:
16225 case AMDGPUISD::CVT_F32_UBYTE1:
16226 case AMDGPUISD::CVT_F32_UBYTE2:
16227 case AMDGPUISD::CVT_F32_UBYTE3:
16228 case AMDGPUISD::FP_TO_FP16:
16229 case AMDGPUISD::SIN_HW:
16230 case AMDGPUISD::COS_HW:
16242 if (
Op.getValueType() == MVT::i32) {
16248 if (RHS->getZExtValue() == 0xffff0000) {
16259 return Op.getValueType().getScalarType() != MVT::f16;
16269 case AMDGPUISD::CLAMP:
16270 case AMDGPUISD::FMED3:
16271 case AMDGPUISD::FMAX3:
16272 case AMDGPUISD::FMIN3:
16273 case AMDGPUISD::FMAXIMUM3:
16274 case AMDGPUISD::FMINIMUM3: {
16280 if (Subtarget->supportsMinMaxDenormModes() ||
16290 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16305 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16339 if (
Op.getValueType() == MVT::i16) {
16351 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16353 switch (IntrinsicID) {
16354 case Intrinsic::amdgcn_cvt_pkrtz:
16355 case Intrinsic::amdgcn_cubeid:
16356 case Intrinsic::amdgcn_frexp_mant:
16357 case Intrinsic::amdgcn_fdot2:
16358 case Intrinsic::amdgcn_rcp:
16359 case Intrinsic::amdgcn_rsq:
16360 case Intrinsic::amdgcn_rsq_clamp:
16361 case Intrinsic::amdgcn_rcp_legacy:
16362 case Intrinsic::amdgcn_rsq_legacy:
16363 case Intrinsic::amdgcn_trig_preop:
16364 case Intrinsic::amdgcn_tanh:
16365 case Intrinsic::amdgcn_log:
16366 case Intrinsic::amdgcn_exp2:
16367 case Intrinsic::amdgcn_sqrt:
16385 unsigned MaxDepth)
const {
16388 unsigned Opcode =
MI->getOpcode();
16390 if (Opcode == AMDGPU::G_FCANONICALIZE)
16393 std::optional<FPValueAndVReg> FCR;
16396 if (FCR->Value.isSignaling())
16398 if (!FCR->Value.isDenormal())
16409 case AMDGPU::G_FADD:
16410 case AMDGPU::G_FSUB:
16411 case AMDGPU::G_FMUL:
16412 case AMDGPU::G_FCEIL:
16413 case AMDGPU::G_FFLOOR:
16414 case AMDGPU::G_FRINT:
16415 case AMDGPU::G_FNEARBYINT:
16416 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16417 case AMDGPU::G_INTRINSIC_TRUNC:
16418 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16419 case AMDGPU::G_FMA:
16420 case AMDGPU::G_FMAD:
16421 case AMDGPU::G_FSQRT:
16422 case AMDGPU::G_FDIV:
16423 case AMDGPU::G_FREM:
16424 case AMDGPU::G_FPOW:
16425 case AMDGPU::G_FPEXT:
16426 case AMDGPU::G_FLOG:
16427 case AMDGPU::G_FLOG2:
16428 case AMDGPU::G_FLOG10:
16429 case AMDGPU::G_FPTRUNC:
16430 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16431 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16432 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16433 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16434 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16436 case AMDGPU::G_FNEG:
16437 case AMDGPU::G_FABS:
16438 case AMDGPU::G_FCOPYSIGN:
16440 case AMDGPU::G_FMINNUM:
16441 case AMDGPU::G_FMAXNUM:
16442 case AMDGPU::G_FMINNUM_IEEE:
16443 case AMDGPU::G_FMAXNUM_IEEE:
16444 case AMDGPU::G_FMINIMUM:
16445 case AMDGPU::G_FMAXIMUM:
16446 case AMDGPU::G_FMINIMUMNUM:
16447 case AMDGPU::G_FMAXIMUMNUM: {
16448 if (Subtarget->supportsMinMaxDenormModes() ||
16455 case AMDGPU::G_BUILD_VECTOR:
16460 case AMDGPU::G_INTRINSIC:
16461 case AMDGPU::G_INTRINSIC_CONVERGENT:
16463 case Intrinsic::amdgcn_fmul_legacy:
16464 case Intrinsic::amdgcn_fmad_ftz:
16465 case Intrinsic::amdgcn_sqrt:
16466 case Intrinsic::amdgcn_fmed3:
16467 case Intrinsic::amdgcn_sin:
16468 case Intrinsic::amdgcn_cos:
16469 case Intrinsic::amdgcn_log:
16470 case Intrinsic::amdgcn_exp2:
16471 case Intrinsic::amdgcn_log_clamp:
16472 case Intrinsic::amdgcn_rcp:
16473 case Intrinsic::amdgcn_rcp_legacy:
16474 case Intrinsic::amdgcn_rsq:
16475 case Intrinsic::amdgcn_rsq_clamp:
16476 case Intrinsic::amdgcn_rsq_legacy:
16477 case Intrinsic::amdgcn_div_scale:
16478 case Intrinsic::amdgcn_div_fmas:
16479 case Intrinsic::amdgcn_div_fixup:
16480 case Intrinsic::amdgcn_fract:
16481 case Intrinsic::amdgcn_cvt_pkrtz:
16482 case Intrinsic::amdgcn_cubeid:
16483 case Intrinsic::amdgcn_cubema:
16484 case Intrinsic::amdgcn_cubesc:
16485 case Intrinsic::amdgcn_cubetc:
16486 case Intrinsic::amdgcn_frexp_mant:
16487 case Intrinsic::amdgcn_fdot2:
16488 case Intrinsic::amdgcn_trig_preop:
16489 case Intrinsic::amdgcn_tanh:
16508 if (
C.isDenormal()) {
16521 if (
C.isSignaling()) {
16536SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16537 DAGCombinerInfo &DCI)
const {
16538 SelectionDAG &DAG = DCI.DAG;
16540 EVT VT =
N->getValueType(0);
16549 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16561 SDValue NewElts[2];
16564 EVT EltVT =
Lo.getValueType();
16573 for (
unsigned I = 0;
I != 2; ++
I) {
16577 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16578 }
else if (
Op.isUndef()) {
16613 return AMDGPUISD::FMAX3;
16615 return AMDGPUISD::FMAXIMUM3;
16617 return AMDGPUISD::SMAX3;
16619 return AMDGPUISD::UMAX3;
16623 return AMDGPUISD::FMIN3;
16625 return AMDGPUISD::FMINIMUM3;
16627 return AMDGPUISD::SMIN3;
16629 return AMDGPUISD::UMIN3;
16650 if (!MinK || !MaxK)
16662 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16663 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16664 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16688 bool IsKnownNoNaNs)
const {
16724 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16730 if (
Info->getMode().DX10Clamp) {
16739 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16753 SDValue(K0, 0), SDValue(K1, 0));
16771 case AMDGPUISD::FMIN_LEGACY:
16772 case AMDGPUISD::FMAX_LEGACY:
16773 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.
hasMin3Max3_16()) ||
16774 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16777 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16778 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16779 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16784 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.
hasMin3Max3_16());
16793 DAGCombinerInfo &DCI)
const {
16794 SelectionDAG &DAG = DCI.DAG;
16805 auto IsTreeWithCombinableChildren = [
Opc](SDValue
Op) {
16806 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16807 Op.getOperand(0).hasOneUse()) ||
16809 Op.getOperand(1).hasOneUse());
16814 bool HasCombinableTreeChild =
16815 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16816 IsTreeWithCombinableChildren(Op1));
16825 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16863 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
16871 if (SDValue Med3 = performIntMed3ImmCombine(
16876 if (SDValue Med3 = performIntMed3ImmCombine(
16882 if (SDValue Med3 = performIntMed3ImmCombine(
16887 if (SDValue Med3 = performIntMed3ImmCombine(
16900 (
Opc == AMDGPUISD::FMIN_LEGACY &&
16901 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16902 (VT == MVT::f32 || VT == MVT::f64 ||
16903 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16904 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16905 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16906 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16908 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
16909 N->getFlags().hasNoNaNs()))
16916 const SDNodeFlags
Flags =
N->getFlags();
16918 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16922 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
16932 return (CA->isPosZero() && CB->isOne()) ||
16933 (CA->isOne() && CB->isPosZero());
16942 DAGCombinerInfo &DCI)
const {
16943 EVT VT =
N->getValueType(0);
16947 SelectionDAG &DAG = DCI.DAG;
16958 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16962 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16966 if (
Info->getMode().DX10Clamp) {
16979 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
16986 DAGCombinerInfo &DCI)
const {
16990 return DCI.DAG.getUNDEF(
N->getValueType(0));
16998 bool IsDivergentIdx,
17003 unsigned VecSize = EltSize * NumElem;
17006 if (VecSize <= 64 && EltSize < 32)
17015 if (IsDivergentIdx)
17019 unsigned NumInsts = NumElem +
17020 ((EltSize + 31) / 32) * NumElem ;
17024 if (Subtarget->useVGPRIndexMode())
17025 return NumInsts <= 16;
17029 if (Subtarget->hasMovrel())
17030 return NumInsts <= 15;
17036 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17051SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17052 DAGCombinerInfo &DCI)
const {
17058 EVT ResVT =
N->getValueType(0);
17082 if (!
C ||
C->getZExtValue() != 0x1f)
17098 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17126 DCI.AddToWorklist(Elt0.
getNode());
17127 DCI.AddToWorklist(Elt1.
getNode());
17158 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17159 uint64_t KImmValue = KImm->getZExtValue();
17161 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17164 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17166 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17167 return DAG.
getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17173 if (!DCI.isBeforeLegalize())
17180 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17183 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17184 unsigned EltIdx = BitIndex / 32;
17185 unsigned LeftoverBitIdx = BitIndex % 32;
17189 DCI.AddToWorklist(Cast.
getNode());
17193 DCI.AddToWorklist(Elt.
getNode());
17196 DCI.AddToWorklist(Srl.
getNode());
17200 DCI.AddToWorklist(Trunc.
getNode());
17202 if (VecEltVT == ResVT) {
17214SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17215 DAGCombinerInfo &DCI)
const {
17226 SelectionDAG &DAG = DCI.DAG;
17246 Src.getOperand(0).getValueType() == MVT::f16) {
17247 return Src.getOperand(0);
17251 APFloat Val = CFP->getValueAPF();
17252 bool LosesInfo =
true;
17262 DAGCombinerInfo &DCI)
const {
17263 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17264 "combine only useful on gfx8");
17266 SDValue TruncSrc =
N->getOperand(0);
17267 EVT VT =
N->getValueType(0);
17268 if (VT != MVT::f16)
17271 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17275 SelectionDAG &DAG = DCI.DAG;
17306unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17308 const SDNode *N1)
const {
17313 if (((VT == MVT::f32 &&
17315 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17332 EVT VT =
N->getValueType(0);
17333 if (VT != MVT::i32 && VT != MVT::i64)
17339 unsigned Opc =
N->getOpcode();
17361 SDValue Add1 = DAG.
getNode(
Opc, SL, VT, Op0, Op1);
17394 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17413 DAGCombinerInfo &DCI)
const {
17416 SelectionDAG &DAG = DCI.DAG;
17417 EVT VT =
N->getValueType(0);
17419 SDValue
LHS =
N->getOperand(0);
17420 SDValue
RHS =
N->getOperand(1);
17427 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17431 if (NumBits <= 32 || NumBits > 64)
17442 if (!Subtarget->hasFullRate64Ops()) {
17443 unsigned NumUsers = 0;
17444 for (SDNode *User :
LHS->
users()) {
17447 if (!
User->isAnyAdd())
17458 SDValue MulLHS =
LHS.getOperand(0);
17459 SDValue MulRHS =
LHS.getOperand(1);
17460 SDValue AddRHS =
RHS;
17471 bool MulSignedLo =
false;
17472 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17481 if (VT != MVT::i64) {
17504 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17506 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17507 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17509 if (!MulLHSUnsigned32) {
17512 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17516 if (!MulRHSUnsigned32) {
17519 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17527 if (VT != MVT::i64)
17533SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17534 DAGCombinerInfo &DCI)
const {
17535 SDValue
RHS =
N->getOperand(1);
17544 SelectionDAG &DAG = DCI.DAG;
17546 SDValue
LHS =
N->getOperand(0);
17559 unsigned Opcode =
N->getOpcode();
17563 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17574static std::optional<ByteProvider<SDValue>>
17577 if (!Byte0 || Byte0->isConstantZero()) {
17578 return std::nullopt;
17581 if (Byte1 && !Byte1->isConstantZero()) {
17582 return std::nullopt;
17588 unsigned FirstCs =
First & 0x0c0c0c0c;
17589 unsigned SecondCs = Second & 0x0c0c0c0c;
17590 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17591 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17593 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17594 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17595 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17596 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17598 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17622 for (
int BPI = 0; BPI < 2; BPI++) {
17625 BPP = {Src1, Src0};
17627 unsigned ZeroMask = 0x0c0c0c0c;
17628 unsigned FMask = 0xFF << (8 * (3 - Step));
17630 unsigned FirstMask =
17631 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17632 unsigned SecondMask =
17633 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17637 int FirstGroup = -1;
17638 for (
int I = 0;
I < 2;
I++) {
17640 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17641 return IterElt.SrcOp == *BPP.first.Src &&
17642 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17646 if (Match != Srcs.
end()) {
17647 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17652 if (FirstGroup != -1) {
17654 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17655 return IterElt.SrcOp == *BPP.second.Src &&
17656 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17659 if (Match != Srcs.
end()) {
17660 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17662 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17670 unsigned ZeroMask = 0x0c0c0c0c;
17671 unsigned FMask = 0xFF << (8 * (3 - Step));
17675 ((Src0.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17679 ((Src1.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17688 if (Srcs.
size() == 1) {
17689 auto *Elt = Srcs.
begin();
17693 if (Elt->PermMask == 0x3020100)
17696 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17700 auto *FirstElt = Srcs.
begin();
17701 auto *SecondElt = std::next(FirstElt);
17708 auto FirstMask = FirstElt->PermMask;
17709 auto SecondMask = SecondElt->PermMask;
17711 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17712 unsigned FirstPlusFour = FirstMask | 0x04040404;
17715 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17727 FirstElt = std::next(SecondElt);
17728 if (FirstElt == Srcs.
end())
17731 SecondElt = std::next(FirstElt);
17734 if (SecondElt == Srcs.
end()) {
17739 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17740 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17746 return Perms.
size() == 2
17752 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17753 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17754 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17755 EntryMask += ZeroMask;
17760 auto Opcode =
Op.getOpcode();
17762 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17763 Opcode == AMDGPUISD::MUL_I24);
17766static std::optional<bool>
17777 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17780 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17782 assert(!(S0IsUnsigned && S0IsSigned));
17783 assert(!(S1IsUnsigned && S1IsSigned));
17791 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17797 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17798 return std::nullopt;
17810 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17811 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17816 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17822 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17823 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17824 return std::nullopt;
17830 DAGCombinerInfo &DCI)
const {
17831 SelectionDAG &DAG = DCI.DAG;
17832 EVT VT =
N->getValueType(0);
17834 SDValue
LHS =
N->getOperand(0);
17835 SDValue
RHS =
N->getOperand(1);
17838 if (Subtarget->hasMad64_32()) {
17839 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
17844 if (SDValue V = reassociateScalarOps(
N, DAG)) {
17848 if (VT == MVT::i64) {
17849 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17856 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17857 SDValue TempNode(
N, 0);
17858 std::optional<bool> IsSigned;
17864 int ChainLength = 0;
17865 for (
int I = 0;
I < 4;
I++) {
17869 auto Src0 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17872 auto Src1 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17877 TempNode->getOperand(MulIdx), *Src0, *Src1,
17878 TempNode->getOperand(MulIdx)->getOperand(0),
17879 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17883 IsSigned = *IterIsSigned;
17884 if (*IterIsSigned != *IsSigned)
17887 auto AddIdx = 1 - MulIdx;
17890 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
17891 Src2s.
push_back(TempNode->getOperand(AddIdx));
17901 TempNode->getOperand(AddIdx), *Src0, *Src1,
17902 TempNode->getOperand(AddIdx)->getOperand(0),
17903 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17907 if (*IterIsSigned != *IsSigned)
17911 ChainLength =
I + 2;
17915 TempNode = TempNode->getOperand(AddIdx);
17917 ChainLength =
I + 1;
17919 if (TempNode.getOpcode() !=
ISD::ADD)
17921 LHS = TempNode->getOperand(0);
17922 RHS = TempNode->getOperand(1);
17925 if (ChainLength < 2)
17931 if (ChainLength < 4) {
17936 SDValue Src0, Src1;
17941 bool UseOriginalSrc =
false;
17942 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
17943 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
17944 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
17945 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
17946 SmallVector<unsigned, 4> SrcBytes;
17947 auto Src0Mask = Src0s.
begin()->PermMask;
17948 SrcBytes.
push_back(Src0Mask & 0xFF000000);
17949 bool UniqueEntries =
true;
17950 for (
auto I = 1;
I < 4;
I++) {
17951 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
17954 UniqueEntries =
false;
17960 if (UniqueEntries) {
17961 UseOriginalSrc =
true;
17963 auto *FirstElt = Src0s.
begin();
17967 auto *SecondElt = Src1s.
begin();
17969 SecondElt->DWordOffset);
17978 if (!UseOriginalSrc) {
17985 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
17988 : Intrinsic::amdgcn_udot4,
17998 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18003 unsigned Opc =
LHS.getOpcode();
18015 auto Cond =
RHS.getOperand(0);
18020 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18029 SDValue
Args[] = {
LHS,
RHS.getOperand(0),
RHS.getOperand(2)};
18037 DAGCombinerInfo &DCI)
const {
18038 SelectionDAG &DAG = DCI.DAG;
18040 EVT VT =
N->getValueType(0);
18053 SDNodeFlags ShlFlags = N1->
getFlags();
18057 SDNodeFlags NewShlFlags =
18062 DCI.AddToWorklist(Inner.
getNode());
18069 if (Subtarget->hasMad64_32()) {
18070 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
18079 if (VT == MVT::i64) {
18080 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18093 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18094 Y->isDivergent() !=
Z->isDivergent()) {
18103 if (
Y->isDivergent())
18106 SDNodeFlags ReassocFlags =
18109 DCI.AddToWorklist(UniformInner.
getNode());
18121 DAGCombinerInfo &DCI)
const {
18122 SelectionDAG &DAG = DCI.DAG;
18123 EVT VT =
N->getValueType(0);
18125 if (VT == MVT::i64) {
18126 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18130 if (VT != MVT::i32)
18134 SDValue
LHS =
N->getOperand(0);
18135 SDValue
RHS =
N->getOperand(1);
18139 unsigned Opc =
RHS.getOpcode();
18146 auto Cond =
RHS.getOperand(0);
18151 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18162 SDValue
Args[] = {
LHS.getOperand(0),
RHS,
LHS.getOperand(2)};
18168 SDValue CtlzSrc =
LHS.getOperand(0);
18177 ConstantSDNode *ShiftAmt =
18179 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18190 DAGCombinerInfo &DCI)
const {
18194 SelectionDAG &DAG = DCI.DAG;
18195 EVT VT =
N->getValueType(0);
18198 SDValue
LHS =
N->getOperand(0);
18199 SDValue
RHS =
N->getOperand(1);
18206 SDValue
A =
LHS.getOperand(0);
18207 if (
A ==
LHS.getOperand(1)) {
18208 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18209 if (FusedOp != 0) {
18211 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18218 SDValue
A =
RHS.getOperand(0);
18219 if (
A ==
RHS.getOperand(1)) {
18220 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18221 if (FusedOp != 0) {
18223 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18232 DAGCombinerInfo &DCI)
const {
18236 SelectionDAG &DAG = DCI.DAG;
18238 EVT VT =
N->getValueType(0);
18246 SDValue
LHS =
N->getOperand(0);
18247 SDValue
RHS =
N->getOperand(1);
18250 SDValue
A =
LHS.getOperand(0);
18251 if (
A ==
LHS.getOperand(1)) {
18252 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18253 if (FusedOp != 0) {
18257 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18265 SDValue
A =
RHS.getOperand(0);
18266 if (
A ==
RHS.getOperand(1)) {
18267 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18268 if (FusedOp != 0) {
18270 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18279 DAGCombinerInfo &DCI)
const {
18280 SelectionDAG &DAG = DCI.DAG;
18282 EVT VT =
N->getValueType(0);
18284 if (VT != MVT::f16 && VT != MVT::bf16)
18287 SDValue
LHS =
N->getOperand(0);
18288 SDValue
RHS =
N->getOperand(1);
18290 SDNodeFlags
Flags =
N->getFlags();
18291 SDNodeFlags RHSFlags =
RHS->getFlags();
18297 bool IsNegative =
false;
18298 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18303 SDValue SqrtOp =
RHS.getOperand(0);
18307 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18308 }
else if (VT == MVT::f16) {
18317 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18334 DAGCombinerInfo &DCI)
const {
18335 SelectionDAG &DAG = DCI.DAG;
18336 EVT VT =
N->getValueType(0);
18340 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18341 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18346 SDValue
LHS =
N->getOperand(0);
18347 SDValue
RHS =
N->getOperand(1);
18356 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18361 const ConstantFPSDNode *FalseNode =
18371 if (ScalarVT == MVT::f32 &&
18377 if (TrueNodeExpVal == INT_MIN)
18380 if (FalseNodeExpVal == INT_MIN)
18384 SDValue SelectNode =
18400 DAGCombinerInfo &DCI)
const {
18401 SelectionDAG &DAG = DCI.DAG;
18402 EVT VT =
N->getValueType(0);
18405 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18412 SDValue
FMA =
N->getOperand(2);
18433 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18434 FMA->getFlags().hasApproximateFuncs();
18435 if (!AllowInaccuracy) {
18438 if (Subtarget->dot2UnconditionalFlush()) {
18450 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18461 SDValue FMAOp1 =
FMA.getOperand(0);
18462 SDValue FMAOp2 =
FMA.getOperand(1);
18463 SDValue FMAAcc =
FMA.getOperand(2);
18486 if (Vec1 == Vec2 || Vec3 == Vec4)
18492 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18493 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18536 EVT VT =
LHS.getValueType();
18537 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18569 if (CC ==
ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18573 if (CC ==
ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18577 if (CC ==
ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18581 if (CC ==
ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18584 const std::optional<bool> KnownEq =
18613 if (CC ==
ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18617 if (CC ==
ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18625 const std::optional<bool> KnownUge =
18650 if (CC ==
ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18664 if (CC ==
ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18667 const std::optional<bool> KnownUle =
18690 DAGCombinerInfo &DCI)
const {
18691 SelectionDAG &DAG = DCI.DAG;
18694 SDValue
LHS =
N->getOperand(0);
18695 SDValue
RHS =
N->getOperand(1);
18696 EVT VT =
LHS.getValueType();
18725 return LHS.getOperand(0);
18739 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18740 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18745 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18748 return LHS.getOperand(0);
18769 if (VT == MVT::i64) {
18781 const std::optional<bool> KnownEq =
18789 const std::optional<bool> KnownEq =
18800 const std::optional<bool> KnownUge =
18820 const std::optional<bool> KnownUle =
18860 SDValue Op0 =
LHS.getOperand(0);
18861 SDValue Op1 =
LHS.getOperand(1);
18871 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18873 SDValue CarryInHi = NodeLo.
getValue(1);
18876 {Op0Hi, Op1Hi, CarryInHi});
18878 SDValue ResultLo = NodeLo.
getValue(0);
18879 SDValue ResultHi = NodeHi.
getValue(0);
18881 SDValue JoinedResult =
18885 SDValue Overflow = NodeHi.
getValue(1);
18886 DCI.CombineTo(
LHS.getNode(), Result);
18890 if (VT != MVT::f32 && VT != MVT::f64 &&
18891 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18906 const unsigned IsInfMask =
18908 const unsigned IsFiniteMask =
18913 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
18918 if (VT == MVT::f64) {
18929SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
18930 DAGCombinerInfo &DCI)
const {
18931 SelectionDAG &DAG = DCI.DAG;
18933 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18935 SDValue Src =
N->getOperand(0);
18936 SDValue Shift =
N->getOperand(0);
18952 unsigned ShiftOffset = 8 *
Offset;
18954 ShiftOffset -=
C->getZExtValue();
18956 ShiftOffset +=
C->getZExtValue();
18958 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18959 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18960 MVT::f32, Shifted);
18971 DCI.AddToWorklist(
N);
18972 return SDValue(
N, 0);
18976 if (SDValue DemandedSrc =
18978 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
18984 DAGCombinerInfo &DCI)
const {
18993 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
18994 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
18999 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
19001 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
19010 if (V.getOpcode() ==
ISD::FFREXP && V.getResNo() == 1) {
19021SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
19022 DAGCombinerInfo &DCI)
const {
19024 if (Subtarget->hasFractBug())
19027 SDValue
Cond =
N->getOperand(0);
19028 SDValue
TrueVal =
N->getOperand(1);
19036 bool CondSelectsZero;
19040 SDValue FrexpInput;
19044 CondSelectsZero =
true;
19045 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19048 CondSelectsZero =
false;
19060 bool IsNonFiniteTest =
false;
19066 SDValue CondLHS =
Cond.getOperand(0);
19067 SDValue CondRHS =
Cond.getOperand(1);
19072 bool LHSMatchesFrexp =
19073 (CondLHS == FrexpInput) ||
19074 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19076 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19084 SelectionDAG &DAG = DCI.DAG;
19085 if (LHSMatchesFrexp &&
19087 IsNonFiniteTest = CondSelectsZero;
19089 IsNonFiniteTest = CondSelectsZero;
19096 IsNonFiniteTest = CondSelectsZero;
19103 IsNonFiniteTest = !CondSelectsZero;
19109 SelectionDAG &DAG = DCI.DAG;
19110 if (LHSMatchesFrexp &&
19112 IsNonFiniteTest = !CondSelectsZero;
19114 IsNonFiniteTest = !CondSelectsZero;
19118 if (!IsNonFiniteTest)
19126 DAGCombinerInfo &DCI)
const {
19135 SDValue
Cond =
N->getOperand(0);
19136 SDValue
TrueVal =
N->getOperand(1);
19143 SDValue
LHS =
Cond.getOperand(0);
19144 SDValue
RHS =
Cond.getOperand(1);
19147 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19148 bool isInteger =
LHS.getValueType().isInteger();
19151 if (!isFloatingPoint && !isInteger)
19156 bool isNonEquality =
19158 if (!isEquality && !isNonEquality)
19161 SDValue ArgVal, ConstVal;
19175 if (isFloatingPoint) {
19177 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19180 const std::optional<int64_t> Val =
19189 if (!(isEquality && TrueVal == ConstVal) &&
19190 !(isNonEquality && FalseVal == ConstVal))
19194 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19195 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19198 SDValue SelectLHS = (isEquality &&
TrueVal == ConstVal) ? ArgVal :
TrueVal;
19199 SDValue SelectRHS =
19202 SelectLHS, SelectRHS);
19207 switch (
N->getOpcode()) {
19229 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19239 switch (
N->getOpcode()) {
19241 return performAddCombine(
N, DCI);
19243 return performPtrAddCombine(
N, DCI);
19245 return performSubCombine(
N, DCI);
19247 return performFAddCombine(
N, DCI);
19249 return performFSubCombine(
N, DCI);
19251 return performFDivCombine(
N, DCI);
19253 return performFMulCombine(
N, DCI);
19255 return performSetCCCombine(
N, DCI);
19257 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19259 if (
auto Res = performSelectCombine(
N, DCI))
19274 case AMDGPUISD::FMIN_LEGACY:
19275 case AMDGPUISD::FMAX_LEGACY:
19276 return performMinMaxCombine(
N, DCI);
19278 return performFMACombine(
N, DCI);
19280 return performAndCombine(
N, DCI);
19282 return performOrCombine(
N, DCI);
19285 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19286 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19292 return performXorCombine(
N, DCI);
19295 return performZeroOrAnyExtendCombine(
N, DCI);
19297 return performSignExtendInRegCombine(
N, DCI);
19298 case AMDGPUISD::FP_CLASS:
19299 return performClassCombine(
N, DCI);
19301 return performFCanonicalizeCombine(
N, DCI);
19302 case AMDGPUISD::RCP:
19303 return performRcpCombine(
N, DCI);
19305 case AMDGPUISD::FRACT:
19306 case AMDGPUISD::RSQ:
19307 case AMDGPUISD::RCP_LEGACY:
19308 case AMDGPUISD::RCP_IFLAG:
19309 case AMDGPUISD::RSQ_CLAMP: {
19318 return performUCharToFloatCombine(
N, DCI);
19320 return performFCopySignCombine(
N, DCI);
19321 case AMDGPUISD::CVT_F32_UBYTE0:
19322 case AMDGPUISD::CVT_F32_UBYTE1:
19323 case AMDGPUISD::CVT_F32_UBYTE2:
19324 case AMDGPUISD::CVT_F32_UBYTE3:
19325 return performCvtF32UByteNCombine(
N, DCI);
19326 case AMDGPUISD::FMED3:
19327 return performFMed3Combine(
N, DCI);
19328 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19329 return performCvtPkRTZCombine(
N, DCI);
19330 case AMDGPUISD::CLAMP:
19331 return performClampCombine(
N, DCI);
19334 EVT VT =
N->getValueType(0);
19337 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19340 EVT EltVT = Src.getValueType();
19341 if (EltVT != MVT::i16)
19351 return performExtractVectorEltCombine(
N, DCI);
19353 return performInsertVectorEltCombine(
N, DCI);
19355 return performFPRoundCombine(
N, DCI);
19364 return performMemSDNodeCombine(MemNode, DCI);
19395 unsigned Opcode =
Node->getMachineOpcode();
19398 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19399 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19402 SDNode *
Users[5] = {
nullptr};
19404 unsigned DmaskIdx =
19405 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19406 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19407 unsigned NewDmask = 0;
19408 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19409 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19410 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19411 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19412 unsigned TFCLane = 0;
19413 bool HasChain =
Node->getNumValues() > 1;
19415 if (OldDmask == 0) {
19423 TFCLane = OldBitsSet;
19427 for (SDUse &Use :
Node->uses()) {
19430 if (
Use.getResNo() != 0)
19433 SDNode *
User =
Use.getUser();
19436 if (!
User->isMachineOpcode() ||
19437 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19449 if (UsesTFC && Lane == TFCLane) {
19454 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19456 Dmask &= ~(1 << Comp);
19464 NewDmask |= 1 << Comp;
19469 bool NoChannels = !NewDmask;
19476 if (OldBitsSet == 1)
19482 if (NewDmask == OldDmask)
19491 unsigned NewChannels = BitsSet + UsesTFC;
19495 assert(NewOpcode != -1 &&
19496 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19497 "failed to find equivalent MIMG op");
19505 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19507 MVT ResultVT = NewChannels == 1
19510 : NewChannels == 5 ? 8
19512 SDVTList NewVTList =
19515 MachineSDNode *NewNode =
19524 if (NewChannels == 1) {
19534 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19539 if (i || !NoChannels)
19544 if (NewUser != User) {
19554 Idx = AMDGPU::sub1;
19557 Idx = AMDGPU::sub2;
19560 Idx = AMDGPU::sub3;
19563 Idx = AMDGPU::sub4;
19574 Op =
Op.getOperand(0);
19599 Node->getOperand(0), SL, VReg, SrcVal,
19605 return ToResultReg.
getNode();
19610 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19612 Ops.push_back(
Node->getOperand(i));
19618 Node->getOperand(i).getValueType(),
19619 Node->getOperand(i)),
19631 unsigned Opcode =
Node->getMachineOpcode();
19633 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19634 !
TII->isGather4(Opcode) &&
19636 return adjustWritemask(
Node, DAG);
19639 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19645 case AMDGPU::V_DIV_SCALE_F32_e64:
19646 case AMDGPU::V_DIV_SCALE_F64_e64: {
19656 (Src0 == Src1 || Src0 == Src2))
19712 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19713 unsigned InitIdx = 0;
19715 if (
TII->isImage(
MI)) {
19723 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19724 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19725 unsigned D16Val = D16 ? D16->getImm() : 0;
19727 if (!TFEVal && !LWEVal)
19738 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19740 unsigned dmask = MO_Dmask->
getImm();
19745 bool Packed = !Subtarget->hasUnpackedD16VMem();
19747 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19754 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19755 if (DstSize < InitIdx)
19759 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
19768 unsigned NewDst = 0;
19773 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19774 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19777 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19798 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
19810 if (
TII->isVOP3(
MI.getOpcode())) {
19812 TII->legalizeOperandsVOP3(MRI,
MI);
19814 if (
TII->isMAI(
MI)) {
19819 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19820 AMDGPU::OpName::scale_src0);
19821 if (Src0Idx != -1) {
19822 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19823 AMDGPU::OpName::scale_src1);
19824 if (
TII->usesConstantBus(MRI,
MI, Src0Idx) &&
19825 TII->usesConstantBus(MRI,
MI, Src1Idx))
19826 TII->legalizeOpWithMove(
MI, Src1Idx);
19833 if (
TII->isImage(
MI))
19834 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
19876 uint64_t RsrcDword2And3)
const {
19906std::pair<unsigned, const TargetRegisterClass *>
19913 if (Constraint.
size() == 1) {
19917 if (VT == MVT::Other)
19920 switch (Constraint[0]) {
19927 RC = &AMDGPU::SReg_32RegClass;
19930 RC = &AMDGPU::SGPR_64RegClass;
19935 return std::pair(0U,
nullptr);
19942 return std::pair(0U,
nullptr);
19944 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19945 : &AMDGPU::VGPR_32_Lo256RegClass;
19948 RC = Subtarget->has1024AddressableVGPRs()
19949 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
19952 return std::pair(0U,
nullptr);
19957 if (!Subtarget->hasMAIInsts())
19961 return std::pair(0U,
nullptr);
19963 RC = &AMDGPU::AGPR_32RegClass;
19968 return std::pair(0U,
nullptr);
19973 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
19977 RC = &AMDGPU::AV_32RegClass;
19980 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
19982 return std::pair(0U,
nullptr);
19991 return std::pair(0U, RC);
19994 if (Kind !=
'\0') {
19996 RC = &AMDGPU::VGPR_32_Lo256RegClass;
19997 }
else if (Kind ==
's') {
19998 RC = &AMDGPU::SGPR_32RegClass;
19999 }
else if (Kind ==
'a') {
20000 RC = &AMDGPU::AGPR_32RegClass;
20006 return std::pair(0U,
nullptr);
20012 return std::pair(0U,
nullptr);
20016 RC =
TRI->getVGPRClassForBitWidth(Width);
20018 RC =
TRI->getSGPRClassForBitWidth(Width);
20020 RC =
TRI->getAGPRClassForBitWidth(Width);
20022 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20027 return std::pair(0U,
nullptr);
20029 return std::pair(Reg, RC);
20038 return std::pair(0U,
nullptr);
20039 if (RC && Idx < RC->getNumRegs())
20041 return std::pair(0U,
nullptr);
20047 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20053 if (Constraint.
size() == 1) {
20054 switch (Constraint[0]) {
20064 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20072 if (Constraint.
size() == 1) {
20073 switch (Constraint[0]) {
20081 }
else if (Constraint.
size() == 2) {
20082 if (Constraint ==
"VA")
20100 std::vector<SDValue> &
Ops,
20115 unsigned Size =
Op.getScalarValueSizeInBits();
20119 if (
Size == 16 && !Subtarget->has16BitInsts())
20123 Val =
C->getSExtValue();
20127 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20131 if (
Size != 16 ||
Op.getNumOperands() != 2)
20133 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20136 Val =
C->getSExtValue();
20140 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20149 uint64_t Val)
const {
20150 if (Constraint.
size() == 1) {
20151 switch (Constraint[0]) {
20166 }
else if (Constraint.
size() == 2) {
20167 if (Constraint ==
"DA") {
20168 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20169 int64_t LoBits =
static_cast<int32_t
>(Val);
20173 if (Constraint ==
"DB") {
20181 unsigned MaxSize)
const {
20182 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20183 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20185 MVT VT =
Op.getSimpleValueType();
20210 switch (UnalignedClassID) {
20211 case AMDGPU::VReg_64RegClassID:
20212 return AMDGPU::VReg_64_Align2RegClassID;
20213 case AMDGPU::VReg_96RegClassID:
20214 return AMDGPU::VReg_96_Align2RegClassID;
20215 case AMDGPU::VReg_128RegClassID:
20216 return AMDGPU::VReg_128_Align2RegClassID;
20217 case AMDGPU::VReg_160RegClassID:
20218 return AMDGPU::VReg_160_Align2RegClassID;
20219 case AMDGPU::VReg_192RegClassID:
20220 return AMDGPU::VReg_192_Align2RegClassID;
20221 case AMDGPU::VReg_224RegClassID:
20222 return AMDGPU::VReg_224_Align2RegClassID;
20223 case AMDGPU::VReg_256RegClassID:
20224 return AMDGPU::VReg_256_Align2RegClassID;
20225 case AMDGPU::VReg_288RegClassID:
20226 return AMDGPU::VReg_288_Align2RegClassID;
20227 case AMDGPU::VReg_320RegClassID:
20228 return AMDGPU::VReg_320_Align2RegClassID;
20229 case AMDGPU::VReg_352RegClassID:
20230 return AMDGPU::VReg_352_Align2RegClassID;
20231 case AMDGPU::VReg_384RegClassID:
20232 return AMDGPU::VReg_384_Align2RegClassID;
20233 case AMDGPU::VReg_512RegClassID:
20234 return AMDGPU::VReg_512_Align2RegClassID;
20235 case AMDGPU::VReg_1024RegClassID:
20236 return AMDGPU::VReg_1024_Align2RegClassID;
20237 case AMDGPU::AReg_64RegClassID:
20238 return AMDGPU::AReg_64_Align2RegClassID;
20239 case AMDGPU::AReg_96RegClassID:
20240 return AMDGPU::AReg_96_Align2RegClassID;
20241 case AMDGPU::AReg_128RegClassID:
20242 return AMDGPU::AReg_128_Align2RegClassID;
20243 case AMDGPU::AReg_160RegClassID:
20244 return AMDGPU::AReg_160_Align2RegClassID;
20245 case AMDGPU::AReg_192RegClassID:
20246 return AMDGPU::AReg_192_Align2RegClassID;
20247 case AMDGPU::AReg_256RegClassID:
20248 return AMDGPU::AReg_256_Align2RegClassID;
20249 case AMDGPU::AReg_512RegClassID:
20250 return AMDGPU::AReg_512_Align2RegClassID;
20251 case AMDGPU::AReg_1024RegClassID:
20252 return AMDGPU::AReg_1024_Align2RegClassID;
20268 if (Info->isEntryFunction()) {
20275 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20277 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20278 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20279 &AMDGPU::SGPR_64RegClass);
20280 Info->setSGPRForEXECCopy(SReg);
20282 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20283 Info->getStackPtrOffsetReg()));
20284 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20285 MRI.
replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20289 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20290 MRI.
replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20292 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20295 Info->limitOccupancy(MF);
20297 if (ST.isWave32() && !MF.
empty()) {
20298 for (
auto &
MBB : MF) {
20299 for (
auto &
MI :
MBB) {
20300 TII->fixImplicitOperands(
MI);
20310 if (ST.needsAlignedVGPRs()) {
20317 if (NewClassID != -1)
20327 const APInt &DemandedElts,
20329 unsigned Depth)
const {
20331 unsigned Opc =
Op.getOpcode();
20334 unsigned IID =
Op.getConstantOperandVal(0);
20336 case Intrinsic::amdgcn_mbcnt_lo:
20337 case Intrinsic::amdgcn_mbcnt_hi: {
20342 Known.Zero.setBitsFrom(
20343 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20369 unsigned MaxValue =
20376 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20380 unsigned Src1Cst = 0;
20381 if (Src1.
isImm()) {
20382 Src1Cst = Src1.
getImm();
20383 }
else if (Src1.
isReg()) {
20387 Src1Cst = Cst->Value.getZExtValue();
20398 if (Width >= BFEWidth)
20415 unsigned Depth)
const {
20418 switch (
MI->getOpcode()) {
20419 case AMDGPU::S_BFE_I32:
20422 case AMDGPU::S_BFE_U32:
20425 case AMDGPU::S_BFE_I64:
20428 case AMDGPU::S_BFE_U64:
20431 case AMDGPU::G_INTRINSIC:
20432 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20435 case Intrinsic::amdgcn_workitem_id_x:
20438 case Intrinsic::amdgcn_workitem_id_y:
20441 case Intrinsic::amdgcn_workitem_id_z:
20444 case Intrinsic::amdgcn_mbcnt_lo:
20445 case Intrinsic::amdgcn_mbcnt_hi: {
20448 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20457 case Intrinsic::amdgcn_groupstaticsize: {
20461 Known.Zero.setHighBits(
20468 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20469 Known.Zero.setHighBits(24);
20471 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20472 Known.Zero.setHighBits(16);
20474 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20477 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20479 case AMDGPU::G_AMDGPU_SMED3:
20480 case AMDGPU::G_AMDGPU_UMED3: {
20481 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20508 unsigned Depth)
const {
20517 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20535 if (Header->getAlignment() != PrefAlign)
20536 return Header->getAlignment();
20537 if (needsFetchWindowAlignment(*Header))
20558 if (Header->getAlignment() != PrefAlign)
20559 return Header->getAlignment();
20561 unsigned LoopSize = 0;
20566 LoopSize +=
MBB->getAlignment().value() / 2;
20569 LoopSize +=
TII->getInstSizeInBytes(
MI);
20570 if (LoopSize > 192)
20575 if (LoopSize <= 64)
20578 if (LoopSize <= 128)
20579 return CacheLineAlign;
20585 auto I = Exit->getFirstNonDebugInstr();
20586 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20587 return CacheLineAlign;
20596 if (PreTerm == Pre->
begin() ||
20597 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20601 auto ExitHead = Exit->getFirstNonDebugInstr();
20602 if (ExitHead == Exit->end() ||
20603 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20608 return CacheLineAlign;
20616 if (needsFetchWindowAlignment(*
MBB))
20621bool SITargetLowering::needsFetchWindowAlignment(
20623 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20627 if (
MI.isMetaInstruction())
20630 return TII->getInstSizeInBytes(
MI) > 4;
20640 N =
N->getOperand(0).getNode();
20650 switch (
N->getOpcode()) {
20658 if (Reg.isPhysical() || MRI.
isLiveIn(Reg))
20659 return !
TRI->isSGPRReg(MRI, Reg);
20665 return !
TRI->isSGPRReg(MRI, Reg);
20669 unsigned AS = L->getAddressSpace();
20679 case AMDGPUISD::ATOMIC_CMP_SWAP:
20680 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20681 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20682 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20683 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20684 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20685 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20686 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20687 case AMDGPUISD::BUFFER_ATOMIC_AND:
20688 case AMDGPUISD::BUFFER_ATOMIC_OR:
20689 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20690 case AMDGPUISD::BUFFER_ATOMIC_INC:
20691 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20692 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20693 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20694 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20695 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20701 return A->readMem() &&
A->writeMem();
20722 switch (Ty.getScalarSizeInBits()) {
20734 const APInt &DemandedElts,
20737 unsigned Depth)
const {
20738 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
20742 if (Info->getMode().DX10Clamp)
20754 if (RMW->
hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
20774 <<
"Hardware instruction generated for atomic "
20776 <<
" operation at memory scope " << MemScope;
20781 Type *EltTy = VT->getElementType();
20782 return VT->getNumElements() == 2 &&
20802 unsigned BW =
IT->getBitWidth();
20803 return BW == 32 || BW == 64;
20817 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
20818 return BW == 32 || BW == 64;
20821 if (Ty->isFloatTy() || Ty->isDoubleTy())
20825 return VT->getNumElements() == 2 &&
20826 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20836 bool HasSystemScope) {
20843 if (HasSystemScope) {
20844 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20847 if (Subtarget.hasEmulatedSystemScopeAtomics())
20849 }
else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20852 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory");
20865 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
20873 return STI.hasGloballyAddressableScratch()
20891 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
20904 bool HasSystemScope =
20938 if (!
IT ||
IT->getBitWidth() != 32)
20944 if (Subtarget->hasEmulatedSystemScopeAtomics())
20960 if (!HasSystemScope &&
20961 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
20973 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
20982 ConstVal && ConstVal->isNullValue() &&
21021 if (Ty->isFloatTy()) {
21026 if (Ty->isDoubleTy()) {
21047 if (Ty->isFloatTy() &&
21048 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
21061 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21065 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21069 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21074 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21079 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21083 if (Ty->isFloatTy()) {
21086 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21089 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21094 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21102 if (Subtarget->hasFlatAtomicFaddF32Inst())
21111 if (Subtarget->hasLDSFPAtomicAddF32()) {
21112 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21114 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21142 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21144 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21148 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21150 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21204 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21205 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21206 : &AMDGPU::SReg_32RegClass;
21207 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21208 return TRI->getEquivalentSGPRClass(RC);
21209 if (
TRI->isSGPRClass(RC) && isDivergent) {
21210 if (Subtarget->hasGFX90AInsts())
21211 return TRI->getEquivalentAVClass(RC);
21212 return TRI->getEquivalentVGPRClass(RC);
21225 unsigned WaveSize) {
21230 if (!
IT ||
IT->getBitWidth() != WaveSize)
21235 if (!Visited.
insert(V).second)
21237 bool Result =
false;
21238 for (
const auto *U : V->users()) {
21240 if (V == U->getOperand(1)) {
21245 case Intrinsic::amdgcn_if_break:
21246 case Intrinsic::amdgcn_if:
21247 case Intrinsic::amdgcn_else:
21252 if (V == U->getOperand(0)) {
21257 case Intrinsic::amdgcn_end_cf:
21258 case Intrinsic::amdgcn_loop:
21264 Result =
hasCFUser(U, Visited, WaveSize);
21273 const Value *V)
const {
21275 if (CI->isInlineAsm()) {
21284 for (
auto &TC : TargetConstraints) {
21298 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21333 if (
I.getMetadata(
"amdgpu.noclobber"))
21335 if (
I.getMetadata(
"amdgpu.last.use"))
21399 Alignment = RMW->getAlign();
21412 bool FullFlatEmulation =
21414 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21415 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21416 RMW->getType()->isDoubleTy()));
21419 bool ReturnValueIsUsed = !AI->
use_empty();
21428 if (FullFlatEmulation) {
21439 std::prev(BB->
end())->eraseFromParent();
21440 Builder.SetInsertPoint(BB);
21442 Value *LoadedShared =
nullptr;
21443 if (FullFlatEmulation) {
21444 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21445 {Addr},
nullptr,
"is.shared");
21446 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21447 Builder.SetInsertPoint(SharedBB);
21448 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21454 LoadedShared = Clone;
21456 Builder.CreateBr(PhiBB);
21457 Builder.SetInsertPoint(CheckPrivateBB);
21460 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21461 {Addr},
nullptr,
"is.private");
21462 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21464 Builder.SetInsertPoint(PrivateBB);
21466 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21469 Value *LoadedPrivate;
21471 LoadedPrivate = Builder.CreateAlignedLoad(
21472 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21476 LoadedPrivate, RMW->getValOperand());
21478 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21479 RMW->isVolatile());
21487 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21490 Builder.CreateBr(PhiBB);
21492 Builder.SetInsertPoint(GlobalBB);
21496 if (FullFlatEmulation) {
21497 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21506 if (!FullFlatEmulation) {
21511 MDNode *RangeNotPrivate =
21514 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21518 Builder.CreateBr(PhiBB);
21520 Builder.SetInsertPoint(PhiBB);
21522 if (ReturnValueIsUsed) {
21525 if (FullFlatEmulation)
21526 Loaded->addIncoming(LoadedShared, SharedBB);
21527 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21528 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21529 Loaded->takeName(AI);
21532 Builder.CreateBr(ExitBB);
21536 unsigned PtrOpIdx) {
21537 Value *PtrOp =
I->getOperand(PtrOpIdx);
21544 I->setOperand(PtrOpIdx, ASCast);
21556 ConstVal && ConstVal->isNullValue() &&
21587 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21595 "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.
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)
LLVM_READONLY int32_t getVOPe64(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(SDNode *N, const SelectionDAG *DAG, 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