47#include "llvm/IR/IntrinsicsAMDGPU.h"
48#include "llvm/IR/IntrinsicsR600.h"
61#define DEBUG_TYPE "si-lower"
67 cl::desc(
"Do not align and prefetch loops"),
71 "amdgpu-use-divergent-register-indexing",
cl::Hidden,
72 cl::desc(
"Use indirect register addressing for divergent indexes"),
90 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
91 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
93 return AMDGPU::SGPR0 +
Reg;
109 TRI->getDefaultVectorSuperClassForBitWidth(32);
115 TRI->getDefaultVectorSuperClassForBitWidth(64);
153 TRI->getDefaultVectorSuperClassForBitWidth(320));
157 TRI->getDefaultVectorSuperClassForBitWidth(352));
161 TRI->getDefaultVectorSuperClassForBitWidth(384));
165 TRI->getDefaultVectorSuperClassForBitWidth(512));
172 TRI->getDefaultVectorSuperClassForBitWidth(1024));
174 if (Subtarget->has16BitInsts()) {
175 if (Subtarget->useRealTrue16Insts()) {
205 TRI->getDefaultVectorSuperClassForBitWidth(1024));
221 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
222 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
223 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
224 MVT::i1, MVT::v32i32},
228 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
229 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
230 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
231 MVT::i1, MVT::v32i32},
249 if (Subtarget->hasBF16PackedInsts()) {
316 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
323 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
324 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
325 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
328 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
329 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
330 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
334 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
335 MVT::v3i16, MVT::v4i16, MVT::Other},
340 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
356 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
357 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
358 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
359 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
360 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
361 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
362 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
363 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
398 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
412 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
426 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
440 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
454 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
469 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
470 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
473 if (Subtarget->hasPkMovB32()) {
494 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
495 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
500 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
504 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
505 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
506 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
507 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
531 if (Subtarget->hasSMemRealTime() ||
536 if (Subtarget->has16BitInsts()) {
546 if (Subtarget->hasMadMacF32Insts())
564 if (Subtarget->hasIntClamp())
567 if (Subtarget->hasAddNoCarryInsts())
573 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
576 {MVT::f64, MVT::f32},
Legal);
580 {MVT::f64, MVT::f32},
Custom);
585 {MVT::f64, MVT::f32},
Legal);
588 if (Subtarget->haveRoundOpsF64())
618 if (Subtarget->has16BitInsts()) {
666 if (!Subtarget->useRealTrue16Insts() ||
667 !Subtarget->d16PreservesUnusedBits()) {
668 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
674 if (!Subtarget->useRealTrue16Insts()) {
675 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
687 if (Subtarget->hasBF16TransInsts())
703 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
704 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
705 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
740 if (Subtarget->hasVCvtPkIU16F32())
743 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
750 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
850 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
851 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
852 MVT::v32f16, MVT::v32bf16},
854 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
861 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
Custom);
872 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
876 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
881 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
882 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
889 if (Subtarget->hasVOP3PInsts()) {
900 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
903 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
904 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
905 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
908 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
916 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
922 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
932 {MVT::v2f16, MVT::v4f16},
Custom);
938 if (Subtarget->hasBF16PackedInsts()) {
944 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
952 if (Subtarget->hasAnyPackedFP32Ops()) {
956 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
959 if (Subtarget->hasAnyPackedFP64Ops()) {
965 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
967 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
974 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
983 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
988 if (Subtarget->hasAnyPackedU64Ops()) {
992 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
999 if (Subtarget->has16BitInsts()) {
1014 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1015 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1016 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1017 MVT::v32f16, MVT::v32bf16},
1022 if (Subtarget->useVMulU64Inst())
1024 else if (Subtarget->hasScalarSMulU64())
1027 if (Subtarget->hasMad64_32())
1030 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1036 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1038 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
1041 if (Subtarget->hasMinimum3Maximum3F32())
1044 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1048 if (!Subtarget->hasMinimum3Maximum3F16())
1054 if (Subtarget->hasVOP3PInsts()) {
1057 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1061 if (Subtarget->useMinMaxI64Insts())
1066 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1067 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1072 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1073 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1074 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1075 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1090 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1095 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1096 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1097 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1098 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1113 if (Subtarget->hasBF16ConversionInsts()) {
1115 {MVT::bf16, MVT::v2bf16},
Custom);
1119 if (Subtarget->hasBF16TransInsts()) {
1123 const bool HasE5M3ConversionInsts =
1124 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1125 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1136 if (Subtarget->hasFP8F16ConversionInsts()) {
1141 if (Subtarget->hasCvtPkF16F32Inst()) {
1143 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1196 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1237 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1250 EVT DestVT,
EVT SrcVT)
const {
1252 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1255 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1262 LLT DestTy,
LLT SrcTy)
const {
1263 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1264 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1266 SrcTy.getScalarSizeInBits() == 16 &&
1287 return Subtarget->has16BitInsts()
1293 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1297 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1319 return (NumElts + 1) / 2;
1325 return NumElts * ((
Size + 31) / 32);
1334 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1343 MVT SimpleIntermediateVT =
1345 IntermediateVT = SimpleIntermediateVT;
1346 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1347 NumIntermediates = (NumElts + 1) / 2;
1348 return (NumElts + 1) / 2;
1353 IntermediateVT = RegisterVT;
1354 NumIntermediates = NumElts;
1355 return NumIntermediates;
1360 RegisterVT = MVT::i16;
1361 IntermediateVT = ScalarVT;
1362 NumIntermediates = NumElts;
1363 return NumIntermediates;
1367 RegisterVT = MVT::i32;
1368 IntermediateVT = ScalarVT;
1369 NumIntermediates = NumElts;
1370 return NumIntermediates;
1374 RegisterVT = MVT::i32;
1375 IntermediateVT = RegisterVT;
1376 NumIntermediates = NumElts * ((
Size + 31) / 32);
1377 return NumIntermediates;
1382 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1387 unsigned MaxNumLanes) {
1388 assert(MaxNumLanes != 0);
1392 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1397 return TLI.getValueType(
DL, Ty);
1403 unsigned MaxNumLanes) {
1409 assert(ST->getNumContainedTypes() == 2 &&
1410 ST->getContainedType(1)->isIntegerTy(32));
1424 return MVT::amdgpuBufferFatPointer;
1426 DL.getPointerSizeInBits(AS) == 192)
1427 return MVT::amdgpuBufferStridedPointer;
1436 DL.getPointerSizeInBits(AS) == 160) ||
1438 DL.getPointerSizeInBits(AS) == 192))
1445 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1446 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1447 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1449 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1450 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1451 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1452 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1453 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1454 case Intrinsic::amdgcn_flat_load_monitor_b32:
1455 case Intrinsic::amdgcn_global_load_monitor_b32:
1457 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1458 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1459 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1460 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1461 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1462 case Intrinsic::amdgcn_flat_load_monitor_b64:
1463 case Intrinsic::amdgcn_global_load_monitor_b64:
1465 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1466 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1467 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1468 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1469 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1470 case Intrinsic::amdgcn_flat_load_monitor_b128:
1471 case Intrinsic::amdgcn_global_load_monitor_b128:
1507 unsigned IntrID)
const {
1509 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1523 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1537 if (RsrcIntr->IsImage) {
1552 Info.ptrVal = RsrcArg;
1556 if (RsrcIntr->IsImage) {
1557 unsigned MaxNumLanes = 4;
1572 std::numeric_limits<unsigned>::max());
1582 if (RsrcIntr->IsImage) {
1602 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1604 Info.memVT = MVT::i32;
1611 case Intrinsic::amdgcn_raw_buffer_load_lds:
1612 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1613 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1614 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1615 case Intrinsic::amdgcn_struct_buffer_load_lds:
1616 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1617 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1618 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1632 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1641 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1642 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1643 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1644 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1647 std::numeric_limits<unsigned>::max());
1660 case Intrinsic::amdgcn_ds_ordered_add:
1661 case Intrinsic::amdgcn_ds_ordered_swap: {
1675 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1676 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1679 Info.ptrVal =
nullptr;
1685 case Intrinsic::amdgcn_ds_append:
1686 case Intrinsic::amdgcn_ds_consume: {
1700 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1701 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1702 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1707 Info.memVT = MVT::i64;
1715 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1716 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1717 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1720 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1723 ->getElementType(0));
1732 case Intrinsic::amdgcn_global_atomic_fmin_num:
1733 case Intrinsic::amdgcn_global_atomic_fmax_num:
1734 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1735 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1736 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1747 case Intrinsic::amdgcn_cluster_load_b32:
1748 case Intrinsic::amdgcn_cluster_load_b64:
1749 case Intrinsic::amdgcn_cluster_load_b128:
1750 case Intrinsic::amdgcn_ds_load_tr6_b96:
1751 case Intrinsic::amdgcn_ds_load_tr4_b64:
1752 case Intrinsic::amdgcn_ds_load_tr8_b64:
1753 case Intrinsic::amdgcn_ds_load_tr16_b128:
1754 case Intrinsic::amdgcn_global_load_tr6_b96:
1755 case Intrinsic::amdgcn_global_load_tr4_b64:
1756 case Intrinsic::amdgcn_global_load_tr_b64:
1757 case Intrinsic::amdgcn_global_load_tr_b128:
1758 case Intrinsic::amdgcn_ds_read_tr4_b64:
1759 case Intrinsic::amdgcn_ds_read_tr6_b96:
1760 case Intrinsic::amdgcn_ds_read_tr8_b64:
1761 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1770 case Intrinsic::amdgcn_flat_load_monitor_b32:
1771 case Intrinsic::amdgcn_flat_load_monitor_b64:
1772 case Intrinsic::amdgcn_flat_load_monitor_b128:
1773 case Intrinsic::amdgcn_global_load_monitor_b32:
1774 case Intrinsic::amdgcn_global_load_monitor_b64:
1775 case Intrinsic::amdgcn_global_load_monitor_b128: {
1786 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1787 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1788 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1799 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1800 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1801 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1812 case Intrinsic::amdgcn_ds_gws_init:
1813 case Intrinsic::amdgcn_ds_gws_barrier:
1814 case Intrinsic::amdgcn_ds_gws_sema_v:
1815 case Intrinsic::amdgcn_ds_gws_sema_br:
1816 case Intrinsic::amdgcn_ds_gws_sema_p:
1817 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1827 Info.memVT = MVT::i32;
1829 Info.align =
Align(4);
1831 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1838 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1839 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1840 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1841 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1842 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1843 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1844 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1845 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1860 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1861 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1862 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1863 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1878 case Intrinsic::amdgcn_av_load_b8:
1879 case Intrinsic::amdgcn_av_load_b16:
1880 case Intrinsic::amdgcn_av_load_b32:
1881 case Intrinsic::amdgcn_av_load_b64:
1882 case Intrinsic::amdgcn_av_load_b128:
1883 case Intrinsic::amdgcn_av_store_b8:
1884 case Intrinsic::amdgcn_av_store_b16:
1885 case Intrinsic::amdgcn_av_store_b32:
1886 case Intrinsic::amdgcn_av_store_b64:
1887 case Intrinsic::amdgcn_av_store_b128: {
1893 Info.align =
Align(Info.memVT.getStoreSize());
1901 unsigned ScopeIdx = CI.
arg_size() - 1;
1905 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1909 case Intrinsic::amdgcn_load_to_lds:
1910 case Intrinsic::amdgcn_load_async_to_lds:
1911 case Intrinsic::amdgcn_global_load_lds:
1912 case Intrinsic::amdgcn_global_load_async_lds: {
1931 Width * 8 * Subtarget->getWavefrontSize());
1937 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1938 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1939 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1940 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1950 Info.memVT = MVT::i32;
1952 Info.align =
Align(4);
1958 case Intrinsic::amdgcn_s_prefetch_data:
1959 case Intrinsic::amdgcn_s_prefetch_inst:
1960 case Intrinsic::amdgcn_flat_prefetch:
1961 case Intrinsic::amdgcn_global_prefetch: {
1976 Type *&AccessTy)
const {
1977 Value *Ptr =
nullptr;
1978 switch (
II->getIntrinsicID()) {
1979 case Intrinsic::amdgcn_cluster_load_b128:
1980 case Intrinsic::amdgcn_cluster_load_b64:
1981 case Intrinsic::amdgcn_cluster_load_b32:
1982 case Intrinsic::amdgcn_ds_append:
1983 case Intrinsic::amdgcn_ds_consume:
1984 case Intrinsic::amdgcn_ds_load_tr8_b64:
1985 case Intrinsic::amdgcn_ds_load_tr16_b128:
1986 case Intrinsic::amdgcn_ds_load_tr4_b64:
1987 case Intrinsic::amdgcn_ds_load_tr6_b96:
1988 case Intrinsic::amdgcn_ds_read_tr4_b64:
1989 case Intrinsic::amdgcn_ds_read_tr6_b96:
1990 case Intrinsic::amdgcn_ds_read_tr8_b64:
1991 case Intrinsic::amdgcn_ds_read_tr16_b64:
1992 case Intrinsic::amdgcn_ds_ordered_add:
1993 case Intrinsic::amdgcn_ds_ordered_swap:
1994 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1995 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1996 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1997 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1998 case Intrinsic::amdgcn_global_atomic_fmax_num:
1999 case Intrinsic::amdgcn_global_atomic_fmin_num:
2000 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
2001 case Intrinsic::amdgcn_global_load_tr_b64:
2002 case Intrinsic::amdgcn_global_load_tr_b128:
2003 case Intrinsic::amdgcn_global_load_tr4_b64:
2004 case Intrinsic::amdgcn_global_load_tr6_b96:
2005 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
2006 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
2007 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
2008 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
2009 case Intrinsic::amdgcn_av_load_b8:
2010 case Intrinsic::amdgcn_av_load_b16:
2011 case Intrinsic::amdgcn_av_load_b32:
2012 case Intrinsic::amdgcn_av_load_b64:
2013 case Intrinsic::amdgcn_av_load_b128:
2014 case Intrinsic::amdgcn_av_store_b8:
2015 case Intrinsic::amdgcn_av_store_b16:
2016 case Intrinsic::amdgcn_av_store_b32:
2017 case Intrinsic::amdgcn_av_store_b64:
2018 case Intrinsic::amdgcn_av_store_b128:
2019 Ptr =
II->getArgOperand(0);
2021 case Intrinsic::amdgcn_load_to_lds:
2022 case Intrinsic::amdgcn_load_async_to_lds:
2023 case Intrinsic::amdgcn_global_load_lds:
2024 case Intrinsic::amdgcn_global_load_async_lds:
2025 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2026 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2027 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2028 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2029 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2030 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2031 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2032 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2033 Ptr =
II->getArgOperand(1);
2038 AccessTy =
II->getType();
2044 unsigned AddrSpace)
const {
2045 if (!Subtarget->hasFlatInstOffsets()) {
2052 FlatAddrSpace FlatVariant =
2055 : FlatAddrSpace::FLAT;
2057 return AM.
Scale == 0 &&
2058 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2059 AM.
BaseOffs, AddrSpace, FlatVariant));
2063 if (Subtarget->hasFlatGlobalInsts())
2066 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2079 return isLegalMUBUFAddressingMode(AM);
2082bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2093 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2105 if (AM.HasBaseReg) {
2137 return isLegalMUBUFAddressingMode(AM);
2139 if (!Subtarget->hasScalarSubwordLoads()) {
2144 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2192 return Subtarget->hasFlatScratchEnabled()
2194 : isLegalMUBUFAddressingMode(AM);
2241 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2250 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2253 Align RequiredAlignment(
2255 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2256 Alignment < RequiredAlignment)
2271 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2277 RequiredAlignment =
Align(4);
2279 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2295 *IsFast = (Alignment >= RequiredAlignment) ? 64
2296 : (Alignment <
Align(4)) ? 32
2303 if (!Subtarget->hasDS96AndDS128())
2309 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2318 *IsFast = (Alignment >= RequiredAlignment) ? 96
2319 : (Alignment <
Align(4)) ? 32
2326 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2332 RequiredAlignment =
Align(8);
2334 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2343 *IsFast = (Alignment >= RequiredAlignment) ? 128
2344 : (Alignment <
Align(4)) ? 32
2361 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2363 return Alignment >= RequiredAlignment ||
2364 Subtarget->hasUnalignedDSAccessEnabled();
2372 bool AlignedBy4 = Alignment >=
Align(4);
2373 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2375 *IsFast = AlignedBy4 ?
Size : 1;
2380 *IsFast = AlignedBy4;
2391 return Alignment >=
Align(4) ||
2392 Subtarget->hasUnalignedBufferAccessEnabled();
2405 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2420 return Size >= 32 && Alignment >=
Align(4);
2425 unsigned *IsFast)
const {
2427 Alignment, Flags, IsFast);
2438 if (
Op.size() >= 16 &&
2442 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2460 unsigned DestAS)
const {
2463 Subtarget->hasGloballyAddressableScratch()) {
2494 unsigned Index)
const {
2508 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2513 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2540 if (Subtarget->hasScalarSubwordLoads() &&
N->getOpcode() ==
ISD::LOAD &&
2591 auto [InputPtrReg, RC, ArgTy] =
2601 Chain, SL,
MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2607 const SDLoc &SL)
const {
2614 const SDLoc &SL)
const {
2617 std::optional<uint32_t> KnownSize =
2619 if (KnownSize.has_value())
2646 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2661SDValue SITargetLowering::lowerKernargMemParameter(
2666 MachinePointerInfo PtrInfo =
2675 int64_t OffsetDiff =
Offset - AlignDownOffset;
2681 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2692 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2697 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2711 const SDLoc &SL)
const {
2780 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2783 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2784 if (ConvertedVal == ArgValue)
2785 return ConvertedVal;
2790SDValue SITargetLowering::lowerWorkGroupId(
2795 if (!Subtarget->hasClusters())
2796 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2804 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2805 SDLoc SL(ClusterIdXYZ);
2806 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2809 SDValue ClusterWorkGroupIdXYZ =
2810 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2820 return ClusterIdXYZ;
2822 using namespace AMDGPU::Hwreg;
2826 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2837SDValue SITargetLowering::getPreloadedValue(
2840 const ArgDescriptor *
Reg =
nullptr;
2845 const ArgDescriptor WorkGroupIDX =
2853 const ArgDescriptor WorkGroupIDZ =
2855 const ArgDescriptor ClusterWorkGroupIDX =
2857 const ArgDescriptor ClusterWorkGroupIDY =
2859 const ArgDescriptor ClusterWorkGroupIDZ =
2861 const ArgDescriptor ClusterWorkGroupMaxIDX =
2863 const ArgDescriptor ClusterWorkGroupMaxIDY =
2865 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2867 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2870 auto LoadConstant = [&](
unsigned N) {
2874 if (Subtarget->hasArchitectedSGPRs() &&
2882 Reg = &WorkGroupIDX;
2883 RC = &AMDGPU::SReg_32RegClass;
2887 Reg = &WorkGroupIDY;
2888 RC = &AMDGPU::SReg_32RegClass;
2892 Reg = &WorkGroupIDZ;
2893 RC = &AMDGPU::SReg_32RegClass;
2897 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2898 return LoadConstant(0);
2899 Reg = &ClusterWorkGroupIDX;
2900 RC = &AMDGPU::SReg_32RegClass;
2904 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2905 return LoadConstant(0);
2906 Reg = &ClusterWorkGroupIDY;
2907 RC = &AMDGPU::SReg_32RegClass;
2911 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2912 return LoadConstant(0);
2913 Reg = &ClusterWorkGroupIDZ;
2914 RC = &AMDGPU::SReg_32RegClass;
2919 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2920 Reg = &ClusterWorkGroupMaxIDX;
2921 RC = &AMDGPU::SReg_32RegClass;
2926 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2927 Reg = &ClusterWorkGroupMaxIDY;
2928 RC = &AMDGPU::SReg_32RegClass;
2933 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2934 Reg = &ClusterWorkGroupMaxIDZ;
2935 RC = &AMDGPU::SReg_32RegClass;
2939 Reg = &ClusterWorkGroupMaxFlatID;
2940 RC = &AMDGPU::SReg_32RegClass;
2971 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2975 "vector type argument should have been split");
2980 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2988 "unexpected vector split in ps argument type");
3002 Info->markPSInputAllocated(PSInputNum);
3004 Info->markPSInputEnabled(PSInputNum);
3020 if (Info.hasWorkItemIDX()) {
3022 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3026 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3030 if (Info.hasWorkItemIDY()) {
3031 assert(Info.hasWorkItemIDX());
3032 if (Subtarget->hasPackedTID()) {
3033 Info.setWorkItemIDY(
3036 unsigned Reg = AMDGPU::VGPR1;
3037 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3044 if (Info.hasWorkItemIDZ()) {
3045 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3046 if (Subtarget->hasPackedTID()) {
3047 Info.setWorkItemIDZ(
3050 unsigned Reg = AMDGPU::VGPR2;
3051 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3061 unsigned NumArgRegs) {
3064 if (RegIdx == ArgSGPRs.
size())
3067 unsigned Reg = ArgSGPRs[RegIdx];
3112 const unsigned Mask = 0x3ff;
3121 auto &
ArgInfo = Info.getArgInfo();
3133 if (Info.hasImplicitArgPtr())
3141 if (Info.hasWorkGroupIDX())
3144 if (Info.hasWorkGroupIDY())
3147 if (Info.hasWorkGroupIDZ())
3150 if (Info.hasLDSKernelId())
3161 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3162 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3168 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3169 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3174 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3175 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3181 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3187 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3196 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3201 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3202 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3207 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3208 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3223 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3225 bool InPreloadSequence =
true;
3227 bool AlignedForImplictArgs =
false;
3228 unsigned ImplicitArgOffset = 0;
3229 for (
auto &Arg :
F.args()) {
3230 if (!InPreloadSequence || !Arg.hasInRegAttr())
3233 unsigned ArgIdx = Arg.getArgNo();
3236 if (InIdx < Ins.
size() &&
3237 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3240 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3241 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3243 assert(ArgLocs[ArgIdx].isMemLoc());
3244 auto &ArgLoc = ArgLocs[InIdx];
3246 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3248 unsigned NumAllocSGPRs =
3249 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3252 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3253 if (!AlignedForImplictArgs) {
3255 alignTo(LastExplicitArgOffset,
3256 Subtarget->getAlignmentForImplicitArgPtr()) -
3257 LastExplicitArgOffset;
3258 AlignedForImplictArgs =
true;
3260 ArgOffset += ImplicitArgOffset;
3264 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3265 assert(InIdx >= 1 &&
"No previous SGPR");
3266 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3267 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3271 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3272 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3275 InPreloadSequence =
false;
3281 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3283 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3285 if (PreloadRegs->
size() > 1)
3286 RC = &AMDGPU::SGPR_32RegClass;
3287 for (
auto &Reg : *PreloadRegs) {
3293 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3302 if (Info.hasLDSKernelId()) {
3303 Register Reg = Info.addLDSKernelId();
3304 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3313 bool IsShader)
const {
3314 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3315 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3321 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3323 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3327 unsigned NumRequiredSystemSGPRs =
3328 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3329 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3330 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3331 Register Reg = Info.addReservedUserSGPR();
3332 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3337 if (!HasArchitectedSGPRs) {
3338 if (Info.hasWorkGroupIDX()) {
3339 Register Reg = Info.addWorkGroupIDX();
3340 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3344 if (Info.hasWorkGroupIDY()) {
3345 Register Reg = Info.addWorkGroupIDY();
3346 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3350 if (Info.hasWorkGroupIDZ()) {
3351 Register Reg = Info.addWorkGroupIDZ();
3352 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3357 if (Info.hasWorkGroupInfo()) {
3358 Register Reg = Info.addWorkGroupInfo();
3359 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3363 if (Info.hasPrivateSegmentWaveByteOffset()) {
3365 unsigned PrivateSegmentWaveByteOffsetReg;
3368 PrivateSegmentWaveByteOffsetReg =
3369 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3373 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3375 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3378 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3380 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3381 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3384 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3385 Info.getNumPreloadedSGPRs() >= 16);
3400 if (HasStackObjects)
3401 Info.setHasNonSpillStackObjects(
true);
3406 HasStackObjects =
true;
3410 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3412 if (!ST.hasFlatScratchEnabled()) {
3413 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3420 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3422 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3432 Info.setScratchRSrcReg(ReservedBufferReg);
3451 if (!
MRI.isLiveIn(AMDGPU::SGPR32)) {
3452 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3459 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3460 if (!
MRI.isLiveIn(
Reg)) {
3461 Info.setStackPtrOffsetReg(
Reg);
3466 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3473 if (ST.getFrameLowering()->hasFP(MF)) {
3474 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3490 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3499 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3500 RC = &AMDGPU::SGPR_64RegClass;
3501 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3502 RC = &AMDGPU::SGPR_32RegClass;
3508 Entry->addLiveIn(*
I);
3513 for (
auto *Exit : Exits)
3515 TII->get(TargetOpcode::COPY), *
I)
3530 bool IsError =
false;
3534 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3552 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3553 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3555 if (!Subtarget->hasFlatScratchEnabled())
3560 !Subtarget->hasArchitectedSGPRs())
3561 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3562 !Info->hasWorkGroupIDZ());
3565 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3583 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3584 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3587 Info->markPSInputAllocated(0);
3588 Info->markPSInputEnabled(0);
3590 if (Subtarget->isAmdPalOS()) {
3599 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3600 if ((PsInputBits & 0x7F) == 0 ||
3601 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3604 }
else if (IsKernel) {
3605 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3617 if (IsKernel && Subtarget->hasKernargPreload())
3621 }
else if (!IsGraphics) {
3626 if (!Subtarget->hasFlatScratchEnabled())
3638 Info->setNumWaveDispatchSGPRs(
3640 Info->setNumWaveDispatchVGPRs(
3642 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3643 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3648 if (IsWholeWaveFunc) {
3650 {MVT::i1, MVT::Other}, Chain);
3662 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3673 if (IsEntryFunc && VA.
isMemLoc()) {
3697 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3701 int64_t OffsetDiff =
Offset - AlignDownOffset;
3708 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3719 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3720 Ins[i].Flags.isSExt(), &Ins[i]);
3728 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3731 if (PreloadRegs.
size() == 1) {
3732 Register VReg =
MRI.getLiveInVirtReg(PreloadRegs[0]);
3737 TRI->getRegSizeInBits(*RC)));
3745 for (
auto Reg : PreloadRegs) {
3752 PreloadRegs.size()),
3769 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3770 Ins[i].Flags.isSExt(), &Ins[i]);
3782 "hidden argument in kernel signature was not preloaded",
3788 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3789 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3809 if (!IsEntryFunc && VA.
isMemLoc()) {
3810 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3821 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3822 RC = &AMDGPU::VGPR_32RegClass;
3823 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3824 RC = &AMDGPU::SGPR_32RegClass;
3830 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3836 ReadFirstLane, Val);
3845 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3854 Info->setBytesInStackArgArea(StackArgSize);
3856 return Chains.
empty() ? Chain
3865 const Type *RetTy)
const {
3873 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3878 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3879 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3880 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3881 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3904 Info->setIfReturnsVoid(Outs.
empty());
3905 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3924 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3925 ++
I, ++RealRVLocIdx) {
3929 SDValue Arg = OutVals[RealRVLocIdx];
3952 ReadFirstLane, Arg);
3959 if (!Info->isEntryFunction()) {
3965 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3967 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3980 unsigned Opc = AMDGPUISD::ENDPGM;
3982 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3983 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3984 : AMDGPUISD::RET_GLUE;
4089 const auto [OutgoingArg, ArgRC, ArgTy] =
4094 const auto [IncomingArg, IncomingArgRC, Ty] =
4096 assert(IncomingArgRC == ArgRC);
4099 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4107 InputReg = getImplicitArgPtr(DAG,
DL);
4109 std::optional<uint32_t> Id =
4111 if (Id.has_value()) {
4122 if (OutgoingArg->isRegister()) {
4123 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4124 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4127 unsigned SpecialArgOffset =
4138 auto [OutgoingArg, ArgRC, Ty] =
4141 std::tie(OutgoingArg, ArgRC, Ty) =
4144 std::tie(OutgoingArg, ArgRC, Ty) =
4159 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4160 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4161 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4166 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4174 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4184 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4193 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4194 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4205 : IncomingArgY ? *IncomingArgY
4212 if (OutgoingArg->isRegister()) {
4214 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4240 if (Callee->isDivergent())
4247 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4251 if (!CallerPreserved)
4254 bool CCMatch = CallerCC == CalleeCC;
4267 if (Arg.hasByValAttr())
4281 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4282 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4291 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4304 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4306 if (!CCVA.isRegLoc())
4311 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4313 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4337enum ChainCallArgIdx {
4359 bool UsesDynamicVGPRs =
false;
4360 if (IsChainCallConv) {
4365 auto RequestedExecIt =
4367 return Arg.OrigArgIndex == 2;
4369 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4371 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4374 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4377 "Haven't popped all the special args");
4380 CLI.
Args[ChainCallArgIdx::Exec];
4381 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4389 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4391 ChainCallSpecialArgs.
push_back(Arg.Node);
4394 PushNodeOrTargetConstant(RequestedExecArg);
4400 if (FlagsValue.
isZero()) {
4401 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4403 "no additional args allowed if flags == 0");
4405 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4409 if (!Subtarget->isWave32()) {
4411 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4414 UsesDynamicVGPRs =
true;
4415 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4416 CLI.
Args.end(), PushNodeOrTargetConstant);
4425 bool IsSibCall =
false;
4439 "unsupported call to variadic function ");
4447 "unsupported required tail call to function ");
4452 Outs, OutVals, Ins, DAG);
4456 "site marked musttail or on llvm.amdgcn.cs.chain");
4463 if (!TailCallOpt && IsTailCall)
4487 if (!Subtarget->hasFlatScratchEnabled()) {
4510 auto *
TRI = Subtarget->getRegisterInfo();
4517 if (!IsSibCall || IsChainCallConv) {
4518 if (!Subtarget->hasFlatScratchEnabled()) {
4524 RegsToPass.emplace_back(
4532 const unsigned NumSpecialInputs = RegsToPass.size();
4534 MVT PtrVT = MVT::i32;
4537 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4565 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4573 int32_t
Offset = LocMemOffset;
4580 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4586 ? Flags.getNonZeroByValAlign()
4613 if (Outs[i].Flags.isByVal()) {
4615 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4618 Outs[i].Flags.getNonZeroByValAlign(),
4619 Outs[i].Flags.getNonZeroByValAlign(),
4621 nullptr, std::nullopt, DstInfo,
4627 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4633 if (!MemOpChains.
empty())
4649 unsigned ArgIdx = 0;
4650 for (
auto [Reg, Val] : RegsToPass) {
4651 if (ArgIdx++ >= NumSpecialInputs &&
4652 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4678 if (IsTailCall && !IsSibCall) {
4683 std::vector<SDValue>
Ops({Chain});
4689 Ops.push_back(Callee);
4706 Ops.push_back(Callee);
4717 if (IsChainCallConv)
4722 for (
auto &[Reg, Val] : RegsToPass)
4726 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4727 assert(Mask &&
"Missing call preserved mask for calling convention");
4737 MVT::Glue, GlueOps),
4742 Ops.push_back(InGlue);
4748 unsigned OPC = AMDGPUISD::TC_RETURN;
4751 OPC = AMDGPUISD::TC_RETURN_GFX;
4755 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4756 : AMDGPUISD::TC_RETURN_CHAIN;
4762 if (Info->isWholeWaveFunction())
4763 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4773 Chain =
Call.getValue(0);
4774 InGlue =
Call.getValue(1);
4776 uint64_t CalleePopBytes = NumBytes;
4797 EVT VT =
Op.getValueType();
4811 "Stack grows upwards for AMDGPU");
4813 Chain = BaseAddr.getValue(1);
4815 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4816 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4819 if (Alignment > StackAlign) {
4820 uint64_t ScaledAlignment = Alignment.value()
4821 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4822 uint64_t StackAlignMask = ScaledAlignment - 1;
4829 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4838 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4849 if (!HasFlatScratch) {
4852 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4869 if (
Op.getValueType() != MVT::i32)
4888 assert(
Op.getValueType() == MVT::i32);
4897 Op.getOperand(0), IntrinID, GetRoundBothImm);
4931 SDValue RoundModeTimesNumBits =
4951 TableEntry, EnumOffset);
4967 static_cast<uint32_t>(ConstMode->getZExtValue()),
4979 if (UseReducedTable) {
4985 SDValue RoundModeTimesNumBits =
5005 SDValue RoundModeTimesNumBits =
5014 NewMode = TruncTable;
5023 ReadFirstLaneID, NewMode);
5036 IntrinID, RoundBothImm, NewMode);
5044 return Op.getOperand(0);
5049 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5067 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5068 EVT SrcVT = Src.getValueType();
5077 EVT DstVT =
Op.getValueType();
5086 if (
Op.getValueType() != MVT::i64)
5100 Op.getOperand(0), IntrinID, ModeHwRegImm);
5102 Op.getOperand(0), IntrinID, TrapHwRegImm);
5116 if (
Op.getOperand(1).getValueType() != MVT::i64)
5128 ReadFirstLaneID, NewModeReg);
5130 ReadFirstLaneID, NewTrapReg);
5132 unsigned ModeHwReg =
5135 unsigned TrapHwReg =
5143 IntrinID, ModeHwRegImm, NewModeReg);
5146 IntrinID, TrapHwRegImm, NewTrapReg);
5154 .
Case(
"m0", AMDGPU::M0)
5155 .
Case(
"exec", AMDGPU::EXEC)
5156 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5157 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5158 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5159 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5160 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5161 .
Case(
"src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5162 .
Case(
"src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5163 .
Case(
"src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5169 if (!Subtarget->hasFlatScrRegister() &&
5170 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5173 if (!Subtarget->hasGloballyAddressableScratch() &&
5174 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5179 case AMDGPU::EXEC_LO:
5180 case AMDGPU::EXEC_HI:
5181 case AMDGPU::FLAT_SCR_LO:
5182 case AMDGPU::FLAT_SCR_HI:
5183 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5184 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5189 case AMDGPU::FLAT_SCR:
5190 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5209 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5218static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5240 auto Next = std::next(
I);
5251 MBB.addSuccessor(LoopBB);
5253 return std::pair(LoopBB, RemainderBB);
5260 auto I =
MI.getIterator();
5261 auto E = std::next(
I);
5283 Src->setIsKill(
false);
5293 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5299 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5302 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5326 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5327 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5337 Register PhiExec =
MRI.createVirtualRegister(BoolRC);
5338 Register NewExec =
MRI.createVirtualRegister(BoolRC);
5340 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5341 Register CondReg =
MRI.createVirtualRegister(BoolRC);
5349 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5356 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5360 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5362 .
addReg(Idx.getReg(), {}, Idx.getSubReg());
5369 MRI.setSimpleHint(NewExec, CondReg);
5371 if (UseGPRIdxMode) {
5373 SGPRIdxReg = CurrentIdxReg;
5375 SGPRIdxReg =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5376 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5387 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5420 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5421 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5429 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5431 Register SaveExec =
MRI.createVirtualRegister(BoolXExecRC);
5432 Register TmpExec =
MRI.createVirtualRegister(BoolXExecRC);
5448 InitResultReg, DstReg, PhiReg, TmpExec,
5449 Offset, UseGPRIdxMode, SGPRIdxReg);
5455 LoopBB->removeSuccessor(RemainderBB);
5457 LoopBB->addSuccessor(LandingPad);
5468static std::pair<unsigned, int>
5472 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5477 return std::pair(AMDGPU::sub0,
Offset);
5491 assert(Idx->getReg() != AMDGPU::NoRegister);
5516 return Idx->getReg();
5518 Register Tmp =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5536 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5537 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5543 std::tie(SubReg,
Offset) =
5546 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5549 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5553 if (UseGPRIdxMode) {
5560 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5569 .
addReg(SrcReg, {}, SubReg)
5573 MI.eraseFromParent();
5582 Register PhiReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5583 Register InitReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5589 UseGPRIdxMode, SGPRIdxReg);
5593 if (UseGPRIdxMode) {
5595 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5597 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5602 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5603 .
addReg(SrcReg, {}, SubReg)
5607 MI.eraseFromParent();
5624 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5632 std::tie(SubReg,
Offset) =
5634 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5636 if (Idx->getReg() == AMDGPU::NoRegister) {
5647 MI.eraseFromParent();
5652 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5656 if (UseGPRIdxMode) {
5660 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5669 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5670 TRI.getRegSizeInBits(*VecRC), 32,
false);
5676 MI.eraseFromParent();
5686 Register PhiReg =
MRI.createVirtualRegister(VecRC);
5690 UseGPRIdxMode, SGPRIdxReg);
5693 if (UseGPRIdxMode) {
5695 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5697 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5703 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5704 TRI.getRegSizeInBits(*VecRC), 32,
false);
5705 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5711 MI.eraseFromParent();
5727 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5728 if (ST.hasScalarAddSub64()) {
5730 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5740 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5741 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5744 MI,
MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5746 MI,
MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5749 MI,
MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5751 MI,
MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5756 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5757 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5763 Hi.setOperandDead(3);
5770 MI.eraseFromParent();
5784 Register SrcCond =
MI.getOperand(3).getReg();
5786 Register DstLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5787 Register DstHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5789 Register SrcCondCopy =
MRI.createVirtualRegister(CondRC);
5792 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5794 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5796 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5798 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5801 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5803 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5806 MI,
MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5808 MI,
MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5811 MI,
MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5813 MI,
MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5835 MI.eraseFromParent();
5840 case AMDGPU::S_MIN_U32:
5841 return std::numeric_limits<uint32_t>::max();
5842 case AMDGPU::S_MIN_I32:
5843 return std::numeric_limits<int32_t>::max();
5844 case AMDGPU::S_MAX_U32:
5845 return std::numeric_limits<uint32_t>::min();
5846 case AMDGPU::S_MAX_I32:
5847 return std::numeric_limits<int32_t>::min();
5848 case AMDGPU::V_ADD_F32_e64:
5850 case AMDGPU::V_SUB_F32_e64:
5852 case AMDGPU::S_ADD_I32:
5853 case AMDGPU::S_SUB_I32:
5854 case AMDGPU::S_OR_B32:
5855 case AMDGPU::S_XOR_B32:
5856 return std::numeric_limits<uint32_t>::min();
5857 case AMDGPU::S_AND_B32:
5858 return std::numeric_limits<uint32_t>::max();
5859 case AMDGPU::V_MIN_F32_e64:
5860 case AMDGPU::V_MAX_F32_e64:
5862 case AMDGPU::V_CMP_LT_U64_e64:
5863 return std::numeric_limits<uint64_t>::max();
5864 case AMDGPU::V_CMP_LT_I64_e64:
5865 return std::numeric_limits<int64_t>::max();
5866 case AMDGPU::V_CMP_GT_U64_e64:
5867 return std::numeric_limits<uint64_t>::min();
5868 case AMDGPU::V_CMP_GT_I64_e64:
5869 return std::numeric_limits<int64_t>::min();
5870 case AMDGPU::V_MIN_F64_e64:
5871 case AMDGPU::V_MAX_F64_e64:
5872 case AMDGPU::V_MIN_NUM_F64_e64:
5873 case AMDGPU::V_MAX_NUM_F64_e64:
5874 return 0x7FF8000000000000;
5875 case AMDGPU::S_ADD_U64_PSEUDO:
5876 case AMDGPU::S_SUB_U64_PSEUDO:
5877 case AMDGPU::S_OR_B64:
5878 case AMDGPU::S_XOR_B64:
5879 return std::numeric_limits<uint64_t>::min();
5880 case AMDGPU::S_AND_B64:
5881 return std::numeric_limits<uint64_t>::max();
5882 case AMDGPU::V_ADD_F64_e64:
5883 case AMDGPU::V_ADD_F64_pseudo_e64:
5884 return 0x8000000000000000;
5891 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5892 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5893 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5894 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5895 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5896 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5897 Opc == AMDGPU::V_SUB_F32_e64;
5901 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5902 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5903 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5904 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5905 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5908static std::tuple<unsigned, unsigned>
5912 case AMDGPU::S_MIN_U32:
5913 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5915 case AMDGPU::S_MIN_I32:
5916 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5918 case AMDGPU::S_MAX_U32:
5919 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5921 case AMDGPU::S_MAX_I32:
5922 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5924 case AMDGPU::S_ADD_I32:
5925 case AMDGPU::S_SUB_I32:
5926 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5927 : AMDGPU::V_ADD_CO_U32_dpp;
5929 case AMDGPU::S_AND_B32:
5930 DPPOpc = AMDGPU::V_AND_B32_dpp;
5932 case AMDGPU::S_OR_B32:
5933 DPPOpc = AMDGPU::V_OR_B32_dpp;
5935 case AMDGPU::S_XOR_B32:
5936 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5938 case AMDGPU::V_ADD_F32_e64:
5939 case AMDGPU::V_SUB_F32_e64:
5940 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5942 case AMDGPU::V_MIN_F32_e64:
5943 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5945 case AMDGPU::V_MAX_F32_e64:
5946 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5948 case AMDGPU::V_CMP_LT_U64_e64:
5949 case AMDGPU::V_CMP_LT_I64_e64:
5950 case AMDGPU::V_CMP_GT_U64_e64:
5951 case AMDGPU::V_CMP_GT_I64_e64:
5952 case AMDGPU::S_ADD_U64_PSEUDO:
5953 case AMDGPU::S_SUB_U64_PSEUDO:
5954 case AMDGPU::S_AND_B64:
5955 case AMDGPU::S_OR_B64:
5956 case AMDGPU::S_XOR_B64:
5957 case AMDGPU::V_MIN_NUM_F64_e64:
5958 case AMDGPU::V_MIN_F64_e64:
5959 case AMDGPU::V_MAX_NUM_F64_e64:
5960 case AMDGPU::V_MAX_F64_e64:
5961 case AMDGPU::V_ADD_F64_pseudo_e64:
5962 case AMDGPU::V_ADD_F64_e64:
5963 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5968 unsigned ClampOpc =
Opc;
5969 if (
Opc == AMDGPU::V_SUB_F32_e64)
5970 ClampOpc = AMDGPU::V_ADD_F32_e64;
5971 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5972 if (
Opc == AMDGPU::S_SUB_I32)
5973 ClampOpc = AMDGPU::S_ADD_I32;
5974 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5975 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5976 else if (
Opc == AMDGPU::S_AND_B64)
5977 ClampOpc = AMDGPU::V_AND_B32_e64;
5978 else if (
Opc == AMDGPU::S_OR_B64)
5979 ClampOpc = AMDGPU::V_OR_B32_e64;
5980 else if (
Opc == AMDGPU::S_XOR_B64)
5981 ClampOpc = AMDGPU::V_XOR_B32_e64;
5983 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5985 return {DPPOpc, ClampOpc};
5988static std::pair<Register, Register>
5995 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5997 TII->buildExtractSubReg(
MI,
MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5999 TII->buildExtractSubReg(
MI,
MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
6000 return {Op1L, Op1H};
6014 bool isSGPR =
TRI->isSGPRClass(
MRI.getRegClass(SrcReg));
6016 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
6017 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
6019 unsigned MIOpc =
MI.getOpcode();
6033 case AMDGPU::S_MIN_U32:
6034 case AMDGPU::S_MIN_I32:
6035 case AMDGPU::V_MIN_F32_e64:
6036 case AMDGPU::S_MAX_U32:
6037 case AMDGPU::S_MAX_I32:
6038 case AMDGPU::V_MAX_F32_e64:
6039 case AMDGPU::S_AND_B32:
6040 case AMDGPU::S_OR_B32: {
6046 case AMDGPU::V_CMP_LT_U64_e64:
6047 case AMDGPU::V_CMP_LT_I64_e64:
6048 case AMDGPU::V_CMP_GT_U64_e64:
6049 case AMDGPU::V_CMP_GT_I64_e64:
6050 case AMDGPU::V_MIN_F64_e64:
6051 case AMDGPU::V_MIN_NUM_F64_e64:
6052 case AMDGPU::V_MAX_F64_e64:
6053 case AMDGPU::V_MAX_NUM_F64_e64:
6054 case AMDGPU::S_AND_B64:
6055 case AMDGPU::S_OR_B64: {
6061 case AMDGPU::S_XOR_B32:
6062 case AMDGPU::S_XOR_B64:
6063 case AMDGPU::S_ADD_I32:
6064 case AMDGPU::S_ADD_U64_PSEUDO:
6065 case AMDGPU::V_ADD_F32_e64:
6066 case AMDGPU::V_ADD_F64_e64:
6067 case AMDGPU::V_ADD_F64_pseudo_e64:
6068 case AMDGPU::S_SUB_I32:
6069 case AMDGPU::S_SUB_U64_PSEUDO:
6070 case AMDGPU::V_SUB_F32_e64: {
6073 Register ExecMask =
MRI.createVirtualRegister(WaveMaskRegClass);
6075 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6077 bool IsWave32 = ST.isWave32();
6078 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6079 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6080 unsigned BitCountOpc =
6081 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6085 auto NewAccumulator =
6091 case AMDGPU::S_XOR_B32:
6092 case AMDGPU::S_XOR_B64: {
6098 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6100 .
addReg(NewAccumulator->getOperand(0).getReg())
6104 if (
TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6106 if (
Opc == AMDGPU::S_XOR_B32) {
6111 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6113 BuildRegSequence(BB,
MI, DstReg, ParityRegister, DstHi);
6117 if (
Opc == AMDGPU::S_XOR_B32) {
6123 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6125 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6127 MRI.getRegClass(SrcReg), ST,
MRI);
6134 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6138 case AMDGPU::S_SUB_I32: {
6139 Register NegatedVal =
MRI.createVirtualRegister(DstRegClass);
6147 .
addReg(NewAccumulator->getOperand(0).getReg());
6150 case AMDGPU::S_ADD_I32: {
6152 if (
TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6155 .
addReg(NewAccumulator->getOperand(0).getReg());
6160 .
addReg(NewAccumulator->getOperand(0).getReg());
6163 case AMDGPU::S_ADD_U64_PSEUDO:
6164 case AMDGPU::S_SUB_U64_PSEUDO: {
6165 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6166 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6168 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6170 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6172 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6173 Register AddReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6175 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6177 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6179 MRI.getRegClass(SrcReg), ST,
MRI);
6181 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO &&
6182 TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6184 Register DstHi =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6186 BuildRegSequence(BB,
MI, DstReg,
6187 NewAccumulator->getOperand(0).getReg(), DstHi);
6190 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6193 .
addReg(NewAccumulator->getOperand(0).getReg())
6203 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6205 : NewAccumulator->getOperand(0).getReg();
6209 if (ST.hasScalarMulHiInsts()) {
6215 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6217 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6220 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6223 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6230 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6236 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6242 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6245 case AMDGPU::V_ADD_F32_e64:
6246 case AMDGPU::V_ADD_F64_e64:
6247 case AMDGPU::V_ADD_F64_pseudo_e64:
6248 case AMDGPU::V_SUB_F32_e64: {
6251 Register ActiveLanesVreg =
MRI.createVirtualRegister(VregRC);
6252 Register DstVreg =
MRI.createVirtualRegister(VregRC);
6255 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6256 : AMDGPU::V_CVT_F64_I32_e64),
6258 .
addReg(NewAccumulator->getOperand(0).getReg())
6263 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6264 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6267 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6269 ? AMDGPU::V_MUL_F64_pseudo_e64
6270 : AMDGPU::V_MUL_F64_e64;
6280 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6284 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6286 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6297 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6309 bool NeedsMovDPP = !is32BitOpc;
6314 bool IsWave32 = ST.isWave32();
6315 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6316 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6317 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6331 Register LoopIterator =
MRI.createVirtualRegister(WaveMaskRegClass);
6332 Register IdentityValReg =
MRI.createVirtualRegister(DstRegClass);
6333 Register AccumulatorReg =
MRI.createVirtualRegister(DstRegClass);
6334 Register ActiveBitsReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6335 Register NewActiveBitsReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6336 Register FF1Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6337 Register LaneValueReg =
MRI.createVirtualRegister(DstRegClass);
6343 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6347 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6348 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6357 I = ComputeLoop->begin();
6359 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6363 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6367 I = ComputeLoop->end();
6371 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6376 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6377 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6378 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6379 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6381 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6383 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6385 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6386 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6390 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6392 Register LaneValVgpr =
MRI.createVirtualRegister(SrcRegClass);
6393 Register VgprResultReg =
MRI.createVirtualRegister(SrcRegClass);
6394 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6396 OpDstReg = VgprResultReg;
6397 LaneValueReg = LaneValVgpr;
6400 if (hasSrc0Modifier)
6402 OpInstr.addReg(AccumulatorReg);
6403 if (hasSrc1Modifier)
6405 OpInstr.addReg(LaneValueReg);
6413 OpInstr.setOperandDead(3);
6414 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6415 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6421 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6423 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6425 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6427 MRI.getRegClass(SrcReg), ST,
MRI);
6429 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6433 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6437 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6438 LaneValueLoReg, LaneValueHiReg);
6440 case AMDGPU::S_OR_B64:
6441 case AMDGPU::S_AND_B64:
6442 case AMDGPU::S_XOR_B64: {
6445 .
addReg(LaneValue->getOperand(0).getReg())
6449 case AMDGPU::V_CMP_GT_I64_e64:
6450 case AMDGPU::V_CMP_GT_U64_e64:
6451 case AMDGPU::V_CMP_LT_I64_e64:
6452 case AMDGPU::V_CMP_LT_U64_e64: {
6453 Register LaneMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6455 MRI.createVirtualRegister(WaveMaskRegClass);
6457 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6459 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6460 Register AccumulatorVReg =
MRI.createVirtualRegister(VregClass);
6463 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6466 .
addReg(LaneValue->getOperand(0).getReg())
6467 .
addReg(AccumulatorVReg);
6469 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6470 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6474 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6475 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6476 .
addReg(LaneValue->getOperand(0).getReg())
6480 case AMDGPU::V_MIN_F64_e64:
6481 case AMDGPU::V_MIN_NUM_F64_e64:
6482 case AMDGPU::V_MAX_F64_e64:
6483 case AMDGPU::V_MAX_NUM_F64_e64:
6484 case AMDGPU::V_ADD_F64_e64:
6485 case AMDGPU::V_ADD_F64_pseudo_e64: {
6487 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6489 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6490 Register AccumulatorVReg =
MRI.createVirtualRegister(VregRC);
6491 Register DstVreg =
MRI.createVirtualRegister(VregRC);
6493 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6495 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6496 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6499 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6505 .
addReg(LaneValue->getOperand(0).getReg())
6512 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6515 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6517 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6519 ReadLaneLo.addReg(Op1L);
6520 ReadLaneHi.addReg(Op1H);
6522 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6525 case AMDGPU::S_ADD_U64_PSEUDO:
6526 case AMDGPU::S_SUB_U64_PSEUDO: {
6529 .
addReg(LaneValue->getOperand(0).getReg())
6538 unsigned BITSETOpc =
6539 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6540 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6546 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6550 if (!ST.hasScalarCompareEq64()) {
6552 Register LaneMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6553 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6555 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6558 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6559 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6561 SetSCCInstr.
addReg(NewActiveBitsReg);
6562 if (ST.hasScalarCompareEq64())
6565 SetSCCInstr.
addReg(NewActiveBitsReg);
6566 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6571 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6573 Register SrcWithIdentity =
MRI.createVirtualRegister(SrcRegClass);
6574 Register IdentityVGPR =
MRI.createVirtualRegister(SrcRegClass);
6575 Register IdentitySGPR =
MRI.createVirtualRegister(DstRegClass);
6576 Register DPPRowShr1 =
MRI.createVirtualRegister(SrcRegClass);
6577 Register DPPRowShr2 =
MRI.createVirtualRegister(SrcRegClass);
6578 Register DPPRowShr4 =
MRI.createVirtualRegister(SrcRegClass);
6579 Register DPPRowShr8 =
MRI.createVirtualRegister(SrcRegClass);
6580 Register RowBcast15 =
MRI.createVirtualRegister(SrcRegClass);
6581 Register ReducedValSGPR =
MRI.createVirtualRegister(DstRegClass);
6582 Register NegatedReducedVal =
MRI.createVirtualRegister(DstRegClass);
6583 Register RowBcast31 =
MRI.createVirtualRegister(SrcRegClass);
6584 Register UndefExec =
MRI.createVirtualRegister(WaveMaskRegClass);
6588 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6592 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6593 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6596 auto IdentityCopyInstr =
6599 unsigned DPPOpc, ClampOpc;
6615 if (isFPOp && !NeedsMovDPP)
6618 if (isFPOp && !NeedsMovDPP)
6622 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6631 bool isAddSub =
false,
6632 bool needsCarryIn =
false,
6634 unsigned InstrOpc = ClampOpc;
6635 Register CarryOutReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6637 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6638 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6643 ClampInstr.addReg(CarryOutReg,
6649 ClampInstr.addReg(Src0);
6652 ClampInstr.addReg(Src1);
6654 ClampInstr.addReg(CarryIn);
6655 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6656 ClampInstr.addImm(0);
6658 ClampInstr.addImm(0);
6659 LastBcastInstr = ClampInstr;
6664 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6665 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6666 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6667 Register ReturnReg =
MRI.createVirtualRegister(SrcRegClass);
6668 if (isAddSubOpc || isBitWiseOpc) {
6669 Register ResLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6670 Register ResHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6675 auto [Src0Lo, Src0Hi] =
6677 auto [Src1Lo, Src1Hi] =
6679 Register CarryReg = BuildClampInstr(
6680 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6681 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6682 isAddSubOpc, CarryReg);
6683 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6694 Register CmpMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6712 SrcWithIdentityInstr =
6713 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6716 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6718 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6720 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST,
MRI);
6721 auto [SrcReg0Sub0, SrcReg0Sub1] =
6724 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6726 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6727 SrcWithIdentityInstr =
6728 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6735 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6738 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6740 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6743 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6745 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6748 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6750 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6753 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6755 if (ST.hasDPPBroadcasts()) {
6758 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6767 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6773 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6776 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6778 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6779 Register SwizzledValue64 =
MRI.createVirtualRegister(SrcRegClass);
6794 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6797 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6799 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6802 FinalDPPResult = RowBcast15;
6804 if (ST.hasDPPBroadcasts()) {
6807 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6810 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6812 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6813 Register PermutedValue =
MRI.createVirtualRegister(SrcRegClass);
6815 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6817 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6819 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6821 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6823 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6827 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6833 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6841 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6846 .
addReg(ShiftedThreadID);
6851 .
addReg(PermuteByteOffset)
6856 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6858 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6861 auto [RowBcast15Lo, RowBcast15Hi] =
6865 .
addReg(PermuteByteOffset)
6870 .
addReg(PermuteByteOffset)
6873 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6877 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6879 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6881 FinalDPPResult = RowBcast31;
6883 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6884 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6885 Register NegatedValVGPR =
MRI.createVirtualRegister(SrcRegClass);
6894 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6897 FinalDPPResult = NegatedValVGPR;
6904 .
addImm(ST.getWavefrontSize() - 1);
6907 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6909 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6919 .
addImm(ST.getWavefrontSize() - 1);
6923 .
addImm(ST.getWavefrontSize() - 1);
6924 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6927 if (
Opc == AMDGPU::S_SUB_I32) {
6928 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6932 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6933 auto NegatedValInstr =
6942 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6948 MI.eraseFromParent();
6963 switch (
MI.getOpcode()) {
6964 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6966 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6968 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6970 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6972 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6974 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6977 ? AMDGPU::V_MIN_NUM_F64_e64
6978 : AMDGPU::V_MIN_F64_e64);
6979 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6981 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6983 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6985 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6987 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6989 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6992 ? AMDGPU::V_MAX_NUM_F64_e64
6993 : AMDGPU::V_MAX_F64_e64);
6994 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6996 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6998 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
7000 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
7003 ? AMDGPU::V_ADD_F64_pseudo_e64
7004 : AMDGPU::V_ADD_F64_e64);
7005 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
7007 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
7009 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
7011 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7016 ? AMDGPU::V_ADD_F64_pseudo_e64
7017 : AMDGPU::V_ADD_F64_e64);
7018 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7020 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7022 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7024 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7026 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7028 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7030 case AMDGPU::S_UADDO_PSEUDO:
7031 case AMDGPU::S_USUBO_PSEUDO: {
7037 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7039 : AMDGPU::S_SUB_U32;
7047 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7050 MI.eraseFromParent();
7053 case AMDGPU::S_ADD_U64_PSEUDO:
7054 case AMDGPU::S_SUB_U64_PSEUDO: {
7057 case AMDGPU::V_ADD_U64_PSEUDO:
7058 case AMDGPU::V_SUB_U64_PSEUDO: {
7059 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7065 if (ST.hasAddSubU64Insts()) {
7067 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7068 : AMDGPU::V_SUB_U64_e64),
7073 TII->legalizeOperands(*
I);
7074 MI.eraseFromParent();
7078 if (IsAdd && ST.hasLshlAddU64Inst()) {
7084 TII->legalizeOperands(*
Add);
7085 MI.eraseFromParent();
7089 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7091 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7092 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7094 Register CarryReg =
MRI.createVirtualRegister(CarryRC);
7095 Register DeadCarryReg =
MRI.createVirtualRegister(CarryRC);
7098 ?
MRI.getRegClass(Src0.getReg())
7099 : &AMDGPU::VReg_64RegClass;
7101 ?
MRI.getRegClass(Src1.getReg())
7102 : &AMDGPU::VReg_64RegClass;
7105 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7107 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7110 MI,
MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7112 MI,
MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7115 MI,
MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7117 MI,
MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7120 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7127 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7141 TII->legalizeOperands(*LoHalf);
7142 TII->legalizeOperands(*HiHalf);
7143 MI.eraseFromParent();
7146 case AMDGPU::S_ADD_CO_PSEUDO:
7147 case AMDGPU::S_SUB_CO_PSEUDO: {
7157 if (Src0.isReg() &&
TRI->isVectorRegister(
MRI, Src0.getReg())) {
7158 Register RegOp0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7159 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7161 Src0.setReg(RegOp0);
7163 if (Src1.isReg() &&
TRI->isVectorRegister(
MRI, Src1.getReg())) {
7164 Register RegOp1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7165 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7167 Src1.setReg(RegOp1);
7169 Register RegOp2 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7170 if (
TRI->isVectorRegister(
MRI, Src2.getReg())) {
7171 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7173 Src2.setReg(RegOp2);
7176 if (ST.isWave64()) {
7177 if (ST.hasScalarCompareEq64()) {
7184 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7186 MII,
MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7188 MII,
MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7189 Register Src2_32 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7191 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7205 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7206 ? AMDGPU::S_ADDC_U32
7207 : AMDGPU::S_SUBB_U32;
7212 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7218 MI.eraseFromParent();
7221 case AMDGPU::SI_INIT_M0: {
7224 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7227 MI.eraseFromParent();
7230 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7233 TII->get(AMDGPU::S_CMP_EQ_U32))
7238 case AMDGPU::GET_GROUPSTATICSIZE: {
7242 .
add(
MI.getOperand(0))
7244 MI.eraseFromParent();
7247 case AMDGPU::GET_SHADERCYCLESHILO: {
7260 Register RegHi1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7262 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7263 Register RegLo1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7265 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7266 Register RegHi2 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7268 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7272 Register RegLo =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7277 .
add(
MI.getOperand(0))
7282 MI.eraseFromParent();
7285 case AMDGPU::SI_INDIRECT_SRC_V1:
7286 case AMDGPU::SI_INDIRECT_SRC_V2:
7287 case AMDGPU::SI_INDIRECT_SRC_V3:
7288 case AMDGPU::SI_INDIRECT_SRC_V4:
7289 case AMDGPU::SI_INDIRECT_SRC_V5:
7290 case AMDGPU::SI_INDIRECT_SRC_V6:
7291 case AMDGPU::SI_INDIRECT_SRC_V7:
7292 case AMDGPU::SI_INDIRECT_SRC_V8:
7293 case AMDGPU::SI_INDIRECT_SRC_V9:
7294 case AMDGPU::SI_INDIRECT_SRC_V10:
7295 case AMDGPU::SI_INDIRECT_SRC_V11:
7296 case AMDGPU::SI_INDIRECT_SRC_V12:
7297 case AMDGPU::SI_INDIRECT_SRC_V16:
7298 case AMDGPU::SI_INDIRECT_SRC_V32:
7300 case AMDGPU::SI_INDIRECT_DST_V1:
7301 case AMDGPU::SI_INDIRECT_DST_V2:
7302 case AMDGPU::SI_INDIRECT_DST_V3:
7303 case AMDGPU::SI_INDIRECT_DST_V4:
7304 case AMDGPU::SI_INDIRECT_DST_V5:
7305 case AMDGPU::SI_INDIRECT_DST_V6:
7306 case AMDGPU::SI_INDIRECT_DST_V7:
7307 case AMDGPU::SI_INDIRECT_DST_V8:
7308 case AMDGPU::SI_INDIRECT_DST_V9:
7309 case AMDGPU::SI_INDIRECT_DST_V10:
7310 case AMDGPU::SI_INDIRECT_DST_V11:
7311 case AMDGPU::SI_INDIRECT_DST_V12:
7312 case AMDGPU::SI_INDIRECT_DST_V16:
7313 case AMDGPU::SI_INDIRECT_DST_V32:
7315 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7316 case AMDGPU::SI_KILL_I1_PSEUDO:
7318 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7322 case AMDGPU::SI_BR_UNDEF: {
7324 .
add(
MI.getOperand(0));
7326 MI.eraseFromParent();
7329 case AMDGPU::ADJCALLSTACKUP:
7330 case AMDGPU::ADJCALLSTACKDOWN: {
7337 case AMDGPU::SI_CALL_ISEL: {
7338 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7349 MI.eraseFromParent();
7352 case AMDGPU::V_ADDC_U32_e32:
7353 case AMDGPU::V_SUBB_U32_e32:
7354 case AMDGPU::V_SUBBREV_U32_e32:
7357 TII->legalizeOperands(
MI);
7359 case AMDGPU::DS_GWS_INIT:
7360 case AMDGPU::DS_GWS_SEMA_BR:
7361 case AMDGPU::DS_GWS_BARRIER:
7362 case AMDGPU::DS_GWS_SEMA_V:
7363 case AMDGPU::DS_GWS_SEMA_P:
7364 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7372 case AMDGPU::S_SETREG_B32: {
7382 auto [ID,
Offset, Width] =
7388 const unsigned SetMask = WidthMask <<
Offset;
7391 unsigned SetDenormOp = 0;
7392 unsigned SetRoundOp = 0;
7400 SetRoundOp = AMDGPU::S_ROUND_MODE;
7401 SetDenormOp = AMDGPU::S_DENORM_MODE;
7403 SetRoundOp = AMDGPU::S_ROUND_MODE;
7405 SetDenormOp = AMDGPU::S_DENORM_MODE;
7408 if (SetRoundOp || SetDenormOp) {
7410 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7411 unsigned ImmVal = Def->getOperand(1).getImm();
7425 MI.eraseFromParent();
7434 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7438 case AMDGPU::S_INVERSE_BALLOT_U32:
7439 case AMDGPU::S_INVERSE_BALLOT_U64:
7442 MI.setDesc(
TII->get(AMDGPU::COPY));
7444 case AMDGPU::ENDPGM_TRAP: {
7446 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7466 MI.eraseFromParent();
7469 case AMDGPU::SIMULATED_TRAP: {
7470 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7472 TII->insertSimulatedTrap(
MRI, *BB,
MI,
MI.getDebugLoc());
7473 MI.eraseFromParent();
7476 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7477 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7483 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7484 Register OriginalExec = Setup->getOperand(0).getReg();
7486 MI.getOperand(0).setReg(OriginalExec);
7489 case AMDGPU::V_DOT2_F32_F16:
7490 case AMDGPU::V_DOT2_F32_BF16: {
7494 MRI.setSimpleHint(
MI.getOperand(0).getReg(),
MI.getOperand(6).getReg());
7497 case AMDGPU::SCHED_BARRIER:
7498 case AMDGPU::SCHED_GROUP_BARRIER:
7499 MI.getOperand(0).setImm(
MI.getOperand(0).getImm() &
7536 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7540 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7569 if (!Subtarget->hasMadMacF32Insts())
7570 return Subtarget->hasFastFMAF32();
7576 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7579 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7585 return Subtarget->has16BitInsts() &&
7603 F.getDenormalFPEnv());
7608 switch (Ty.getScalarSizeInBits()) {
7626 return Subtarget->hasMadMacF32Insts() &&
7629 return Subtarget->hasMadF16() &&
7640 if (Ty.getScalarSizeInBits() == 16)
7642 if (Ty.getScalarSizeInBits() == 32)
7657 F.getDenormalFPEnv());
7668 unsigned Opc =
Op.getOpcode();
7669 EVT VT =
Op.getValueType();
7681 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7682 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7695 [[maybe_unused]]
EVT VT =
Op.getValueType();
7697 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7698 VT == MVT::v16i32) &&
7699 "Unexpected ValueType.");
7708 unsigned Opc =
Op.getOpcode();
7709 EVT VT =
Op.getValueType();
7718 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7720 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7727 unsigned Opc =
Op.getOpcode();
7728 EVT VT =
Op.getValueType();
7745 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7747 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7753 switch (
Op.getOpcode()) {
7757 return LowerBRCOND(
Op, DAG);
7759 return LowerRETURNADDR(
Op, DAG);
7761 return LowerSPONENTRY(
Op, DAG);
7764 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7765 "Load should return a value and a chain");
7769 EVT VT =
Op.getValueType();
7771 return lowerFSQRTF32(
Op, DAG);
7773 return lowerFSQRTF64(
Op, DAG);
7778 return LowerTrig(
Op, DAG);
7780 return LowerSELECT(
Op, DAG);
7782 return LowerFDIV(
Op, DAG);
7784 return LowerFFREXP(
Op, DAG);
7786 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7788 return LowerSTORE(
Op, DAG);
7792 return LowerGlobalAddress(MFI,
Op, DAG);
7797 return LowerExternalSymbol(
Op, DAG);
7799 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7801 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7803 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7805 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7807 return LowerINTRINSIC_VOID(
Op, DAG);
7809 return lowerADDRSPACECAST(
Op, DAG);
7811 return lowerINSERT_SUBVECTOR(
Op, DAG);
7813 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7815 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7817 return lowerVECTOR_SHUFFLE(
Op, DAG);
7819 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7821 return lowerBUILD_VECTOR(
Op, DAG);
7824 return lowerFP_ROUND(
Op, DAG);
7826 return lowerTRAP(
Op, DAG);
7828 return lowerDEBUGTRAP(
Op, DAG);
7837 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7838 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7842 if (
Op.getValueType() == MVT::bf16) {
7872 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7875 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7878 return lowerFLDEXP(
Op, DAG);
7883 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7884 Op.getOperand(0).getValueType() == MVT::f32) {
7910 return lowerFCOPYSIGN(
Op, DAG);
7912 return lowerMUL(
Op, DAG);
7915 return lowerXMULO(
Op, DAG);
7918 return lowerXMUL_LOHI(
Op, DAG);
7939 return LowerINLINEASM(
Op, DAG);
7945static std::pair<SDValue, SDValue>
7975 EVT FittingLoadVT = LoadVT;
8007SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
8010 bool IsIntrinsic)
const {
8013 bool IsTFE =
M->getNumValues() == 3;
8014 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8015 EVT LoadVT =
M->getValueType(0);
8017 EVT EquivLoadVT = LoadVT;
8034 SDVTList VTList = DAG.
getVTList(LoadDWordsVT, MVT::Other);
8036 Opcode,
DL, VTList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
8044 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
8048 M->getMemoryVT(),
M->getMemOperand());
8059 EVT LoadVT =
M->getValueType(0);
8068 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
8072 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
8073 bool IsTFE =
M->getNumValues() == 3;
8075 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8078 "TFE D16 format buffer load is not supported on this GPU",
8081 M->getOperand(0),
DL);
8084 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8085 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8086 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8087 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8088 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8089 : AMDGPUISD::BUFFER_LOAD;
8092 return adjustLoadValueType(
Opc, M, DAG,
Ops);
8096 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
8100 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
8101 M->getMemOperand(), DAG);
8105 SDVTList VTList = IsTFE ? DAG.
getVTList(CastVT, MVT::i32, MVT::Other)
8108 M->getMemOperand(), DAG);
8118 EVT VT =
N->getValueType(0);
8142 Exec = AMDGPU::EXEC_LO;
8144 Exec = AMDGPU::EXEC;
8161 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8163 EVT VT =
Op.getValueType();
8168 if (VT != MVT::i32) {
8176 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8185 EVT VT =
N->getValueType(0);
8187 unsigned IID =
N->getConstantOperandVal(0);
8188 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8189 IID == Intrinsic::amdgcn_permlanex16;
8190 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8191 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8192 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8193 IID == Intrinsic::amdgcn_permlane_up ||
8194 IID == Intrinsic::amdgcn_permlane_down ||
8195 IID == Intrinsic::amdgcn_permlane_xor;
8200 unsigned SplitSize = 32;
8201 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8202 ST->hasDPALU_DPP() &&
8210 case Intrinsic::amdgcn_permlane16:
8211 case Intrinsic::amdgcn_permlanex16:
8212 case Intrinsic::amdgcn_update_dpp:
8217 case Intrinsic::amdgcn_writelane:
8218 case Intrinsic::amdgcn_permlane_bcast:
8219 case Intrinsic::amdgcn_permlane_up:
8220 case Intrinsic::amdgcn_permlane_down:
8221 case Intrinsic::amdgcn_permlane_xor:
8224 case Intrinsic::amdgcn_readlane:
8225 case Intrinsic::amdgcn_set_inactive:
8226 case Intrinsic::amdgcn_set_inactive_chain_arg:
8227 case Intrinsic::amdgcn_mov_dpp8:
8230 case Intrinsic::amdgcn_readfirstlane:
8231 case Intrinsic::amdgcn_permlane64:
8241 if (
SDNode *GL =
N->getGluedNode()) {
8243 GL = GL->getOperand(0).getNode();
8253 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8254 IID == Intrinsic::amdgcn_mov_dpp8 ||
8255 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8256 IsPermlaneShuffle) {
8257 Src1 =
N->getOperand(2);
8258 if (IID == Intrinsic::amdgcn_writelane ||
8259 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8261 Src2 =
N->getOperand(3);
8264 if (ValSize == SplitSize) {
8274 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8279 if (IID == Intrinsic::amdgcn_writelane) {
8284 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8286 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8289 if (ValSize % SplitSize != 0)
8293 EVT VT =
N->getValueType(0);
8297 unsigned NumOperands =
N->getNumOperands();
8299 SDNode *GL =
N->getGluedNode();
8304 for (
unsigned i = 0; i != NE; ++i) {
8305 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8307 SDValue Operand =
N->getOperand(j);
8337 if (SplitSize == 32) {
8339 return unrollLaneOp(LaneOp.
getNode());
8345 unsigned SubVecNumElt =
8349 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8350 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8354 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8360 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8361 }
else if (IID == Intrinsic::amdgcn_writelane) {
8365 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8367 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8370 EltIdx += SubVecNumElt;
8384 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8387 if (IID == Intrinsic::amdgcn_writelane)
8390 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8397 EVT VT =
N->getValueType(0);
8415 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8424 if (
TLI.getSubtarget()->supportsWaveWideBPermute()) {
8425 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8426 {ShiftedIndex, ValueI32});
8436 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8437 {ValueI32, PoisonVal});
8438 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8439 {ShiftedIndex, PoisonVal});
8442 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8445 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8446 {WWMIndex, WWMValue});
8447 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8448 MVT::i32, {WWMIndex, Swapped});
8450 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8458 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8466 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8476 switch (
N->getOpcode()) {
8493 unsigned IID =
N->getConstantOperandVal(0);
8495 case Intrinsic::amdgcn_wave_reduce_min:
8496 case Intrinsic::amdgcn_wave_reduce_umin:
8497 case Intrinsic::amdgcn_wave_reduce_max:
8498 case Intrinsic::amdgcn_wave_reduce_umax:
8499 case Intrinsic::amdgcn_wave_reduce_add:
8500 case Intrinsic::amdgcn_wave_reduce_sub:
8501 case Intrinsic::amdgcn_wave_reduce_and:
8502 case Intrinsic::amdgcn_wave_reduce_or:
8503 case Intrinsic::amdgcn_wave_reduce_xor: {
8504 EVT VT =
N->getValueType(0);
8508 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8509 IID == Intrinsic::amdgcn_wave_reduce_max ||
8510 IID == Intrinsic::amdgcn_wave_reduce_add ||
8511 IID == Intrinsic::amdgcn_wave_reduce_sub;
8515 N->getOperand(0), ExtSrc,
N->getOperand(2));
8519 case Intrinsic::amdgcn_make_buffer_rsrc:
8520 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8522 case Intrinsic::amdgcn_cvt_pkrtz: {
8527 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8531 case Intrinsic::amdgcn_cvt_pknorm_i16:
8532 case Intrinsic::amdgcn_cvt_pknorm_u16:
8533 case Intrinsic::amdgcn_cvt_pk_i16:
8534 case Intrinsic::amdgcn_cvt_pk_u16: {
8540 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8541 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8542 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8543 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8544 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8545 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8547 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8549 EVT VT =
N->getValueType(0);
8558 case Intrinsic::amdgcn_s_buffer_load: {
8560 EVT VT =
Op.getValueType();
8562 Op.getOperand(1),
Op.getOperand(2),
8563 Op.getOperand(3), DAG));
8566 case Intrinsic::amdgcn_dead: {
8567 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8575 if (
N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8576 N->getValueType(0).isSimple() &&
8577 SBufferLoadDiagnosticVTs[
N->getSimpleValueType(0).SimpleTy])
8582 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8583 Results.push_back(Res.getOperand(
I));
8586 for (
unsigned I = 0;
I <
N->getNumValues(); ++
I)
8587 Results.push_back(Res.getValue(
I));
8596 EVT VT =
N->getValueType(0);
8601 EVT SelectVT = NewVT;
8602 if (NewVT.
bitsLT(MVT::i32)) {
8605 SelectVT = MVT::i32;
8611 if (NewVT != SelectVT)
8617 if (
N->getValueType(0) != MVT::v2f16)
8629 if (
N->getValueType(0) != MVT::v2f16)
8641 if (
N->getValueType(0) != MVT::f16)
8656 if (U.get() !=
Value)
8659 if (U.getUser()->getOpcode() == Opcode)
8665unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8668 case Intrinsic::amdgcn_if:
8669 return AMDGPUISD::IF;
8670 case Intrinsic::amdgcn_else:
8671 return AMDGPUISD::ELSE;
8672 case Intrinsic::amdgcn_loop:
8673 return AMDGPUISD::LOOP;
8674 case Intrinsic::amdgcn_end_cf:
8694 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8718 assert(GVar->isDeclaration() &&
8719 "AS 3 & 13 GVs should be declaration here "
8720 "when object linking is enabled");
8735 SDNode *Intr = BRCOND.getOperand(1).getNode();
8752 Intr =
LHS.getNode();
8760 assert(BR &&
"brcond missing unconditional branch user");
8765 unsigned CFNode = isCFIntrinsic(Intr);
8783 Ops.push_back(Target);
8806 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8825 MVT VT =
Op.getSimpleValueType();
8828 if (
Op.getConstantOperandVal(0) != 0)
8832 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8834 if (
Info->isEntryFunction())
8851 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8865 return Op.getValueType().bitsLE(VT)
8873 EVT DstVT =
Op.getValueType();
8880 unsigned Opc =
Op.getOpcode();
8891 bool IsStrict =
Op->isStrictFPOpcode();
8892 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8893 EVT SrcVT = Src.getValueType();
8894 EVT DstVT =
Op.getValueType();
8897 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8900 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8907 if (DstVT == MVT::f16) {
8912 if (!Subtarget->has16BitInsts()) {
8917 if (
Op->getFlags().hasApproximateFuncs()) {
8928 "custom lower FP_ROUND for f16 or bf16");
8929 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8946 EVT VT =
Op.getValueType();
8948 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8949 bool IsIEEEMode =
Info->getMode().IEEE;
8955 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8958 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8959 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8960 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8961 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8967SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8969 EVT VT =
Op.getValueType();
8971 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8972 bool IsIEEEMode =
Info->getMode().IEEE;
8974 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8977 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8978 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8979 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8980 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8987 EVT VT =
Op.getValueType();
8991 EVT ExpVT =
Exp.getValueType();
8992 if (ExpVT == MVT::i16)
9013 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
9020 switch (
Op->getOpcode()) {
9053SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
9054 DAGCombinerInfo &DCI)
const {
9055 EVT OpTy =
Op.getValueType();
9056 SelectionDAG &DAG = DCI.DAG;
9073 DAGCombinerInfo &DCI)
const {
9074 const unsigned Opc =
Op.getOpcode();
9083 :
Op->getOperand(0).getValueType();
9084 auto &DAG = DCI.DAG;
9087 if (DCI.isBeforeLegalizeOps() ||
9095 LHS =
Op->getOperand(1);
9096 RHS =
Op->getOperand(2);
9098 LHS =
Op->getOperand(0);
9099 RHS =
Op->getOperand(1);
9143 if (MagVT == SignVT)
9164 EVT VT =
Op.getValueType();
9170 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9197 if (
Op->isDivergent())
9210 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9212 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9215 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9217 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9223 EVT VT =
Op.getValueType();
9230 const APInt &
C = RHSC->getAPIntValue();
9232 if (
C.isPowerOf2()) {
9234 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9261 if (
Op->isDivergent()) {
9265 if (Subtarget->hasSMulHi()) {
9276 if (!Subtarget->hasTrapHandler() ||
9278 return lowerTrapEndpgm(
Op, DAG);
9280 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9281 : lowerTrapHsaQueuePtr(
Op, DAG);
9287 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9291SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9293 ImplicitParameter Param)
const {
9297 MachinePointerInfo PtrInfo =
9314 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9317 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9320 if (UserSGPR == AMDGPU::NoRegister) {
9337 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9346 if (Subtarget->hasPrivEnabledTrap2NopBug())
9347 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9351 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9359 if (!Subtarget->hasTrapHandler() ||
9363 "debugtrap handler not supported",
9371 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9381 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9382 SmallSet<Register, 8> SGPRInputRegs;
9384 unsigned NumVals = 0;
9387 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9388 NumVals =
Flags.getNumOperandRegisters();
9392 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9393 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9395 for (
unsigned J = 0; J < NumVals; ++J) {
9397 if (
const RegisterSDNode *RegNode =
9406 if (SGPRInputRegs.
empty())
9411 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9423 ReadFirstLaneID, SrcVal);
9427 if (
N->getNumOperands() > 3)
9428 Ops.push_back(
N->getOperand(3));
9434 SDNode *
Next =
nullptr;
9435 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9436 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9437 Next =
N->getOperand(
I).getNode();
9447SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9449 unsigned BaseAS = AS;
9454 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9464SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9468 if (Subtarget->hasApertureRegs()) {
9469 const unsigned ApertureRegNo =
9470 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9471 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9472 !Subtarget->hasGloballyAddressableScratch()) &&
9473 "Cannot use src_private_base with globally addressable scratch!");
9493 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9497 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9499 if (UserSGPR == AMDGPU::NoRegister) {
9510 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9544 const AMDGPUTargetMachine &TM =
9548 unsigned SrcAS = ASC->getSrcAddressSpace();
9549 SDValue Src = ASC->getOperand(0);
9550 unsigned DestAS = ASC->getDestAddressSpace();
9551 bool IsNonNull = ASC->getFlags().hasNonNull();
9562 Subtarget->hasGloballyAddressableScratch()) {
9567 AMDGPU::S_MOV_B32, SL, MVT::i32,
9568 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9591 Subtarget->hasGloballyAddressableScratch()) {
9600 if (Subtarget->isWave64())
9606 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9614 AMDGPU::S_MOV_B64, SL, MVT::i64,
9615 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9617 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9619 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9640 Op.getValueType() == MVT::i64) {
9641 const SIMachineFunctionInfo *
Info =
9643 if (
Info->get32BitAddressHighBits() == 0)
9652 Src.getValueType() == MVT::i64)
9675 unsigned IdxVal =
Idx->getAsZExtVal();
9680 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9685 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9687 MVT::i32, InsNumElts / 2);
9692 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9694 if (InsNumElts == 2) {
9707 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9730 if (NumElts == 4 && EltSize == 16 && KIdx) {
9741 unsigned Idx = KIdx->getZExtValue();
9742 bool InsertLo =
Idx < 2;
9746 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9752 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9766 unsigned PieceSize = std::min(VecSize, 64u);
9767 unsigned NumPieces =
VecSize / PieceSize;
9768 unsigned EltsPerPiece = PieceSize / EltSize;
9803 InsertIntoPiece(DAG.
getBitcast(IntVT, Vec), BFM));
9815 for (
unsigned I = 0;
I != NumPieces; ++
I) {
9821 Pieces.
push_back(InsertIntoPiece(Piece, Mask));
9831 EVT ResultVT =
Op.getValueType();
9844 if (
SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9847 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9851 if (VecSize == 128) {
9859 }
else if (VecSize == 256) {
9862 for (
unsigned P = 0;
P < 4; ++
P) {
9868 Parts[0], Parts[1]));
9870 Parts[2], Parts[3]));
9876 for (
unsigned P = 0;
P < 8; ++
P) {
9883 Parts[0], Parts[1], Parts[2], Parts[3]));
9886 Parts[4], Parts[5], Parts[6], Parts[7]));
9889 EVT IdxVT =
Idx.getValueType();
9906 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9921 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9931 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9936 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9937 !(Mask[Elt + 1] & 1);
9943 EVT ResultVT =
Op.getValueType();
9946 const int NewSrcNumElts = 2;
9948 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9964 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9986 if (ShouldUseConsecutiveExtract &&
9989 int VecIdx =
Idx < SrcNumElts ? 0 : 1;
9990 int EltIdx =
Idx < SrcNumElts ?
Idx :
Idx - SrcNumElts;
10002 if (Idx0 >= SrcNumElts) {
10004 Idx0 -= SrcNumElts;
10007 if (Idx1 >= SrcNumElts) {
10009 Idx1 -= SrcNumElts;
10012 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
10013 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
10021 int NewMaskIdx0 = Idx0 - AlignedIdx0;
10022 int NewMaskIdx1 = Idx1 - AlignedIdx1;
10027 if (SubVec0 != SubVec1) {
10028 NewMaskIdx1 += NewSrcNumElts;
10035 {NewMaskIdx0, NewMaskIdx1});
10040 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10041 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10042 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10043 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10062 EVT ResultVT =
Op.getValueType();
10078 EVT VT =
Op.getValueType();
10080 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10081 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10087 if (
Hi.isUndef()) {
10117 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10143 if (!Subtarget->isAmdHsaOS())
10186 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10195 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10203 EVT PtrVT =
Op.getValueType();
10205 const GlobalValue *GV = GSD->
getGlobal();
10218 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10239 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10242 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10243 if (Subtarget->has64BitLiterals()) {
10252 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10256 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10274 MachinePointerInfo PtrInfo =
10287 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10309 unsigned Offset)
const {
10311 SDValue Param = lowerKernargMemParameter(
10322 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10330 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10338 unsigned NumElts = Elts.
size();
10340 if (NumElts <= 12) {
10344 Type = MVT::v16f32;
10349 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10355 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10364 SDValue Src,
int ExtraElts) {
10365 EVT SrcVT = Src.getValueType();
10375 while (ExtraElts--)
10386 bool Unpacked,
bool IsD16,
int DMaskPop,
10387 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10391 EVT ReqRetVT = ResultTypes[0];
10393 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10394 ? (ReqRetNumElts + 1) / 2
10397 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10400 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10403 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10408 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10412 SDValue(Result, 0), ZeroIdx);
10415 SDValue(Result, 0), ZeroIdx);
10419 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10421 NumDataDwords - MaskPopDwords);
10426 EVT LegalReqRetVT = ReqRetVT;
10428 if (!
Data.getValueType().isInteger())
10430 Data.getValueType().changeTypeToInteger(),
Data);
10451 if (Result->getNumValues() == 1)
10458 SDValue *LWE,
bool &IsTexFail) {
10478 unsigned DimIdx,
unsigned EndIdx,
10479 unsigned NumGradients) {
10481 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10489 if (((
I + 1) >= EndIdx) ||
10490 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10491 I == DimIdx + NumGradients - 1))) {
10523 !
Op.getNode()->hasAnyUseOfValue(0))
10525 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10536 ResultTypes.erase(&ResultTypes[0]);
10538 bool IsD16 =
false;
10539 bool IsG16 =
false;
10540 bool IsA16 =
false;
10542 int NumVDataDwords = 0;
10543 bool AdjustRetType =
false;
10544 bool IsAtomicPacked16Bit =
false;
10547 const unsigned ArgOffset = WithChain ? 2 : 1;
10550 unsigned DMaskLanes = 0;
10552 if (BaseOpcode->
Atomic) {
10553 VData =
Op.getOperand(2);
10555 IsAtomicPacked16Bit =
10556 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10557 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10558 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10559 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10564 "unsupported image atomic data type");
10576 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10578 DMask = Is64Bit ? 0xf : 0x3;
10579 NumVDataDwords = Is64Bit ? 4 : 2;
10581 DMask = Is64Bit ? 0x3 : 0x1;
10582 NumVDataDwords = Is64Bit ? 2 : 1;
10585 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10588 if (BaseOpcode->
Store) {
10589 VData =
Op.getOperand(2);
10593 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10596 "unsupported image store data type");
10598 if (StoreScalarVT == MVT::f16) {
10599 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10603 VData = handleD16VData(VData, DAG,
true);
10606 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10607 }
else if (!BaseOpcode->
NoReturn) {
10612 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10615 "unsupported image load data type");
10617 if (LoadScalarVT == MVT::f16) {
10618 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10626 (!LoadVT.
isVector() && DMaskLanes > 1))
10632 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10633 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10634 NumVDataDwords = (DMaskLanes + 1) / 2;
10636 NumVDataDwords = DMaskLanes;
10638 AdjustRetType =
true;
10642 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10649 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10650 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10652 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10654 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10655 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10659 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10665 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10669 "Bias needs to be converted to 16 bit in A16 mode");
10674 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10678 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10679 "require 16 bit args for both gradients and addresses");
10684 if (!
ST->hasA16()) {
10685 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10686 "support 16 bit addresses\n");
10696 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10698 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10700 IntrOpcode = G16MappingInfo->
G16;
10723 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10741 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10742 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10743 const bool UseNSA =
ST->hasNSAEncoding() &&
10744 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10745 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10746 const bool UsePartialNSA =
10747 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10750 if (UsePartialNSA) {
10752 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10753 }
else if (!UseNSA) {
10764 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10772 bool IsTexFail =
false;
10773 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10782 NumVDataDwords = 1;
10784 NumVDataDwords += 1;
10785 AdjustRetType =
true;
10790 if (AdjustRetType) {
10793 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10802 MVT::i32, NumVDataDwords)
10805 ResultTypes[0] = NewVT;
10806 if (ResultTypes.size() == 3) {
10810 ResultTypes.erase(&ResultTypes[1]);
10824 Ops.push_back(VData);
10825 if (UsePartialNSA) {
10827 Ops.push_back(VAddr);
10831 Ops.push_back(VAddr);
10834 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10835 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10837 Ops.push_back(Rsrc);
10838 bool IsSampIndexed =
false;
10842 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10843 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10845 Ops.push_back(Samp);
10850 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10851 Ops.push_back(Unorm);
10853 Ops.push_back(IsA16 &&
10854 ST->hasFeature(AMDGPU::FeatureR128A16)
10860 if (!Subtarget->hasGFX90AInsts())
10861 Ops.push_back(TFE);
10865 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10868 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10869 Ops.push_back(LWE);
10875 Ops.push_back(
Op.getOperand(0));
10877 int NumVAddrDwords =
10884 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10885 }
else if (IsGFX12Plus) {
10887 NumVDataDwords, NumVAddrDwords);
10888 }
else if (IsGFX11Plus) {
10890 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10891 : AMDGPU::MIMGEncGfx11Default,
10892 NumVDataDwords, NumVAddrDwords);
10893 }
else if (IsGFX10Plus) {
10895 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10896 : AMDGPU::MIMGEncGfx10Default,
10897 NumVDataDwords, NumVAddrDwords);
10899 if (Subtarget->hasGFX90AInsts()) {
10901 NumVDataDwords, NumVAddrDwords);
10902 if (Opcode == -1) {
10904 DAG,
Op, OrigResultTypes,
DL,
10905 "requested image instruction is not supported on this GPU");
10908 if (Opcode == -1 &&
10911 NumVDataDwords, NumVAddrDwords);
10914 NumVDataDwords, NumVAddrDwords);
10921 MachineMemOperand *MemRef = MemOp->getMemOperand();
10940 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10941 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10950 bool HasChainResult = MMO !=
nullptr;
10954 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10955 Subtarget->hasScalarSubwordLoads();
10958 MF.
getFunction(),
"unsupported s_buffer_load result type",
10959 DL.getDebugLoc()));
10960 EVT ResultTypes[] = {VT, MVT::Other};
10962 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain,
DL);
10965 if (!HasChainResult) {
10977 if (!
Offset->isDivergent()) {
10985 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) ->
SDValue {
10987 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10990 if (HasChainResult)
10994 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10995 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10997 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10998 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
11003 !Subtarget->hasScalarDwordx3Loads()) {
11007 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
11012 if (HasChainResult)
11034 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11035 Subtarget->hasScalarSubwordLoads()) {
11039 if (HasChainResult)
11045 unsigned NumLoads = 1;
11051 if (NumElts == 8 || NumElts == 16) {
11052 NumLoads = NumElts / 4;
11056 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
11061 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
11065 for (
unsigned i = 0; i < NumLoads; ++i) {
11068 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
11069 LoadVT, LoadMMO, DAG));
11072 if (NumElts == 8 || NumElts == 16) {
11074 if (HasChainResult) {
11089 if (!Subtarget->hasArchitectedSGPRs())
11094 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11101 unsigned Width)
const {
11103 using namespace AMDGPU::Hwreg;
11105 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11145 EVT DstVT =
Op.getValueType();
11147 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11148 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11152 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11154 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11167SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11176 const bool HasE5M3ConversionInsts =
11177 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11178 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11182 EVT DstVT =
Op.getValueType();
11186 !Subtarget->hasFP8F16ConversionInsts())
11196 "only the v2f32 vector result is custom lowered");
11202 auto ConvertByte = [&](
unsigned ByteSel) {
11203 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11208 return ConvertByte(0);
11209 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11214 if (Src.getValueType() != MVT::i32) {
11224 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11225 return lowerFromFP8(
Op, IsBF8, DAG);
11233 EVT ResVT =
Op.getValueType();
11234 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11235 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11236 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11238 "only the v2i8 vector result is custom lowered");
11242 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11247 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11248 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11249 : AMDGPUISD::CVT_PK_FP8_F32;
11257 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11269SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11278 const bool HasE5M3ConversionInsts =
11279 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11280 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11290 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11293 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11296 if (SrcEltVT == MVT::f32)
11297 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11298 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11299 Subtarget->hasF16FP8ConversionInsts()) {
11302 if (!
Op.getValueType().isVector())
11304 return lowerToFP8(
Op, IsBF8,
false, DAG);
11312 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11314 EVT VT =
Op.getValueType();
11316 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11320 switch (IntrinsicID) {
11321 case Intrinsic::amdgcn_wave_reduce_min:
11322 case Intrinsic::amdgcn_wave_reduce_umin:
11323 case Intrinsic::amdgcn_wave_reduce_fmin:
11324 case Intrinsic::amdgcn_wave_reduce_max:
11325 case Intrinsic::amdgcn_wave_reduce_umax:
11326 case Intrinsic::amdgcn_wave_reduce_fmax:
11327 case Intrinsic::amdgcn_wave_reduce_add:
11328 case Intrinsic::amdgcn_wave_reduce_fadd:
11329 case Intrinsic::amdgcn_wave_reduce_sub:
11330 case Intrinsic::amdgcn_wave_reduce_fsub:
11331 case Intrinsic::amdgcn_wave_reduce_and:
11332 case Intrinsic::amdgcn_wave_reduce_or:
11333 case Intrinsic::amdgcn_wave_reduce_xor: {
11334 EVT SrcVT =
Op.getOperand(1).getValueType();
11337 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11338 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11339 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11340 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11344 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11345 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11349 Op.getOperand(0), ExtendedSrc, Strategy);
11358 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11359 if (!MFI->getUserSGPRInfo().hasImplicitBufferPtr()) {
11360 const char *
Error =
11361 Subtarget->hasArchitectedFlatScratch()
11362 ?
"intrinsic not supported on subtarget"
11363 : !Subtarget->isMesa3DOS()
11364 ?
"intrinsic not supported for OS"
11365 :
"intrinsic not supported for calling convention";
11371 return getPreloadedValue(DAG, *MFI, VT,
11374 case Intrinsic::amdgcn_dispatch_ptr:
11375 case Intrinsic::amdgcn_queue_ptr: {
11376 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11378 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11379 DL.getDebugLoc()));
11383 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11386 return getPreloadedValue(DAG, *MFI, VT, RegID);
11388 case Intrinsic::amdgcn_implicitarg_ptr: {
11390 return getImplicitArgPtr(DAG,
DL);
11391 return getPreloadedValue(DAG, *MFI, VT,
11394 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11400 return getPreloadedValue(DAG, *MFI, VT,
11403 case Intrinsic::amdgcn_dispatch_id: {
11406 case Intrinsic::amdgcn_rcp:
11407 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11408 case Intrinsic::amdgcn_rsq:
11409 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11410 case Intrinsic::amdgcn_rsq_legacy:
11414 case Intrinsic::amdgcn_rcp_legacy:
11417 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11418 case Intrinsic::amdgcn_fma_legacy:
11419 case Intrinsic::amdgcn_sudot4:
11420 case Intrinsic::amdgcn_sudot8:
11421 case Intrinsic::amdgcn_tanh:
11423 case Intrinsic::amdgcn_rsq_clamp: {
11425 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11437 case Intrinsic::r600_read_ngroups_x:
11438 if (Subtarget->isAmdHsaOS())
11441 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11444 case Intrinsic::r600_read_ngroups_y:
11445 if (Subtarget->isAmdHsaOS())
11448 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11451 case Intrinsic::r600_read_ngroups_z:
11452 if (Subtarget->isAmdHsaOS())
11455 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11458 case Intrinsic::r600_read_local_size_x:
11459 if (Subtarget->isAmdHsaOS())
11462 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11464 case Intrinsic::r600_read_local_size_y:
11465 if (Subtarget->isAmdHsaOS())
11468 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11470 case Intrinsic::r600_read_local_size_z:
11471 if (Subtarget->isAmdHsaOS())
11474 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11476 case Intrinsic::amdgcn_workgroup_id_x:
11477 return lowerWorkGroupId(DAG, *MFI, VT,
11481 case Intrinsic::amdgcn_workgroup_id_y:
11482 return lowerWorkGroupId(DAG, *MFI, VT,
11486 case Intrinsic::amdgcn_workgroup_id_z:
11487 return lowerWorkGroupId(DAG, *MFI, VT,
11491 case Intrinsic::amdgcn_cluster_id_x:
11492 return Subtarget->hasClusters()
11493 ? getPreloadedValue(DAG, *MFI, VT,
11495 : DAG.getPOISON(VT);
11496 case Intrinsic::amdgcn_cluster_id_y:
11497 return Subtarget->hasClusters()
11498 ? getPreloadedValue(DAG, *MFI, VT,
11501 case Intrinsic::amdgcn_cluster_id_z:
11502 return Subtarget->hasClusters()
11503 ? getPreloadedValue(DAG, *MFI, VT,
11506 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11507 return Subtarget->hasClusters()
11508 ? getPreloadedValue(
11512 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11513 return Subtarget->hasClusters()
11514 ? getPreloadedValue(
11518 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11519 return Subtarget->hasClusters()
11520 ? getPreloadedValue(
11524 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11525 return Subtarget->hasClusters()
11528 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11529 return Subtarget->hasClusters()
11530 ? getPreloadedValue(
11534 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11535 return Subtarget->hasClusters()
11536 ? getPreloadedValue(
11540 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11541 return Subtarget->hasClusters()
11542 ? getPreloadedValue(
11546 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11547 return Subtarget->hasClusters()
11548 ? getPreloadedValue(
11552 case Intrinsic::amdgcn_wave_id:
11553 return lowerWaveID(DAG,
Op);
11554 case Intrinsic::amdgcn_lds_kernel_id: {
11556 return getLDSKernelId(DAG,
DL);
11557 return getPreloadedValue(DAG, *MFI, VT,
11560 case Intrinsic::amdgcn_workitem_id_x:
11561 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11562 case Intrinsic::amdgcn_workitem_id_y:
11563 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11564 case Intrinsic::amdgcn_workitem_id_z:
11565 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11566 case Intrinsic::amdgcn_wavefrontsize:
11568 SDLoc(
Op), MVT::i32);
11569 case Intrinsic::amdgcn_s_buffer_load: {
11570 unsigned CPol =
Op.getConstantOperandVal(3);
11578 Op.getOperand(2),
Op.getOperand(3), DAG);
11580 case Intrinsic::amdgcn_fdiv_fast:
11581 return lowerFDIV_FAST(
Op, DAG);
11582 case Intrinsic::amdgcn_sin:
11583 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11585 case Intrinsic::amdgcn_cos:
11586 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11588 case Intrinsic::amdgcn_mul_u24:
11589 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11591 case Intrinsic::amdgcn_mul_i24:
11592 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11595 case Intrinsic::amdgcn_log_clamp: {
11601 case Intrinsic::amdgcn_fract:
11602 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11604 case Intrinsic::amdgcn_class: {
11606 EVT SrcVT = Src.getValueType();
11607 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11608 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11612 "llvm.amdgcn.class only supports f16, f32, and f64",
11613 DL.getDebugLoc()));
11616 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11618 case Intrinsic::amdgcn_div_fmas:
11619 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11620 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11622 case Intrinsic::amdgcn_div_fixup:
11623 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11624 Op.getOperand(2),
Op.getOperand(3));
11626 case Intrinsic::amdgcn_div_scale: {
11632 SDValue Denominator =
Op.getOperand(2);
11641 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11642 Denominator, Numerator);
11644 case Intrinsic::amdgcn_ballot:
11646 case Intrinsic::amdgcn_fmed3:
11647 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11648 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11649 case Intrinsic::amdgcn_fdot2:
11650 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11651 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11652 case Intrinsic::amdgcn_fmul_legacy:
11653 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11655 case Intrinsic::amdgcn_sbfe:
11656 case Intrinsic::amdgcn_ubfe:
11658 case Intrinsic::amdgcn_cvt_pkrtz:
11659 case Intrinsic::amdgcn_cvt_pknorm_i16:
11660 case Intrinsic::amdgcn_cvt_pknorm_u16:
11661 case Intrinsic::amdgcn_cvt_pk_i16:
11662 case Intrinsic::amdgcn_cvt_pk_u16: {
11664 EVT VT =
Op.getValueType();
11667 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11668 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11669 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11670 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11671 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11672 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11673 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11674 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11676 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11679 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11682 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11685 case Intrinsic::amdgcn_fmad_ftz:
11686 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11687 Op.getOperand(2),
Op.getOperand(3));
11689 case Intrinsic::amdgcn_if_break:
11691 Op->getOperand(1),
Op->getOperand(2)),
11694 case Intrinsic::amdgcn_groupstaticsize: {
11700 const GlobalValue *GV =
11706 case Intrinsic::amdgcn_is_shared:
11707 case Intrinsic::amdgcn_is_private: {
11714 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11718 Subtarget->hasGloballyAddressableScratch()) {
11721 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11722 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11731 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11734 case Intrinsic::amdgcn_perm:
11735 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11736 Op.getOperand(2),
Op.getOperand(3));
11737 case Intrinsic::amdgcn_reloc_constant: {
11747 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11748 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11749 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11750 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11751 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11752 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11753 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11754 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11755 if (
Op.getOperand(4).getValueType() == MVT::i32)
11761 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11762 Op.getOperand(3), IndexKeyi32);
11764 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11765 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11766 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11767 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11768 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11769 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11770 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11771 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11772 if (
Op.getOperand(4).getValueType() == MVT::i64)
11777 Op.getOperand(4).getValueType() == MVT::v2i32
11781 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11782 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11783 Op.getOperand(6)});
11785 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11786 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11787 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11788 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11789 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11790 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11791 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11794 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11799 Op.getOperand(6).getValueType().isVector()
11803 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11804 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11805 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11806 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11807 Args.push_back(
Op.getOperand(9));
11810 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11811 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11812 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11813 if (
Op.getOperand(6).getValueType() == MVT::i32)
11819 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11820 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11821 IndexKeyi32, Op.getOperand(7)});
11823 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11824 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11825 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11826 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11827 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11828 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11832 "invalid matrix and scale format combination in wmma call");
11838 case Intrinsic::amdgcn_readlane:
11839 case Intrinsic::amdgcn_readfirstlane:
11840 case Intrinsic::amdgcn_writelane:
11841 case Intrinsic::amdgcn_permlane16:
11842 case Intrinsic::amdgcn_permlanex16:
11843 case Intrinsic::amdgcn_permlane64:
11844 case Intrinsic::amdgcn_set_inactive:
11845 case Intrinsic::amdgcn_set_inactive_chain_arg:
11846 case Intrinsic::amdgcn_mov_dpp8:
11847 case Intrinsic::amdgcn_update_dpp:
11848 case Intrinsic::amdgcn_permlane_bcast:
11849 case Intrinsic::amdgcn_permlane_up:
11850 case Intrinsic::amdgcn_permlane_down:
11851 case Intrinsic::amdgcn_permlane_xor:
11853 case Intrinsic::amdgcn_dead: {
11855 for (
const EVT ValTy :
Op.getNode()->values())
11859 case Intrinsic::amdgcn_wave_shuffle:
11862 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11864 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11875 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11881 unsigned NewOpcode)
const {
11888 "unsupported buffer atomic data type");
11890 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11891 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11909 M->getMemOperand());
11914 unsigned NewOpcode)
const {
11921 "unsupported buffer atomic data type");
11923 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11924 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11942 M->getMemOperand());
11949 unsigned NumOperands =
N->getNumOperands();
11950 if (
N->getOperand(NumOperands - 1) == Zero)
11953 Ops[NumOperands - 1] = Zero;
11959 unsigned IntrID =
Op.getConstantOperandVal(1);
11963 case Intrinsic::amdgcn_cluster_load_b32:
11964 case Intrinsic::amdgcn_cluster_load_b64:
11965 case Intrinsic::amdgcn_cluster_load_b128: {
11966 if (Subtarget->hasGFX1250_STRICT())
11970 case Intrinsic::amdgcn_ds_ordered_add:
11971 case Intrinsic::amdgcn_ds_ordered_swap: {
11976 unsigned IndexOperand =
M->getConstantOperandVal(7);
11977 unsigned WaveRelease =
M->getConstantOperandVal(8);
11978 unsigned WaveDone =
M->getConstantOperandVal(9);
11980 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11981 IndexOperand &= ~0x3f;
11982 unsigned CountDw = 0;
11985 CountDw = (IndexOperand >> 24) & 0xf;
11986 IndexOperand &= ~(0xf << 24);
11988 if (CountDw < 1 || CountDw > 4) {
11991 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11992 DL.getDebugLoc()));
11997 if (IndexOperand) {
12000 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
12003 if (WaveDone && !WaveRelease) {
12007 Fn,
"ds_ordered_count: wave_done requires wave_release",
12008 DL.getDebugLoc()));
12011 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
12012 unsigned ShaderType =
12014 unsigned Offset0 = OrderedCountIndex << 2;
12015 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
12018 Offset1 |= (CountDw - 1) << 6;
12021 Offset1 |= ShaderType << 2;
12023 unsigned Offset = Offset0 | (Offset1 << 8);
12030 M->getVTList(),
Ops,
M->getMemoryVT(),
12031 M->getMemOperand());
12033 case Intrinsic::amdgcn_ptr_s_buffer_load: {
12034 unsigned CPol =
Op.getConstantOperandVal(4);
12041 return lowerSBuffer(
12042 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
12043 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
12044 Op.getOperand(4), DAG,
M->getMemOperand());
12046 case Intrinsic::amdgcn_raw_buffer_load:
12047 case Intrinsic::amdgcn_raw_ptr_buffer_load:
12048 case Intrinsic::amdgcn_raw_atomic_buffer_load:
12049 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12050 case Intrinsic::amdgcn_raw_buffer_load_format:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12052 const bool IsFormat =
12053 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12054 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12056 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12057 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12071 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
12073 case Intrinsic::amdgcn_struct_buffer_load:
12074 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12075 case Intrinsic::amdgcn_struct_buffer_load_format:
12076 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12077 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12078 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12079 const bool IsFormat =
12080 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12081 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12083 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12084 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12099 case Intrinsic::amdgcn_raw_tbuffer_load:
12100 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12102 EVT LoadVT =
Op.getValueType();
12103 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12104 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12120 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12122 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12123 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12126 case Intrinsic::amdgcn_struct_tbuffer_load:
12127 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12129 EVT LoadVT =
Op.getValueType();
12130 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12131 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12147 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12149 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12150 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12153 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12154 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12155 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12156 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12157 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12158 return lowerStructBufferAtomicIntrin(
Op, DAG,
12159 AMDGPUISD::BUFFER_ATOMIC_FADD);
12160 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12161 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12162 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12163 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12164 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12165 return lowerStructBufferAtomicIntrin(
Op, DAG,
12166 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12167 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12168 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12169 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12170 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12172 return lowerStructBufferAtomicIntrin(
Op, DAG,
12173 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12174 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12175 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12176 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12177 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12179 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12180 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12182 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12183 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12185 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12186 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12187 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12188 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12189 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12190 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12191 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12192 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12193 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12194 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12195 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12197 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12198 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12199 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12200 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12201 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12202 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12203 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12204 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12205 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12206 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12207 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12208 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12209 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12210 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12211 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12212 return lowerStructBufferAtomicIntrin(
Op, DAG,
12213 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12214 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12215 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12216 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12217 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12218 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12219 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12220 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12221 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12222 return lowerStructBufferAtomicIntrin(
Op, DAG,
12223 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12224 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12225 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12226 return lowerStructBufferAtomicIntrin(
Op, DAG,
12227 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12228 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12229 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12230 return lowerStructBufferAtomicIntrin(
Op, DAG,
12231 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12232 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12233 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12234 return lowerStructBufferAtomicIntrin(
Op, DAG,
12235 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12236 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12237 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12238 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12239 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12240 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12241 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12242 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12243 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12244 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12245 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12246 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12247 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12248 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12249 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12250 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12251 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12252 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12253 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12254 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12255 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12256 return lowerStructBufferAtomicIntrin(
Op, DAG,
12257 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12258 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12259 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12260 return lowerRawBufferAtomicIntrin(
Op, DAG,
12261 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12262 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12263 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12264 return lowerStructBufferAtomicIntrin(
Op, DAG,
12265 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12266 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12267 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12269 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12272 "unsupported buffer atomic data type");
12274 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12275 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12289 EVT VT =
Op.getValueType();
12293 Op->getVTList(),
Ops, VT,
12294 M->getMemOperand());
12296 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12297 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12299 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12302 "unsupported buffer atomic data type");
12304 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12305 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12319 EVT VT =
Op.getValueType();
12323 Op->getVTList(),
Ops, VT,
12324 M->getMemOperand());
12326 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12327 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12329 SDValue NodePtr =
M->getOperand(2);
12330 SDValue RayExtent =
M->getOperand(3);
12331 SDValue InstanceMask =
M->getOperand(4);
12332 SDValue RayOrigin =
M->getOperand(5);
12333 SDValue RayDir =
M->getOperand(6);
12335 SDValue TDescr =
M->getOperand(8);
12340 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12341 const unsigned NumVDataDwords = 10;
12342 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12344 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12345 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12346 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12350 Ops.push_back(NodePtr);
12353 {DAG.getBitcast(MVT::i32, RayExtent),
12354 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12355 Ops.push_back(RayOrigin);
12356 Ops.push_back(RayDir);
12357 Ops.push_back(Offsets);
12358 Ops.push_back(TDescr);
12359 Ops.push_back(
M->getChain());
12362 MachineMemOperand *MemRef =
M->getMemOperand();
12366 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12368 SDValue NodePtr =
M->getOperand(2);
12369 SDValue RayExtent =
M->getOperand(3);
12370 SDValue RayOrigin =
M->getOperand(4);
12371 SDValue RayDir =
M->getOperand(5);
12372 SDValue RayInvDir =
M->getOperand(6);
12373 SDValue TDescr =
M->getOperand(7);
12385 const unsigned NumVDataDwords = 4;
12386 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12387 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12388 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12391 const unsigned BaseOpcodes[2][2] = {
12392 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12393 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12394 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12398 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12399 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12400 : AMDGPU::MIMGEncGfx10NSA,
12401 NumVDataDwords, NumVAddrDwords);
12405 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12406 : AMDGPU::MIMGEncGfx10Default,
12407 NumVDataDwords, NumVAddrDwords);
12413 auto packLanes = [&DAG, &
Ops, &
DL](
SDValue Op,
bool IsAligned) {
12416 if (Lanes[0].getValueSizeInBits() == 32) {
12417 for (
unsigned I = 0;
I < 3; ++
I)
12424 Ops.push_back(Lanes[2]);
12436 if (UseNSA && IsGFX11Plus) {
12437 Ops.push_back(NodePtr);
12439 Ops.push_back(RayOrigin);
12444 for (
unsigned I = 0;
I < 3; ++
I) {
12447 {DirLanes[I], InvDirLanes[I]})));
12451 Ops.push_back(RayDir);
12452 Ops.push_back(RayInvDir);
12459 Ops.push_back(NodePtr);
12462 packLanes(RayOrigin,
true);
12463 packLanes(RayDir,
true);
12464 packLanes(RayInvDir,
false);
12469 if (NumVAddrDwords > 12) {
12477 Ops.push_back(MergedOps);
12480 Ops.push_back(TDescr);
12482 Ops.push_back(
M->getChain());
12485 MachineMemOperand *MemRef =
M->getMemOperand();
12489 case Intrinsic::amdgcn_global_atomic_fmin_num:
12490 case Intrinsic::amdgcn_global_atomic_fmax_num:
12491 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12492 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12499 unsigned Opcode = 0;
12501 case Intrinsic::amdgcn_global_atomic_fmin_num:
12502 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12506 case Intrinsic::amdgcn_global_atomic_fmax_num:
12507 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12514 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12515 Ops,
M->getMemOperand());
12517 case Intrinsic::amdgcn_s_alloc_vgpr: {
12525 ReadFirstLaneID, NumVGPRs);
12528 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12530 case Intrinsic::amdgcn_s_get_barrier_state:
12531 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12538 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12539 BarID = BarID & 0x3F;
12540 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12543 Ops.push_back(Chain);
12545 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12546 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12557 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12558 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12559 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12563 EVT VT =
Op->getValueType(0);
12567 case Intrinsic::amdgcn_av_load_b8:
12568 case Intrinsic::amdgcn_av_load_b16:
12569 case Intrinsic::amdgcn_av_load_b32:
12570 case Intrinsic::amdgcn_av_load_b64:
12571 case Intrinsic::amdgcn_av_load_b128: {
12575 EVT VT =
Op->getValueType(0);
12582 case Intrinsic::amdgcn_flat_load_monitor_b32:
12583 case Intrinsic::amdgcn_flat_load_monitor_b64:
12584 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12589 Op->getVTList(), {Chain, Ptr},
12592 case Intrinsic::amdgcn_global_load_monitor_b32:
12593 case Intrinsic::amdgcn_global_load_monitor_b64:
12594 case Intrinsic::amdgcn_global_load_monitor_b128: {
12599 Op->getVTList(), {Chain, Ptr},
12604 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12606 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12614SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12621 EVT VT = VTList.
VTs[0];
12624 bool IsTFE = VTList.
NumVTs == 3;
12627 unsigned NumOpDWords = NumValueDWords + 1;
12629 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12630 MachineMemOperand *OpDWordsMMO =
12632 SDValue Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12633 OpDWordsVT, OpDWordsMMO, DAG);
12638 if (!Subtarget->hasDwordx3LoadStores() &&
12639 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12643 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12645 WidenedMemVT, WidenedMMO);
12655 bool ImageStore)
const {
12665 if (Subtarget->hasUnpackedD16VMem()) {
12679 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12690 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12696 if ((NumElements % 2) == 1) {
12698 unsigned I = Elts.
size() / 2;
12714 if (NumElements == 3) {
12733 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12734 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12735 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12736 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12737 case Intrinsic::amdgcn_load_async_to_lds:
12738 case Intrinsic::amdgcn_global_load_async_lds:
12748 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12750 switch (IntrinsicID) {
12751 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12752 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12753 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12754 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12755 if (Subtarget->hasGFX1250_STRICT())
12759 case Intrinsic::amdgcn_exp_compr: {
12780 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12784 case Intrinsic::amdgcn_struct_tbuffer_store:
12785 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12789 VData = handleD16VData(VData, DAG);
12790 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12791 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12805 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12806 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12809 M->getMemoryVT(),
M->getMemOperand());
12812 case Intrinsic::amdgcn_raw_tbuffer_store:
12813 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12817 VData = handleD16VData(VData, DAG);
12818 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12819 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12833 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12834 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12837 M->getMemoryVT(),
M->getMemOperand());
12840 case Intrinsic::amdgcn_raw_buffer_store:
12841 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12842 case Intrinsic::amdgcn_raw_buffer_store_format:
12843 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12844 const bool IsFormat =
12845 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12846 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12856 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12861 VData = handleD16VData(VData, DAG);
12871 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12872 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12886 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12887 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12892 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12895 M->getMemoryVT(),
M->getMemOperand());
12898 case Intrinsic::amdgcn_struct_buffer_store:
12899 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12900 case Intrinsic::amdgcn_struct_buffer_store_format:
12901 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12902 const bool IsFormat =
12903 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12904 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12914 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12919 VData = handleD16VData(VData, DAG);
12929 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12930 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12944 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12945 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12949 EVT VDataType = VData.getValueType().getScalarType();
12951 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12954 M->getMemoryVT(),
M->getMemOperand());
12956 case Intrinsic::amdgcn_raw_buffer_load_lds:
12957 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12958 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12959 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12960 case Intrinsic::amdgcn_struct_buffer_load_lds:
12961 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12962 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12963 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12966 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12967 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12968 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12969 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12970 unsigned OpOffset = HasVIndex ? 1 : 0;
12971 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12973 unsigned Size =
Op->getConstantOperandVal(4);
12979 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12980 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12981 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12982 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12985 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12986 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12987 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12988 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12991 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12992 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12993 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12994 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12997 if (!Subtarget->hasLDSLoadB96_B128())
12999 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
13000 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
13001 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
13002 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
13005 if (!Subtarget->hasLDSLoadB96_B128())
13007 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
13008 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
13009 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
13010 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
13018 if (HasVIndex && HasVOffset)
13022 else if (HasVIndex)
13023 Ops.push_back(
Op.getOperand(5));
13024 else if (HasVOffset)
13025 Ops.push_back(VOffset);
13027 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
13028 Ops.push_back(Rsrc);
13029 Ops.push_back(
Op.getOperand(6 + OpOffset));
13030 Ops.push_back(
Op.getOperand(7 + OpOffset));
13032 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
13055 case Intrinsic::amdgcn_load_to_lds:
13056 case Intrinsic::amdgcn_load_async_to_lds:
13057 case Intrinsic::amdgcn_global_load_lds:
13058 case Intrinsic::amdgcn_global_load_async_lds: {
13059 if (!Subtarget->hasVMemToLDSLoad())
13063 unsigned Size =
Op->getConstantOperandVal(4);
13068 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13071 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13074 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13077 if (!Subtarget->hasLDSLoadB96_B128())
13079 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13082 if (!Subtarget->hasLDSLoadB96_B128())
13084 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13100 if (
LHS->isDivergent())
13104 RHS.getOperand(0).getValueType() == MVT::i32) {
13107 VOffset =
RHS.getOperand(0);
13111 Ops.push_back(Addr);
13119 Ops.push_back(VOffset);
13122 Ops.push_back(
Op.getOperand(5));
13124 unsigned Aux =
Op.getConstantOperandVal(6);
13139 case Intrinsic::amdgcn_end_cf:
13141 Op->getOperand(2), Chain),
13143 case Intrinsic::amdgcn_s_barrier_signal_var: {
13150 if (CntC && CntC->isZero()) {
13155 std::optional<uint64_t> BarVal;
13157 BarVal =
C->getZExtValue();
13161 BarVal = *Addr + GA->getOffset();
13164 unsigned BarID = *BarVal & 0x3F;
13166 Ops.push_back(Chain);
13168 Op->getVTList(),
Ops);
13174 case Intrinsic::amdgcn_s_barrier_init: {
13181 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13182 ? AMDGPU::S_BARRIER_INIT_M0
13183 : AMDGPU::S_BARRIER_SIGNAL_M0;
13193 constexpr unsigned ShAmt = 16;
13204 case Intrinsic::amdgcn_s_wakeup_barrier: {
13205 if (!Subtarget->hasSWakeupBarrier())
13209 case Intrinsic::amdgcn_s_barrier_join: {
13218 switch (IntrinsicID) {
13221 case Intrinsic::amdgcn_s_barrier_join:
13222 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13224 case Intrinsic::amdgcn_s_wakeup_barrier:
13225 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13229 unsigned BarID = BarVal & 0x3F;
13232 Ops.push_back(Chain);
13234 switch (IntrinsicID) {
13237 case Intrinsic::amdgcn_s_barrier_join:
13238 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13240 case Intrinsic::amdgcn_s_wakeup_barrier:
13241 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13253 case Intrinsic::amdgcn_s_prefetch_data:
13254 case Intrinsic::amdgcn_s_prefetch_inst: {
13257 return Op.getOperand(0);
13260 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13262 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13269 Op->getVTList(),
Ops,
M->getMemoryVT(),
13270 M->getMemOperand());
13272 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13273 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13274 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13282 case Intrinsic::amdgcn_av_store_b8:
13283 case Intrinsic::amdgcn_av_store_b16:
13284 case Intrinsic::amdgcn_av_store_b32:
13285 case Intrinsic::amdgcn_av_store_b64:
13286 case Intrinsic::amdgcn_av_store_b128: {
13294 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13296 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13312 return PtrVT == MVT::i64;
13326std::pair<SDValue, SDValue>
13339 bool CheckNUW =
Subtarget->hasGFX1250Insts();
13347 unsigned ImmOffset =
C1->getZExtValue();
13356 unsigned Overflow = ImmOffset & ~MaxImm;
13357 ImmOffset -= Overflow;
13358 if ((int32_t)Overflow < 0) {
13359 Overflow += ImmOffset;
13364 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13383void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13385 Align Alignment)
const {
13387 SDLoc
DL(CombinedOffset);
13389 uint32_t
Imm =
C->getZExtValue();
13390 uint32_t SOffset, ImmOffset;
13391 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13402 bool CheckNUW = Subtarget->hasGFX1250Insts();
13405 uint32_t SOffset, ImmOffset;
13408 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13416 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13425SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13428 return MaybePointer;
13442 SDValue NumRecords =
Op->getOperand(3);
13448 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13451 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13470 SDValue ExtShiftedStrideVec =
13482 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13484 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13489 auto [LowHalf, HighHalf] =
13490 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13500 NumRecords, Flags);
13512 bool IsTFE)
const {
13517 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13518 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13521 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13533 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13534 : AMDGPUISD::BUFFER_LOAD_USHORT;
13536 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13550 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13554 Ops[1] = BufferStoreExt;
13555 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13556 : AMDGPUISD::BUFFER_STORE_SHORT;
13559 M->getMemOperand());
13584 DAGCombinerInfo &DCI)
const {
13585 SelectionDAG &DAG = DCI.DAG;
13586 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13590 unsigned AS = Ld->getAddressSpace();
13599 EVT MemVT = Ld->getMemoryVT();
13600 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13607 "unexpected vector extload");
13610 SDValue Ptr = Ld->getBasePtr();
13613 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13614 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13619 "unexpected fp extload");
13634 EVT VT = Ld->getValueType(0);
13637 DCI.AddToWorklist(Cvt.
getNode());
13642 DCI.AddToWorklist(Cvt.
getNode());
13653 if (Info.isEntryFunction())
13654 return Info.getUserSGPRInfo().hasFlatScratchInit();
13662 EVT MemVT =
Load->getMemoryVT();
13663 MachineMemOperand *MMO =
Load->getMemOperand();
13670 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13677 BasePtr, MVT::i16, MMO);
13700 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13728 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13729 "Custom lowering for non-i32 vectors hasn't been implemented.");
13732 unsigned AS =
Load->getAddressSpace();
13733 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13740 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13744 !Subtarget->hasMultiDwordFlatScratchAddressing())
13756 Alignment >=
Align(4) && NumElements < 32) {
13758 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13770 if (NumElements > 4)
13773 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13783 switch (Subtarget->getMaxPrivateElementSize()) {
13789 if (NumElements > 2)
13794 if (NumElements > 4)
13797 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13806 auto Flags =
Load->getMemOperand()->getFlags();
13808 Load->getAlign(), Flags, &
Fast) &&
13817 MemVT, *
Load->getMemOperand())) {
13826 EVT VT =
Op.getValueType();
13863 EVT VT =
Op.getValueType();
13864 const SDNodeFlags
Flags =
Op->getFlags();
13866 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13872 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13875 if (CLHS->isOne()) {
13888 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13892 if (CLHS->isMinusOne()) {
13895 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13901 if (!AllowInaccurateRcp &&
13902 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13916 EVT VT =
Op.getValueType();
13917 const SDNodeFlags
Flags =
Op->getFlags();
13919 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13920 if (!AllowInaccurateDiv)
13944 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13956 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13966 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13970 return DAG.
getNode(Opcode, SL, VTList,
13979 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13989 Opcode = AMDGPUISD::FMA_W_CHAIN;
13993 return DAG.
getNode(Opcode, SL, VTList,
13999 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
14000 return FastLowered;
14003 EVT VT =
Op.getValueType();
14010 if (VT == MVT::bf16) {
14033 unsigned FMADOpCode =
14037 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
14040 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14042 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
14043 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14053 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
14059 SDNodeFlags
Flags =
Op->getFlags();
14069 const APFloat K0Val(0x1p+96f);
14072 const APFloat K1Val(0x1p-32f);
14099 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
14100 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14101 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14106 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
14107 return FastLowered;
14113 SDNodeFlags
Flags =
Op->getFlags();
14114 Flags.setNoFPExcept(
true);
14122 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
14131 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14135 using namespace AMDGPU::Hwreg;
14136 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14140 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
14141 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
14144 const bool HasDynamicDenormals =
14150 if (!PreservesDenormals) {
14155 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14158 if (HasDynamicDenormals) {
14162 SavedDenormMode =
SDValue(GetReg, 0);
14168 SDNode *EnableDenorm;
14169 if (Subtarget->hasDenormModeInst()) {
14170 const SDValue EnableDenormValue =
14173 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14177 const SDValue EnableDenormValue =
14179 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14180 {EnableDenormValue,
BitField, Glue});
14190 ApproxRcp, One, NegDivScale0, Flags);
14193 ApproxRcp, Fma0, Flags);
14199 NumeratorScaled,
Mul, Flags);
14205 NumeratorScaled, Fma3, Flags);
14207 if (!PreservesDenormals) {
14208 SDNode *DisableDenorm;
14209 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14213 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14215 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14219 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14220 const SDValue DisableDenormValue =
14221 HasDynamicDenormals
14226 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14237 {Fma4, Fma1, Fma3, Scale},
Flags);
14239 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14243 if (
SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14244 return FastLowered;
14252 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14258 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14276 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14306 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14308 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14312 EVT VT =
Op.getValueType();
14314 if (VT == MVT::f32)
14315 return LowerFDIV32(
Op, DAG);
14317 if (VT == MVT::f64)
14318 return LowerFDIV64(
Op, DAG);
14320 if (VT == MVT::f16 || VT == MVT::bf16)
14321 return LowerFDIV16(
Op, DAG);
14330 EVT ResultExpVT =
Op->getValueType(1);
14331 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14341 if (Subtarget->hasFractBug()) {
14359 EVT VT =
Store->getMemoryVT();
14361 if (VT == MVT::i1) {
14365 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14369 Store->getValue().getValueType().getScalarType() == MVT::i32);
14371 unsigned AS =
Store->getAddressSpace();
14372 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14380 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14384 !Subtarget->hasMultiDwordFlatScratchAddressing())
14391 if (NumElements > 4)
14394 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14398 VT, *
Store->getMemOperand()))
14404 switch (Subtarget->getMaxPrivateElementSize()) {
14408 if (NumElements > 2)
14412 if (NumElements > 4 ||
14413 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14421 auto Flags =
Store->getMemOperand()->getFlags();
14440 assert(!Subtarget->has16BitInsts());
14441 SDNodeFlags
Flags =
Op->getFlags();
14455 SDNodeFlags
Flags =
Op->getFlags();
14456 MVT VT =
Op.getValueType().getSimpleVT();
14564 SDNodeFlags
Flags =
Op->getFlags();
14573 if (!
Flags.hasApproximateFuncs()) {
14605 if (!
Flags.hasApproximateFuncs()) {
14614 ScaleDownFactor, ZeroInt);
14621 if (
Flags.hasNoInfs()) {
14637 EVT VT =
Op.getValueType();
14648 if (!
V.getValueType().isVector())
14656 if (Subtarget->hasTrigReducedRange()) {
14658 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14663 switch (
Op.getOpcode()) {
14665 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14668 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14674 return UnrollIfVec(TrigVal);
14694 EVT VT =
Op.getValueType();
14702 Op->getVTList(),
Ops, VT,
14711SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14712 DAGCombinerInfo &DCI)
const {
14713 EVT VT =
N->getValueType(0);
14715 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14718 SelectionDAG &DAG = DCI.DAG;
14722 EVT SrcVT = Src.getValueType();
14728 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14731 DCI.AddToWorklist(Cvt.
getNode());
14734 if (ScalarVT != MVT::f32) {
14746 DAGCombinerInfo &DCI)
const {
14757 SelectionDAG &DAG = DCI.DAG;
14776 for (
unsigned I = 0;
I != NumElts; ++
I) {
14800 if (NewElts.
size() == 1)
14822 for (
unsigned I = 0;
I != NumElts; ++
I) {
14857SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14859 DAGCombinerInfo &DCI)
const {
14876 SelectionDAG &DAG = DCI.DAG;
14889 AM.BaseOffs =
Offset.getSExtValue();
14894 EVT VT =
N->getValueType(0);
14900 Flags.setNoUnsignedWrap(
14901 N->getFlags().hasNoUnsignedWrap() &&
14913 switch (
N->getOpcode()) {
14924 DAGCombinerInfo &DCI)
const {
14925 SelectionDAG &DAG = DCI.DAG;
14932 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14933 N->getMemoryVT(), DCI);
14937 NewOps[PtrIdx] = NewPtr;
14946 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14947 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14956SDValue SITargetLowering::splitBinaryBitConstantOp(
14960 uint32_t ValLo =
Lo_32(Val);
14961 uint32_t ValHi =
Hi_32(Val);
14968 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14982 if (V.getValueType() != MVT::i1)
14984 switch (V.getOpcode()) {
14989 case AMDGPUISD::FP_CLASS:
15001 return V.getResNo() == 1;
15003 unsigned IntrinsicID = V.getConstantOperandVal(0);
15004 switch (IntrinsicID) {
15005 case Intrinsic::amdgcn_is_shared:
15006 case Intrinsic::amdgcn_is_private:
15023 if (!(
C & 0x000000ff))
15024 ZeroByteMask |= 0x000000ff;
15025 if (!(
C & 0x0000ff00))
15026 ZeroByteMask |= 0x0000ff00;
15027 if (!(
C & 0x00ff0000))
15028 ZeroByteMask |= 0x00ff0000;
15029 if (!(
C & 0xff000000))
15030 ZeroByteMask |= 0xff000000;
15031 uint32_t NonZeroByteMask = ~ZeroByteMask;
15032 if ((NonZeroByteMask &
C) != NonZeroByteMask)
15045 assert(
V.getValueSizeInBits() == 32);
15047 if (
V.getNumOperands() != 2)
15056 switch (
V.getOpcode()) {
15061 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15066 return (0x03020100 & ~ConstMask) | ConstMask;
15073 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
15079 return uint32_t(0x0c0c0c0c03020100ull >>
C);
15086 DAGCombinerInfo &DCI)
const {
15087 if (DCI.isBeforeLegalize())
15090 SelectionDAG &DAG = DCI.DAG;
15091 EVT VT =
N->getValueType(0);
15096 if (VT == MVT::i64 && CRHS) {
15098 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
15102 if (CRHS && VT == MVT::i32) {
15112 unsigned Shift = CShift->getZExtValue();
15114 unsigned Offset = NB + Shift;
15115 if ((
Offset & (Bits - 1)) == 0) {
15118 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
15139 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15141 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15151 if (Shift && Shift->getZExtValue() < 16 &&
15170 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
15175 if (
X !=
LHS.getOperand(1))
15179 const ConstantFPSDNode *
C1 =
15181 if (!
C1 || !
C1->isInfinity() ||
C1->isNegative())
15196 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15202 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15205 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15213 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15214 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15216 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15217 :
Mask->getZExtValue() & OrdMask;
15220 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15238 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15241 if (LHSMask != ~0u && RHSMask != ~0u) {
15244 if (LHSMask > RHSMask) {
15251 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15252 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15255 if (!(LHSUsedLanes & RHSUsedLanes) &&
15258 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15264 uint32_t
Mask = LHSMask & RHSMask;
15265 for (
unsigned I = 0;
I < 32;
I += 8) {
15266 uint32_t ByteSel = 0xff <<
I;
15267 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15268 Mask &= (0x0c <<
I) & 0xffffffff;
15273 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15276 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15326static const std::optional<ByteProvider<SDValue>>
15328 unsigned Depth = 0) {
15331 return std::nullopt;
15333 if (
Op.getValueSizeInBits() < 8)
15334 return std::nullopt;
15336 if (
Op.getValueType().isVector())
15339 switch (
Op->getOpcode()) {
15352 NarrowVT = VTSign->getVT();
15355 return std::nullopt;
15358 if (SrcIndex >= NarrowByteWidth)
15359 return std::nullopt;
15367 return std::nullopt;
15369 uint64_t BitShift = ShiftOp->getZExtValue();
15371 if (BitShift % 8 != 0)
15372 return std::nullopt;
15374 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15375 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15376 return std::nullopt;
15395static const std::optional<ByteProvider<SDValue>>
15397 unsigned StartingIndex = 0) {
15401 return std::nullopt;
15403 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15405 return std::nullopt;
15407 return std::nullopt;
15409 bool IsVec =
Op.getValueType().isVector();
15410 switch (
Op.getOpcode()) {
15413 return std::nullopt;
15418 return std::nullopt;
15422 return std::nullopt;
15425 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15426 return std::nullopt;
15427 if (!
LHS ||
LHS->isConstantZero())
15429 if (!
RHS ||
RHS->isConstantZero())
15431 return std::nullopt;
15436 return std::nullopt;
15440 return std::nullopt;
15442 uint32_t BitMask = BitMaskOp->getZExtValue();
15444 uint32_t IndexMask = 0xFF << (Index * 8);
15446 if ((IndexMask & BitMask) != IndexMask) {
15449 if (IndexMask & BitMask)
15450 return std::nullopt;
15459 return std::nullopt;
15463 if (!ShiftOp ||
Op.getValueType().isVector())
15464 return std::nullopt;
15466 uint64_t BitsProvided =
Op.getValueSizeInBits();
15467 if (BitsProvided % 8 != 0)
15468 return std::nullopt;
15470 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15472 return std::nullopt;
15474 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15475 uint64_t ByteShift = BitShift / 8;
15477 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15478 uint64_t BytesProvided = BitsProvided / 8;
15479 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15480 NewIndex %= BytesProvided;
15487 return std::nullopt;
15491 return std::nullopt;
15493 uint64_t BitShift = ShiftOp->getZExtValue();
15495 return std::nullopt;
15497 auto BitsProvided =
Op.getScalarValueSizeInBits();
15498 if (BitsProvided % 8 != 0)
15499 return std::nullopt;
15501 uint64_t BytesProvided = BitsProvided / 8;
15502 uint64_t ByteShift = BitShift / 8;
15503 if (Index + ByteShift < BytesProvided)
15505 Index + ByteShift);
15508 return std::nullopt;
15514 return std::nullopt;
15518 return std::nullopt;
15520 uint64_t BitShift = ShiftOp->getZExtValue();
15521 if (BitShift % 8 != 0)
15522 return std::nullopt;
15523 uint64_t ByteShift = BitShift / 8;
15529 return Index < ByteShift
15532 Depth + 1, StartingIndex);
15541 return std::nullopt;
15549 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15551 if (NarrowBitWidth % 8 != 0)
15552 return std::nullopt;
15553 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15555 if (Index >= NarrowByteWidth)
15557 ? std::optional<ByteProvider<SDValue>>(
15565 return std::nullopt;
15569 if (NarrowByteWidth >= Index) {
15574 return std::nullopt;
15581 return std::nullopt;
15587 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15588 if (NarrowBitWidth % 8 != 0)
15589 return std::nullopt;
15590 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15595 if (Index >= NarrowByteWidth) {
15597 ? std::optional<ByteProvider<SDValue>>(
15602 if (NarrowByteWidth > Index) {
15606 return std::nullopt;
15611 return std::nullopt;
15614 Depth + 1, StartingIndex);
15620 return std::nullopt;
15621 auto VecIdx = IdxOp->getZExtValue();
15622 auto ScalarSize =
Op.getScalarValueSizeInBits();
15623 if (ScalarSize < 32)
15624 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15626 StartingIndex, Index);
15629 case AMDGPUISD::PERM: {
15631 return std::nullopt;
15635 return std::nullopt;
15638 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15639 if (IdxMask > 0x07 && IdxMask != 0x0c)
15640 return std::nullopt;
15642 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15643 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15645 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15651 return std::nullopt;
15666 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15673 auto MemVT = L->getMemoryVT();
15676 return L->getMemoryVT().getSizeInBits() == 16;
15686 int Low8 = Mask & 0xff;
15687 int Hi8 = (Mask & 0xff00) >> 8;
15689 assert(Low8 < 8 && Hi8 < 8);
15691 bool IsConsecutive = (Hi8 - Low8 == 1);
15696 bool Is16Aligned = !(Low8 % 2);
15698 return IsConsecutive && Is16Aligned;
15706 int Low16 = PermMask & 0xffff;
15707 int Hi16 = (PermMask & 0xffff0000) >> 16;
15717 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15719 if (!OtherOpIs16Bit)
15727 unsigned DWordOffset) {
15732 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15737 if (Src.getValueType().isVector()) {
15738 auto ScalarTySize = Src.getScalarValueSizeInBits();
15739 auto ScalarTy = Src.getValueType().getScalarType();
15740 if (ScalarTySize == 32) {
15744 if (ScalarTySize > 32) {
15747 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15748 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15755 assert(ScalarTySize < 32);
15764 auto NumElements =
TypeSize / ScalarTySize;
15765 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15766 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15767 auto NumElementsIn32 = 32 / ScalarTySize;
15768 auto NumAvailElements = DWordOffset < Trunc32Elements
15770 : NumElements - NormalizedTrunc;
15783 auto ShiftVal = 32 * DWordOffset;
15791 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15796 for (
int i = 0; i < 4; i++) {
15798 std::optional<ByteProvider<SDValue>>
P =
15801 if (!
P ||
P->isConstantZero())
15806 if (PermNodes.
size() != 4)
15809 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15810 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15812 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15813 auto PermOp = PermNodes[i];
15816 int SrcByteAdjust = 4;
15820 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15821 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15823 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15824 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15828 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15829 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15832 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15834 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15837 SDValue Op = *PermNodes[FirstSrc.first].Src;
15839 assert(
Op.getValueSizeInBits() == 32);
15843 int Low16 = PermMask & 0xffff;
15844 int Hi16 = (PermMask & 0xffff0000) >> 16;
15846 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15847 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15850 if (WellFormedLow && WellFormedHi)
15854 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15863 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15864 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15869 assert(
Op.getValueType().isByteSized() &&
15880 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15887 DAGCombinerInfo &DCI)
const {
15888 SelectionDAG &DAG = DCI.DAG;
15892 EVT VT =
N->getValueType(0);
15893 if (VT == MVT::i1) {
15895 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15896 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15898 if (Src !=
RHS.getOperand(0))
15903 if (!CLHS || !CRHS)
15907 static const uint32_t MaxMask = 0x3ff;
15912 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15921 LHS.getOpcode() == AMDGPUISD::PERM &&
15927 Sel |=
LHS.getConstantOperandVal(2);
15929 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15936 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15940 auto usesCombinedOperand = [](SDNode *OrUse) {
15943 !OrUse->getValueType(0).isVector())
15947 for (
auto *VUser : OrUse->users()) {
15948 if (!VUser->getValueType(0).isVector())
15955 if (VUser->getOpcode() == VectorwiseOp)
15961 if (!
any_of(
N->users(), usesCombinedOperand))
15967 if (LHSMask != ~0u && RHSMask != ~0u) {
15970 if (LHSMask > RHSMask) {
15977 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15978 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15981 if (!(LHSUsedLanes & RHSUsedLanes) &&
15984 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15986 LHSMask &= ~RHSUsedLanes;
15987 RHSMask &= ~LHSUsedLanes;
15989 LHSMask |= LHSUsedLanes & 0x04040404;
15991 uint32_t Sel = LHSMask | RHSMask;
15994 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15999 if (LHSMask == ~0u || RHSMask == ~0u) {
16040 return IdentitySrc;
16046 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
16061 if (SrcVT == MVT::i32) {
16066 DCI.AddToWorklist(LowOr.
getNode());
16067 DCI.AddToWorklist(HiBits.getNode());
16078 N->getOperand(0), CRHS))
16086 DAGCombinerInfo &DCI)
const {
16087 if (
SDValue RV = reassociateScalarOps(
N, DCI.DAG))
16094 SelectionDAG &DAG = DCI.DAG;
16096 EVT VT =
N->getValueType(0);
16097 if (CRHS && VT == MVT::i64) {
16099 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
16106 unsigned Opc =
LHS.getOpcode();
16136 LHS->getOperand(0), FNegLHS, FNegRHS);
16145SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
16146 DAGCombinerInfo &DCI)
const {
16147 if (!Subtarget->has16BitInsts() ||
16151 EVT VT =
N->getValueType(0);
16152 if (VT != MVT::i32)
16156 if (Src.getValueType() != MVT::i16)
16159 if (!Src->hasOneUse())
16162 if (
SDValue Ext = performExtendTruncShiftCombine(
N, DCI))
16169 std::optional<ByteProvider<SDValue>> BP0 =
16171 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16175 std::optional<ByteProvider<SDValue>> BP1 =
16177 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16185 SelectionDAG &DAG = DCI.DAG;
16187 uint32_t PermMask = 0x0c0c0c0c;
16190 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16195 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16198 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16206SITargetLowering::performExtendTruncShiftCombine(
SDNode *
N,
16207 DAGCombinerInfo &DCI)
const {
16211 const unsigned Opc =
N->getOpcode();
16214 if (
N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16215 Src.getOpcode() != (IsSigned ?
ISD::SRA :
ISD::SRL) || !Src.hasOneUse() ||
16221 if (!IsSigned && !Src->isDivergent())
16224 SDValue X = Src.getOperand(0).getOperand(0);
16226 if (
X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16227 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16230 SelectionDAG &DAG = DCI.DAG;
16232 const unsigned Width = 16 - Shift->getZExtValue();
16245SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16246 DAGCombinerInfo &DCI)
const {
16252 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16253 VTSign->getVT() == MVT::i8) ||
16254 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16255 VTSign->getVT() == MVT::i16))) {
16256 assert(Subtarget->hasScalarSubwordLoads() &&
16257 "s_buffer_load_{u8, i8} are supported "
16258 "in GFX12 (or newer) architectures.");
16259 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16260 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16261 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16264 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16272 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16273 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16274 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16276 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16277 VTSign->getVT() == MVT::i8) ||
16278 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16279 VTSign->getVT() == MVT::i16)) &&
16288 Src.getOperand(6), Src.getOperand(7)};
16291 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16292 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16293 ? AMDGPUISD::BUFFER_LOAD_BYTE
16294 : AMDGPUISD::BUFFER_LOAD_SHORT;
16295 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16296 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16297 return DCI.DAG.getMergeValues(
16298 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16304 DAGCombinerInfo &DCI)
const {
16305 SelectionDAG &DAG = DCI.DAG;
16312 if (
N->getOperand(0).isUndef())
16319 DAGCombinerInfo &DCI)
const {
16320 EVT VT =
N->getValueType(0);
16331 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16340 unsigned MaxDepth)
const {
16341 EVT VT =
Op.getValueType();
16343 "expected a floating-point value to query canonicality of");
16349 unsigned MaxDepth)
const {
16351 "QueryVT must be a floating-point scalar type");
16352 EVT VT =
Op.getValueType();
16356 unsigned Opcode =
Op.getOpcode();
16361 const auto &
F = CFP->getValueAPF();
16362 if (
F.isNaN() &&
F.isSignaling())
16364 if (!
F.isDenormal())
16396 case AMDGPUISD::FMUL_LEGACY:
16397 case AMDGPUISD::FMAD_FTZ:
16398 case AMDGPUISD::RCP:
16399 case AMDGPUISD::RSQ:
16400 case AMDGPUISD::RSQ_CLAMP:
16401 case AMDGPUISD::RCP_LEGACY:
16402 case AMDGPUISD::RCP_IFLAG:
16403 case AMDGPUISD::LOG:
16404 case AMDGPUISD::EXP:
16405 case AMDGPUISD::DIV_SCALE:
16406 case AMDGPUISD::DIV_FMAS:
16407 case AMDGPUISD::DIV_FIXUP:
16408 case AMDGPUISD::FRACT:
16409 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16410 case AMDGPUISD::CVT_F32_UBYTE0:
16411 case AMDGPUISD::CVT_F32_UBYTE1:
16412 case AMDGPUISD::CVT_F32_UBYTE2:
16413 case AMDGPUISD::CVT_F32_UBYTE3:
16414 case AMDGPUISD::FP_TO_FP16:
16415 case AMDGPUISD::SIN_HW:
16416 case AMDGPUISD::COS_HW:
16428 if (
Op.getValueType() == MVT::i32) {
16434 if (RHS->getZExtValue() == 0xffff0000) {
16445 return Op.getValueType().getScalarType() != MVT::f16;
16455 case AMDGPUISD::CLAMP:
16456 case AMDGPUISD::FMED3:
16457 case AMDGPUISD::FMAX3:
16458 case AMDGPUISD::FMIN3:
16459 case AMDGPUISD::FMAXIMUM3:
16460 case AMDGPUISD::FMINIMUM3: {
16466 if (Subtarget->supportsMinMaxDenormModes() ||
16476 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16491 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16525 if (
Op.getValueType() == MVT::i16) {
16537 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16539 switch (IntrinsicID) {
16540 case Intrinsic::amdgcn_cvt_pkrtz:
16541 case Intrinsic::amdgcn_cubeid:
16542 case Intrinsic::amdgcn_frexp_mant:
16543 case Intrinsic::amdgcn_fdot2:
16544 case Intrinsic::amdgcn_rcp:
16545 case Intrinsic::amdgcn_rsq:
16546 case Intrinsic::amdgcn_rsq_clamp:
16547 case Intrinsic::amdgcn_rcp_legacy:
16548 case Intrinsic::amdgcn_rsq_legacy:
16549 case Intrinsic::amdgcn_trig_preop:
16550 case Intrinsic::amdgcn_tanh:
16551 case Intrinsic::amdgcn_log:
16552 case Intrinsic::amdgcn_exp2:
16553 case Intrinsic::amdgcn_sqrt:
16571 unsigned MaxDepth)
const {
16574 unsigned Opcode =
MI->getOpcode();
16576 if (Opcode == AMDGPU::G_FCANONICALIZE)
16579 std::optional<FPValueAndVReg> FCR;
16582 if (FCR->Value.isSignaling())
16584 if (!FCR->Value.isDenormal())
16595 case AMDGPU::G_FADD:
16596 case AMDGPU::G_FSUB:
16597 case AMDGPU::G_FMUL:
16598 case AMDGPU::G_FCEIL:
16599 case AMDGPU::G_FFLOOR:
16600 case AMDGPU::G_FRINT:
16601 case AMDGPU::G_FNEARBYINT:
16602 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16603 case AMDGPU::G_INTRINSIC_TRUNC:
16604 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16605 case AMDGPU::G_FMA:
16606 case AMDGPU::G_FMAD:
16607 case AMDGPU::G_FSQRT:
16608 case AMDGPU::G_FDIV:
16609 case AMDGPU::G_FREM:
16610 case AMDGPU::G_FPOW:
16611 case AMDGPU::G_FPEXT:
16612 case AMDGPU::G_FLOG:
16613 case AMDGPU::G_FLOG2:
16614 case AMDGPU::G_FLOG10:
16615 case AMDGPU::G_FPTRUNC:
16616 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16617 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16618 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16619 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16620 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16622 case AMDGPU::G_FNEG:
16623 case AMDGPU::G_FABS:
16624 case AMDGPU::G_FCOPYSIGN:
16626 case AMDGPU::G_FMINNUM:
16627 case AMDGPU::G_FMAXNUM:
16628 case AMDGPU::G_FMINNUM_IEEE:
16629 case AMDGPU::G_FMAXNUM_IEEE:
16630 case AMDGPU::G_FMINIMUM:
16631 case AMDGPU::G_FMAXIMUM:
16632 case AMDGPU::G_FMINIMUMNUM:
16633 case AMDGPU::G_FMAXIMUMNUM: {
16634 if (Subtarget->supportsMinMaxDenormModes() ||
16641 case AMDGPU::G_BUILD_VECTOR:
16646 case AMDGPU::G_INTRINSIC:
16647 case AMDGPU::G_INTRINSIC_CONVERGENT:
16649 case Intrinsic::amdgcn_fmul_legacy:
16650 case Intrinsic::amdgcn_fmad_ftz:
16651 case Intrinsic::amdgcn_sqrt:
16652 case Intrinsic::amdgcn_fmed3:
16653 case Intrinsic::amdgcn_sin:
16654 case Intrinsic::amdgcn_cos:
16655 case Intrinsic::amdgcn_log:
16656 case Intrinsic::amdgcn_exp2:
16657 case Intrinsic::amdgcn_log_clamp:
16658 case Intrinsic::amdgcn_rcp:
16659 case Intrinsic::amdgcn_rcp_legacy:
16660 case Intrinsic::amdgcn_rsq:
16661 case Intrinsic::amdgcn_rsq_clamp:
16662 case Intrinsic::amdgcn_rsq_legacy:
16663 case Intrinsic::amdgcn_div_scale:
16664 case Intrinsic::amdgcn_div_fmas:
16665 case Intrinsic::amdgcn_div_fixup:
16666 case Intrinsic::amdgcn_fract:
16667 case Intrinsic::amdgcn_cvt_pkrtz:
16668 case Intrinsic::amdgcn_cubeid:
16669 case Intrinsic::amdgcn_cubema:
16670 case Intrinsic::amdgcn_cubesc:
16671 case Intrinsic::amdgcn_cubetc:
16672 case Intrinsic::amdgcn_frexp_mant:
16673 case Intrinsic::amdgcn_fdot2:
16674 case Intrinsic::amdgcn_trig_preop:
16675 case Intrinsic::amdgcn_tanh:
16694 if (
C.isDenormal()) {
16707 if (
C.isSignaling()) {
16722SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16723 DAGCombinerInfo &DCI)
const {
16724 SelectionDAG &DAG = DCI.DAG;
16726 EVT VT =
N->getValueType(0);
16735 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16750 EVT EltVT =
Lo.getValueType();
16759 for (
unsigned I = 0;
I != 2; ++
I) {
16763 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16764 }
else if (
Op.isUndef()) {
16799 return AMDGPUISD::FMAX3;
16801 return AMDGPUISD::FMAXIMUM3;
16803 return AMDGPUISD::SMAX3;
16805 return AMDGPUISD::UMAX3;
16809 return AMDGPUISD::FMIN3;
16811 return AMDGPUISD::FMINIMUM3;
16813 return AMDGPUISD::SMIN3;
16815 return AMDGPUISD::UMIN3;
16836 if (!MinK || !MaxK)
16848 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16849 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16850 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16874 bool IsKnownNoNaNs)
const {
16910 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16916 if (
Info->getMode().DX10Clamp) {
16925 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16957 case AMDGPUISD::FMIN_LEGACY:
16958 case AMDGPUISD::FMAX_LEGACY:
16959 return (VT == MVT::f32) || (VT == MVT::f16 &&
Subtarget.hasMin3Max3_16()) ||
16960 (VT == MVT::v2f16 &&
Subtarget.hasMin3Max3PKF16());
16963 return (VT == MVT::f32 &&
Subtarget.hasMinimum3Maximum3F32()) ||
16964 (VT == MVT::f16 &&
Subtarget.hasMinimum3Maximum3F16()) ||
16965 (VT == MVT::v2f16 &&
Subtarget.hasMinimum3Maximum3PKF16());
16970 return (VT == MVT::i32) || (VT == MVT::i16 &&
Subtarget.hasMin3Max3_16());
16979 DAGCombinerInfo &DCI)
const {
16980 SelectionDAG &DAG = DCI.DAG;
16991 auto IsTreeWithCombinableChildren = [
Opc](
SDValue Op) {
16992 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16993 Op.getOperand(0).hasOneUse()) ||
16995 Op.getOperand(1).hasOneUse());
17000 bool HasCombinableTreeChild =
17001 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
17002 IsTreeWithCombinableChildren(Op1));
17011 if (CanTreeCombineApply && !HasCombinableTreeChild) {
17049 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
17057 if (
SDValue Med3 = performIntMed3ImmCombine(
17062 if (
SDValue Med3 = performIntMed3ImmCombine(
17068 if (
SDValue Med3 = performIntMed3ImmCombine(
17073 if (
SDValue Med3 = performIntMed3ImmCombine(
17086 (
Opc == AMDGPUISD::FMIN_LEGACY &&
17087 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17088 (VT == MVT::f32 || VT == MVT::f64 ||
17089 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17090 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17091 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17092 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17094 if (
SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
17095 N->getFlags().hasNoNaNs()))
17102 const SDNodeFlags
Flags =
N->getFlags();
17104 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17108 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
17118 return (CA->isPosZero() && CB->isOne()) ||
17119 (CA->isOne() && CB->isPosZero());
17128 DAGCombinerInfo &DCI)
const {
17129 EVT VT =
N->getValueType(0);
17133 SelectionDAG &DAG = DCI.DAG;
17144 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17148 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
17152 if (
Info->getMode().DX10Clamp) {
17165 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17172 DAGCombinerInfo &DCI)
const {
17175 if (
Src0.isUndef() &&
Src1.isUndef())
17176 return DCI.DAG.getUNDEF(
N->getValueType(0));
17183SITargetLowering::performExponentOnlyScaleCombine(
SDNode *
N,
17184 DAGCombinerInfo &DCI)
const {
17185 std::optional<unsigned> ScaleArgIdx =
17191 unsigned OpIdx = *ScaleArgIdx + 1;
17192 SelectionDAG &DAG = DCI.DAG;
17199 Ops[OpIdx] = DemandedScale;
17213 bool IsDivergentIdx,
17218 unsigned VecSize = EltSize * NumElem;
17221 if (VecSize <= 64 && EltSize < 32)
17230 if (IsDivergentIdx)
17234 unsigned NumInsts = NumElem +
17235 ((EltSize + 31) / 32) * NumElem ;
17239 if (Subtarget->useVGPRIndexMode())
17240 return NumInsts <= 16;
17244 if (Subtarget->hasMovrel())
17245 return NumInsts <= 15;
17251 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17262 EltSize, NumElem, Idx->isDivergent(),
getSubtarget());
17266SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17267 DAGCombinerInfo &DCI)
const {
17273 EVT ResVT =
N->getValueType(0);
17297 if (!
C ||
C->getZExtValue() != 0x1f)
17313 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17341 DCI.AddToWorklist(Elt0.
getNode());
17342 DCI.AddToWorklist(Elt1.
getNode());
17373 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17374 uint64_t KImmValue = KImm->getZExtValue();
17376 (KImmValue >> (32 *
Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17379 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17381 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17382 return DAG.
getConstant((KFPImmValue >> (32 *
Idx->getZExtValue())) &
17388 if (!DCI.isBeforeLegalize())
17395 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17398 unsigned BitIndex =
Idx->getZExtValue() * VecEltSize;
17399 unsigned EltIdx = BitIndex / 32;
17400 unsigned LeftoverBitIdx = BitIndex % 32;
17404 DCI.AddToWorklist(Cast.
getNode());
17408 DCI.AddToWorklist(Elt.
getNode());
17411 DCI.AddToWorklist(Srl.
getNode());
17415 DCI.AddToWorklist(Trunc.
getNode());
17417 if (VecEltVT == ResVT) {
17429SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17430 DAGCombinerInfo &DCI)
const {
17444 SelectionDAG &DAG = DCI.DAG;
17447 EVT IdxVT =
Idx.getValueType();
17464 Src.getOperand(0).getValueType() == MVT::f16) {
17465 return Src.getOperand(0);
17469 APFloat Val = CFP->getValueAPF();
17470 bool LosesInfo =
true;
17480 DAGCombinerInfo &DCI)
const {
17481 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17482 "combine only useful on gfx8");
17484 SDValue TruncSrc =
N->getOperand(0);
17485 EVT VT =
N->getValueType(0);
17486 if (VT != MVT::f16)
17489 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17493 SelectionDAG &DAG = DCI.DAG;
17524unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17526 const SDNode *N1)
const {
17531 if (((VT == MVT::f32 &&
17533 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17550 EVT VT =
N->getValueType(0);
17551 if (VT != MVT::i32 && VT != MVT::i64)
17557 unsigned Opc =
N->getOpcode();
17612 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17631 DAGCombinerInfo &DCI)
const {
17634 SelectionDAG &DAG = DCI.DAG;
17635 EVT VT =
N->getValueType(0);
17645 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17649 if (NumBits <= 32 || NumBits > 64)
17660 if (!Subtarget->hasFullRate64Ops()) {
17661 unsigned NumUsers = 0;
17662 for (SDNode *User :
LHS->
users()) {
17665 if (!
User->isAnyAdd())
17689 bool MulSignedLo =
false;
17690 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17699 if (VT != MVT::i64) {
17722 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17724 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17725 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17727 if (!MulLHSUnsigned32) {
17734 if (!MulRHSUnsigned32) {
17745 if (VT != MVT::i64)
17751SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17752 DAGCombinerInfo &DCI)
const {
17762 SelectionDAG &DAG = DCI.DAG;
17777 unsigned Opcode =
N->getOpcode();
17781 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17792static std::optional<ByteProvider<SDValue>>
17795 if (!Byte0 || Byte0->isConstantZero()) {
17796 return std::nullopt;
17799 if (Byte1 && !Byte1->isConstantZero()) {
17800 return std::nullopt;
17806 unsigned FirstCs =
First & 0x0c0c0c0c;
17807 unsigned SecondCs = Second & 0x0c0c0c0c;
17808 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17809 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17811 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17812 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17813 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17814 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17816 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17830 assert(Src0.Src.has_value() && Src1.Src.has_value());
17833 Src0s.
push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17834 Src0.SrcOffset / 4});
17835 Src1s.
push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17836 Src1.SrcOffset / 4});
17840 for (
int BPI = 0; BPI < 2; BPI++) {
17843 BPP = {Src1, Src0};
17845 unsigned ZeroMask = 0x0c0c0c0c;
17846 unsigned FMask = 0xFF << (8 * (3 - Step));
17848 unsigned FirstMask =
17849 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17850 unsigned SecondMask =
17851 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17855 int FirstGroup = -1;
17856 for (
int I = 0;
I < 2;
I++) {
17858 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17859 return IterElt.SrcOp == *BPP.first.Src &&
17860 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17864 if (Match != Srcs.
end()) {
17865 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17870 if (FirstGroup != -1) {
17872 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17873 return IterElt.SrcOp == *BPP.second.Src &&
17874 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17877 if (Match != Srcs.
end()) {
17878 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17880 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17888 unsigned ZeroMask = 0x0c0c0c0c;
17889 unsigned FMask = 0xFF << (8 * (3 - Step));
17893 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17894 Src0.SrcOffset / 4});
17897 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17898 Src1.SrcOffset / 4});
17906 if (Srcs.
size() == 1) {
17907 auto *Elt = Srcs.
begin();
17911 if (Elt->PermMask == 0x3020100)
17914 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17918 auto *FirstElt = Srcs.
begin();
17919 auto *SecondElt = std::next(FirstElt);
17926 auto FirstMask = FirstElt->PermMask;
17927 auto SecondMask = SecondElt->PermMask;
17929 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17930 unsigned FirstPlusFour = FirstMask | 0x04040404;
17933 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17945 FirstElt = std::next(SecondElt);
17946 if (FirstElt == Srcs.
end())
17949 SecondElt = std::next(FirstElt);
17952 if (SecondElt == Srcs.
end()) {
17957 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17958 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17964 return Perms.
size() == 2
17970 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17971 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17972 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17973 EntryMask += ZeroMask;
17978 auto Opcode =
Op.getOpcode();
17980 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17981 Opcode == AMDGPUISD::MUL_I24);
17984static std::optional<bool>
17995 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17998 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
18000 assert(!(S0IsUnsigned && S0IsSigned));
18001 assert(!(S1IsUnsigned && S1IsSigned));
18009 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
18015 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
18016 return std::nullopt;
18028 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
18029 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
18034 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
18040 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
18041 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
18042 return std::nullopt;
18048 DAGCombinerInfo &DCI)
const {
18049 SelectionDAG &DAG = DCI.DAG;
18050 EVT VT =
N->getValueType(0);
18056 if (Subtarget->hasMad64_32()) {
18062 if (
SDValue V = reassociateScalarOps(
N, DAG)) {
18066 if (VT == MVT::i64) {
18074 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
18076 std::optional<bool> IsSigned;
18082 int ChainLength = 0;
18083 for (
int I = 0;
I < 4;
I++) {
18095 TempNode->getOperand(MulIdx), *Src0, *Src1,
18096 TempNode->getOperand(MulIdx)->getOperand(0),
18097 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18101 IsSigned = *IterIsSigned;
18102 if (*IterIsSigned != *IsSigned)
18105 auto AddIdx = 1 - MulIdx;
18108 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
18109 Src2s.
push_back(TempNode->getOperand(AddIdx));
18119 TempNode->getOperand(AddIdx), *Src0, *Src1,
18120 TempNode->getOperand(AddIdx)->getOperand(0),
18121 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18125 if (*IterIsSigned != *IsSigned)
18129 ChainLength =
I + 2;
18133 TempNode = TempNode->getOperand(AddIdx);
18135 ChainLength =
I + 1;
18137 if (TempNode.getOpcode() !=
ISD::ADD)
18139 LHS = TempNode->getOperand(0);
18140 RHS = TempNode->getOperand(1);
18143 if (ChainLength < 2)
18149 if (ChainLength < 4) {
18159 bool UseOriginalSrc =
false;
18160 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
18161 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
18162 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
18163 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
18164 SmallVector<unsigned, 4> SrcBytes;
18165 auto Src0Mask = Src0s.
begin()->PermMask;
18166 SrcBytes.
push_back(Src0Mask & 0xFF000000);
18167 bool UniqueEntries =
true;
18168 for (
auto I = 1;
I < 4;
I++) {
18169 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
18172 UniqueEntries =
false;
18178 if (UniqueEntries) {
18179 UseOriginalSrc =
true;
18181 auto *FirstElt = Src0s.
begin();
18185 auto *SecondElt = Src1s.
begin();
18187 SecondElt->DWordOffset);
18196 if (!UseOriginalSrc) {
18203 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18206 : Intrinsic::amdgcn_udot4,
18216 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18221 unsigned Opc =
LHS.getOpcode();
18233 auto Cond =
RHS.getOperand(0);
18238 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18255 DAGCombinerInfo &DCI)
const {
18256 SelectionDAG &DAG = DCI.DAG;
18258 EVT VT =
N->getValueType(0);
18271 SDNodeFlags ShlFlags = N1->
getFlags();
18275 SDNodeFlags NewShlFlags =
18280 DCI.AddToWorklist(Inner.
getNode());
18287 if (Subtarget->hasMad64_32()) {
18297 if (VT == MVT::i64) {
18311 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18312 Y->isDivergent() !=
Z->isDivergent()) {
18321 if (
Y->isDivergent())
18324 SDNodeFlags ReassocFlags =
18327 DCI.AddToWorklist(UniformInner.
getNode());
18339 DAGCombinerInfo &DCI)
const {
18340 SelectionDAG &DAG = DCI.DAG;
18341 EVT VT =
N->getValueType(0);
18343 if (VT == MVT::i64) {
18348 if (VT != MVT::i32)
18357 unsigned Opc =
RHS.getOpcode();
18364 auto Cond =
RHS.getOperand(0);
18369 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18395 ConstantSDNode *ShiftAmt =
18397 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18408 DAGCombinerInfo &DCI)
const {
18412 SelectionDAG &DAG = DCI.DAG;
18413 EVT VT =
N->getValueType(0);
18425 if (
A ==
LHS.getOperand(1)) {
18426 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18427 if (FusedOp != 0) {
18429 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18437 if (
A ==
RHS.getOperand(1)) {
18438 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18439 if (FusedOp != 0) {
18441 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18450 DAGCombinerInfo &DCI)
const {
18454 SelectionDAG &DAG = DCI.DAG;
18456 EVT VT =
N->getValueType(0);
18469 if (
A ==
LHS.getOperand(1)) {
18470 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18471 if (FusedOp != 0) {
18475 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18484 if (
A ==
RHS.getOperand(1)) {
18485 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18486 if (FusedOp != 0) {
18488 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18497 DAGCombinerInfo &DCI)
const {
18498 SelectionDAG &DAG = DCI.DAG;
18500 EVT VT =
N->getValueType(0);
18502 if (VT != MVT::f16 && VT != MVT::bf16)
18508 SDNodeFlags
Flags =
N->getFlags();
18509 SDNodeFlags RHSFlags =
RHS->getFlags();
18515 bool IsNegative =
false;
18516 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18525 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18526 }
else if (VT == MVT::f16) {
18535 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18552 DAGCombinerInfo &DCI)
const {
18553 SelectionDAG &DAG = DCI.DAG;
18554 EVT VT =
N->getValueType(0);
18558 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18559 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18574 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18579 const ConstantFPSDNode *FalseNode =
18589 if (ScalarVT == MVT::f32 &&
18595 if (TrueNodeExpVal == INT_MIN)
18598 if (FalseNodeExpVal == INT_MIN)
18618 DAGCombinerInfo &DCI)
const {
18619 SelectionDAG &DAG = DCI.DAG;
18620 EVT VT =
N->getValueType(0);
18623 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18651 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18652 FMA->getFlags().hasApproximateFuncs();
18653 if (!AllowInaccuracy) {
18656 if (Subtarget->dot2UnconditionalFlush()) {
18668 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18704 if (Vec1 == Vec2 || Vec3 == Vec4)
18710 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18711 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18754 EVT VT =
LHS.getValueType();
18755 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18802 const std::optional<bool> KnownEq =
18843 const std::optional<bool> KnownUge =
18885 const std::optional<bool> KnownUle =
18908 DAGCombinerInfo &DCI)
const {
18909 SelectionDAG &DAG = DCI.DAG;
18914 EVT VT =
LHS.getValueType();
18943 return LHS.getOperand(0);
18957 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18958 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18963 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18966 return LHS.getOperand(0);
18972 if (VT == MVT::i64) {
18975 const KnownBits LHSKnownLo32 = LHSKnown.
trunc(32);
18976 const KnownBits RHSKnownLo32 = RHSKnown.
trunc(32);
19003 const std::optional<bool> KnownEq =
19011 const std::optional<bool> KnownEq =
19022 const std::optional<bool> KnownUge =
19042 const std::optional<bool> KnownUle =
19066 const KnownBits LHSKnownHi32 = LHSKnown.
extractBits(32, 32);
19067 const KnownBits RHSKnownHi32 = RHSKnown.
extractBits(32, 32);
19068 const std::optional<bool> KnownEq =
19071 if (KnownEq ==
true) {
19077 return DAG.
getSetCC(SL,
N->getValueType(0), LHSLo, RHSLo, NewCC);
19109 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19114 {Op0Hi, Op1Hi, CarryInHi});
19124 DCI.CombineTo(
LHS.getNode(), Result);
19128 if (VT != MVT::f32 && VT != MVT::f64 &&
19129 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19144 const unsigned IsInfMask =
19146 const unsigned IsFiniteMask =
19151 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
19156 if (VT == MVT::f64) {
19167SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
19168 DAGCombinerInfo &DCI)
const {
19169 SelectionDAG &DAG = DCI.DAG;
19171 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19190 unsigned ShiftOffset = 8 *
Offset;
19192 ShiftOffset -=
C->getZExtValue();
19194 ShiftOffset +=
C->getZExtValue();
19196 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19197 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19198 MVT::f32, Shifted);
19209 DCI.AddToWorklist(
N);
19216 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
19222 DAGCombinerInfo &DCI)
const {
19231 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19232 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
19237 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
19239 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
19249 FrexpInput =
V.getOperand(0);
19259SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
19260 DAGCombinerInfo &DCI)
const {
19262 if (Subtarget->hasFractBug())
19274 bool CondSelectsZero;
19282 CondSelectsZero =
true;
19283 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19286 CondSelectsZero =
false;
19298 bool IsNonFiniteTest =
false;
19310 bool LHSMatchesFrexp =
19311 (CondLHS == FrexpInput) ||
19312 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19314 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19322 SelectionDAG &DAG = DCI.DAG;
19323 if (LHSMatchesFrexp &&
19325 IsNonFiniteTest = CondSelectsZero;
19327 IsNonFiniteTest = CondSelectsZero;
19334 IsNonFiniteTest = CondSelectsZero;
19341 IsNonFiniteTest = !CondSelectsZero;
19347 SelectionDAG &DAG = DCI.DAG;
19348 if (LHSMatchesFrexp &&
19350 IsNonFiniteTest = !CondSelectsZero;
19352 IsNonFiniteTest = !CondSelectsZero;
19356 if (!IsNonFiniteTest)
19364 DAGCombinerInfo &DCI)
const {
19385 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19386 bool isInteger =
LHS.getValueType().isInteger();
19389 if (!isFloatingPoint && !isInteger)
19394 bool isNonEquality =
19396 if (!isEquality && !isNonEquality)
19413 if (isFloatingPoint) {
19415 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19418 const std::optional<int64_t> Val =
19427 if (!(isEquality && TrueVal == ConstVal) &&
19428 !(isNonEquality && FalseVal == ConstVal))
19432 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19433 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19440 SelectLHS, SelectRHS);
19445 switch (
N->getOpcode()) {
19467 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19477 switch (
N->getOpcode()) {
19479 return performAddCombine(
N, DCI);
19481 return performPtrAddCombine(
N, DCI);
19483 return performSubCombine(
N, DCI);
19485 return performFAddCombine(
N, DCI);
19487 return performFSubCombine(
N, DCI);
19489 return performFDivCombine(
N, DCI);
19491 return performFMulCombine(
N, DCI);
19493 return performSetCCCombine(
N, DCI);
19495 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19497 if (
auto Res = performSelectCombine(
N, DCI))
19512 case AMDGPUISD::FMIN_LEGACY:
19513 case AMDGPUISD::FMAX_LEGACY:
19514 return performMinMaxCombine(
N, DCI);
19516 return performFMACombine(
N, DCI);
19518 return performAndCombine(
N, DCI);
19520 return performOrCombine(
N, DCI);
19523 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19524 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19530 return performXorCombine(
N, DCI);
19533 return performZeroOrAnyExtendCombine(
N, DCI);
19535 return performExtendTruncShiftCombine(
N, DCI);
19537 return performSignExtendInRegCombine(
N, DCI);
19538 case AMDGPUISD::FP_CLASS:
19539 return performClassCombine(
N, DCI);
19541 return performFCanonicalizeCombine(
N, DCI);
19542 case AMDGPUISD::RCP:
19543 return performRcpCombine(
N, DCI);
19545 case AMDGPUISD::FRACT:
19546 case AMDGPUISD::RSQ:
19547 case AMDGPUISD::RCP_LEGACY:
19548 case AMDGPUISD::RCP_IFLAG:
19549 case AMDGPUISD::RSQ_CLAMP: {
19558 return performUCharToFloatCombine(
N, DCI);
19560 return performFCopySignCombine(
N, DCI);
19561 case AMDGPUISD::CVT_F32_UBYTE0:
19562 case AMDGPUISD::CVT_F32_UBYTE1:
19563 case AMDGPUISD::CVT_F32_UBYTE2:
19564 case AMDGPUISD::CVT_F32_UBYTE3:
19565 return performCvtF32UByteNCombine(
N, DCI);
19566 case AMDGPUISD::FMED3:
19567 return performFMed3Combine(
N, DCI);
19568 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19569 return performCvtPkRTZCombine(
N, DCI);
19571 if (
SDValue Res = performExponentOnlyScaleCombine(
N, DCI))
19574 case AMDGPUISD::CLAMP:
19575 return performClampCombine(
N, DCI);
19578 EVT VT =
N->getValueType(0);
19581 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19584 EVT EltVT = Src.getValueType();
19585 if (EltVT != MVT::i16)
19595 return performExtractVectorEltCombine(
N, DCI);
19597 return performInsertVectorEltCombine(
N, DCI);
19599 return performFPRoundCombine(
N, DCI);
19608 return performMemSDNodeCombine(MemNode, DCI);
19639 unsigned Opcode =
Node->getMachineOpcode();
19642 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19643 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19646 SDNode *
Users[5] = {
nullptr};
19648 unsigned DmaskIdx =
19649 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19650 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19651 unsigned NewDmask = 0;
19652 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19653 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19654 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19655 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19656 unsigned TFCLane = 0;
19657 bool HasChain =
Node->getNumValues() > 1;
19659 if (OldDmask == 0) {
19667 TFCLane = OldBitsSet;
19671 for (SDUse &Use :
Node->uses()) {
19674 if (
Use.getResNo() != 0)
19677 SDNode *
User =
Use.getUser();
19680 if (!
User->isMachineOpcode() ||
19681 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19693 if (UsesTFC && Lane == TFCLane) {
19698 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19700 Dmask &= ~(1 << Comp);
19708 NewDmask |= 1 << Comp;
19713 bool NoChannels = !NewDmask;
19720 if (OldBitsSet == 1)
19726 if (NewDmask == OldDmask)
19735 unsigned NewChannels = BitsSet + UsesTFC;
19739 assert(NewOpcode != -1 &&
19740 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19741 "failed to find equivalent MIMG op");
19749 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19751 MVT ResultVT = NewChannels == 1
19754 : NewChannels == 5 ? 8
19756 SDVTList NewVTList =
19759 MachineSDNode *NewNode =
19768 if (NewChannels == 1) {
19778 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19783 if (i || !NoChannels)
19788 if (NewUser != User) {
19798 Idx = AMDGPU::sub1;
19801 Idx = AMDGPU::sub2;
19804 Idx = AMDGPU::sub3;
19807 Idx = AMDGPU::sub4;
19818 Op =
Op.getOperand(0);
19839 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19843 Node->getOperand(0), SL, VReg, SrcVal,
19849 return ToResultReg.
getNode();
19854 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19856 Ops.push_back(
Node->getOperand(i));
19862 Node->getOperand(i).getValueType(),
19863 Node->getOperand(i)),
19875 unsigned Opcode =
Node->getMachineOpcode();
19877 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19878 !
TII->isGather4(Opcode) &&
19880 return adjustWritemask(
Node, DAG);
19883 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19889 case AMDGPU::V_DIV_SCALE_F32_e64:
19890 case AMDGPU::V_DIV_SCALE_F64_e64: {
19898 if ((Src0.isMachineOpcode() &&
19899 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19900 (Src0 == Src1 || Src0 == Src2))
19903 MVT VT = Src0.getValueType().getSimpleVT();
19915 if (Src0.isMachineOpcode() &&
19916 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19917 if (Src1.isMachineOpcode() &&
19918 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19920 else if (Src2.isMachineOpcode() &&
19921 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19924 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19956 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19957 unsigned InitIdx = 0;
19959 if (
TII->isImage(
MI)) {
19967 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19968 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19969 unsigned D16Val = D16 ? D16->getImm() : 0;
19971 if (!TFEVal && !LWEVal)
19982 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19984 unsigned dmask = MO_Dmask->
getImm();
19989 bool Packed = !Subtarget->hasUnpackedD16VMem();
19991 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19998 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19999 if (DstSize < InitIdx)
20003 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
20011 Register PrevDst =
MRI.cloneVirtualRegister(
MI.getOperand(DstIdx).getReg());
20012 unsigned NewDst = 0;
20017 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
20018 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
20021 for (; SizeLeft; SizeLeft--, CurrIdx++) {
20022 NewDst =
MRI.createVirtualRegister(
TII->getOpRegClass(
MI, DstIdx));
20024 Register SubReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
20042 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
20054 if (
TII->isVOP3(
MI.getOpcode())) {
20056 TII->legalizeOperandsVOP3(
MRI,
MI);
20058 if (
TII->isMAI(
MI)) {
20063 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
20064 AMDGPU::OpName::scale_src0);
20065 if (Src0Idx != -1) {
20066 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
20067 AMDGPU::OpName::scale_src1);
20068 if (
TII->usesConstantBus(
MRI,
MI, Src0Idx) &&
20069 TII->usesConstantBus(
MRI,
MI, Src1Idx))
20070 TII->legalizeOpWithMove(
MI, Src1Idx);
20077 if (
TII->isImage(
MI))
20078 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
20120 uint64_t RsrcDword2And3)
const {
20150std::pair<unsigned, const TargetRegisterClass *>
20157 if (Constraint.
size() == 1) {
20161 if (VT == MVT::Other)
20164 switch (Constraint[0]) {
20171 RC = &AMDGPU::SReg_32RegClass;
20174 RC = &AMDGPU::SGPR_64RegClass;
20179 return std::pair(0U,
nullptr);
20186 return std::pair(0U,
nullptr);
20188 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20189 : &AMDGPU::VGPR_32_Lo256RegClass;
20192 RC = Subtarget->hasVGPRMSBs()
20193 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
20196 return std::pair(0U,
nullptr);
20201 if (!Subtarget->hasMAIInsts())
20205 return std::pair(0U,
nullptr);
20207 RC = &AMDGPU::AGPR_32RegClass;
20212 return std::pair(0U,
nullptr);
20217 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
20221 RC = &AMDGPU::AV_32RegClass;
20224 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
20226 return std::pair(0U,
nullptr);
20235 return std::pair(0U, RC);
20238 if (Kind !=
'\0') {
20240 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20241 }
else if (Kind ==
's') {
20242 RC = &AMDGPU::SGPR_32RegClass;
20243 }
else if (Kind ==
'a') {
20244 RC = &AMDGPU::AGPR_32RegClass;
20250 return std::pair(0U,
nullptr);
20256 return std::pair(0U,
nullptr);
20260 RC =
TRI->getVGPRClassForBitWidth(Width);
20262 RC =
TRI->getSGPRClassForBitWidth(Width);
20264 RC =
TRI->getAGPRClassForBitWidth(Width);
20266 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20271 return std::pair(0U,
nullptr);
20273 return std::pair(Reg, RC);
20282 return std::pair(0U,
nullptr);
20283 if (RC && Idx < RC->getNumRegs())
20285 return std::pair(0U,
nullptr);
20291 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20292 if (!Subtarget->useRealTrue16Insts() &&
20293 TRI->getRegSizeInBits(*Ret.second) == 16)
20294 return std::pair(0U,
nullptr);
20301 if (Constraint.
size() == 1) {
20302 switch (Constraint[0]) {
20312 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20320 if (Constraint.
size() == 1) {
20321 switch (Constraint[0]) {
20329 }
else if (Constraint.
size() == 2) {
20330 if (Constraint ==
"VA")
20348 std::vector<SDValue> &
Ops,
20363 unsigned Size =
Op.getScalarValueSizeInBits();
20367 if (
Size == 16 && !Subtarget->has16BitInsts())
20371 Val =
C->getSExtValue();
20375 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20379 if (
Size != 16 ||
Op.getNumOperands() != 2)
20381 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20384 Val =
C->getSExtValue();
20388 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20397 uint64_t Val)
const {
20398 if (Constraint.
size() == 1) {
20399 switch (Constraint[0]) {
20414 }
else if (Constraint.
size() == 2) {
20415 if (Constraint ==
"DA") {
20416 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20417 int64_t LoBits =
static_cast<int32_t
>(Val);
20421 if (Constraint ==
"DB") {
20429 unsigned MaxSize)
const {
20430 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20431 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20433 MVT VT =
Op.getSimpleValueType();
20458 switch (UnalignedClassID) {
20459 case AMDGPU::VReg_64RegClassID:
20460 return AMDGPU::VReg_64_Align2RegClassID;
20461 case AMDGPU::VReg_96RegClassID:
20462 return AMDGPU::VReg_96_Align2RegClassID;
20463 case AMDGPU::VReg_128RegClassID:
20464 return AMDGPU::VReg_128_Align2RegClassID;
20465 case AMDGPU::VReg_160RegClassID:
20466 return AMDGPU::VReg_160_Align2RegClassID;
20467 case AMDGPU::VReg_192RegClassID:
20468 return AMDGPU::VReg_192_Align2RegClassID;
20469 case AMDGPU::VReg_224RegClassID:
20470 return AMDGPU::VReg_224_Align2RegClassID;
20471 case AMDGPU::VReg_256RegClassID:
20472 return AMDGPU::VReg_256_Align2RegClassID;
20473 case AMDGPU::VReg_288RegClassID:
20474 return AMDGPU::VReg_288_Align2RegClassID;
20475 case AMDGPU::VReg_320RegClassID:
20476 return AMDGPU::VReg_320_Align2RegClassID;
20477 case AMDGPU::VReg_352RegClassID:
20478 return AMDGPU::VReg_352_Align2RegClassID;
20479 case AMDGPU::VReg_384RegClassID:
20480 return AMDGPU::VReg_384_Align2RegClassID;
20481 case AMDGPU::VReg_512RegClassID:
20482 return AMDGPU::VReg_512_Align2RegClassID;
20483 case AMDGPU::VReg_1024RegClassID:
20484 return AMDGPU::VReg_1024_Align2RegClassID;
20485 case AMDGPU::AReg_64RegClassID:
20486 return AMDGPU::AReg_64_Align2RegClassID;
20487 case AMDGPU::AReg_96RegClassID:
20488 return AMDGPU::AReg_96_Align2RegClassID;
20489 case AMDGPU::AReg_128RegClassID:
20490 return AMDGPU::AReg_128_Align2RegClassID;
20491 case AMDGPU::AReg_160RegClassID:
20492 return AMDGPU::AReg_160_Align2RegClassID;
20493 case AMDGPU::AReg_192RegClassID:
20494 return AMDGPU::AReg_192_Align2RegClassID;
20495 case AMDGPU::AReg_256RegClassID:
20496 return AMDGPU::AReg_256_Align2RegClassID;
20497 case AMDGPU::AReg_512RegClassID:
20498 return AMDGPU::AReg_512_Align2RegClassID;
20499 case AMDGPU::AReg_1024RegClassID:
20500 return AMDGPU::AReg_1024_Align2RegClassID;
20516 if (Info->isEntryFunction()) {
20523 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20525 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20526 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20527 &AMDGPU::SGPR_64RegClass);
20528 Info->setSGPRForEXECCopy(SReg);
20530 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20531 Info->getStackPtrOffsetReg()));
20532 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20533 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20537 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20538 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20540 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20541 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20543 Info->limitOccupancy(MF);
20545 if (ST.isWave32() && !MF.
empty()) {
20546 for (
auto &
MBB : MF) {
20547 for (
auto &
MI :
MBB) {
20548 TII->fixImplicitOperands(
MI);
20558 if (ST.needsAlignedVGPRs()) {
20559 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
20565 if (NewClassID != -1)
20566 MRI.setRegClass(Reg,
TRI->getRegClass(NewClassID));
20575 const APInt &DemandedElts,
20577 unsigned Depth)
const {
20579 unsigned Opc =
Op.getOpcode();
20582 unsigned IID =
Op.getConstantOperandVal(0);
20584 case Intrinsic::amdgcn_mbcnt_lo:
20585 case Intrinsic::amdgcn_mbcnt_hi: {
20590 Known.Zero.setBitsFrom(
20591 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20617 unsigned MaxValue =
20624 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20628 unsigned Src1Cst = 0;
20629 if (Src1.isImm()) {
20630 Src1Cst = Src1.getImm();
20631 }
else if (Src1.isReg()) {
20635 Src1Cst = Cst->Value.getZExtValue();
20646 if (Width >= BFEWidth)
20663 unsigned Depth)
const {
20666 switch (
MI->getOpcode()) {
20667 case AMDGPU::S_BFE_I32:
20670 case AMDGPU::S_BFE_U32:
20673 case AMDGPU::S_BFE_I64:
20676 case AMDGPU::S_BFE_U64:
20679 case AMDGPU::G_INTRINSIC:
20680 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20683 case Intrinsic::amdgcn_workitem_id_x:
20686 case Intrinsic::amdgcn_workitem_id_y:
20689 case Intrinsic::amdgcn_workitem_id_z:
20692 case Intrinsic::amdgcn_mbcnt_lo:
20693 case Intrinsic::amdgcn_mbcnt_hi: {
20696 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20705 case Intrinsic::amdgcn_groupstaticsize: {
20709 Known.Zero.setHighBits(
20713 case Intrinsic::amdgcn_readfirstlane:
20714 case Intrinsic::amdgcn_readlane: {
20720 case Intrinsic::amdgcn_mul_u24:
20721 case Intrinsic::amdgcn_mul_i24: {
20735 bool SelfMultiply =
20738 IID == Intrinsic::amdgcn_mul_i24,
20745 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20746 Known.Zero.setHighBits(24);
20748 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20749 Known.Zero.setHighBits(16);
20751 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20754 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20756 case AMDGPU::G_AMDGPU_SMED3:
20757 case AMDGPU::G_AMDGPU_UMED3: {
20758 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20785 unsigned Depth)
const {
20794 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20815 BlockToAlign =
ML->getHeader();
20819 if (needsFetchWindowAlignment(*BlockToAlign))
20840 if (Header->getAlignment() != PrefAlign)
20841 return Header->getAlignment();
20843 unsigned LoopSize = 0;
20848 LoopSize +=
MBB->getAlignment().value() / 2;
20851 LoopSize +=
TII->getInstSizeInBytes(
MI);
20852 if (LoopSize > 192)
20857 if (LoopSize <= 64)
20860 if (LoopSize <= 128)
20861 return CacheLineAlign;
20867 auto I = Exit->getFirstNonDebugInstr();
20868 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20869 return CacheLineAlign;
20878 if (PreTerm == Pre->
begin() ||
20879 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20883 auto ExitHead = Exit->getFirstNonDebugInstr();
20884 if (ExitHead == Exit->end() ||
20885 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20890 return CacheLineAlign;
20898 if (needsFetchWindowAlignment(*
MBB))
20903bool SITargetLowering::needsFetchWindowAlignment(
20905 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20909 if (
MI.isMetaInstruction())
20912 return TII->getInstSizeInBytes(
MI) > 4;
20922 N =
N->getOperand(0).getNode();
20932 switch (
N->getOpcode()) {
20940 if (Reg.isPhysical() ||
MRI.isLiveIn(Reg))
20941 return !
TRI->isSGPRReg(
MRI, Reg);
20947 return !
TRI->isSGPRReg(
MRI, Reg);
20951 unsigned AS = L->getAddressSpace();
20961 case AMDGPUISD::ATOMIC_CMP_SWAP:
20962 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20963 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20964 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20965 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20966 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20967 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20968 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20969 case AMDGPUISD::BUFFER_ATOMIC_AND:
20970 case AMDGPUISD::BUFFER_ATOMIC_OR:
20971 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20972 case AMDGPUISD::BUFFER_ATOMIC_INC:
20973 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20974 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20975 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20976 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20977 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20983 return A->readMem() &&
A->writeMem();
21004 switch (Ty.getScalarSizeInBits()) {
21016 const APInt &DemandedElts,
21019 unsigned Depth)
const {
21020 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
21024 if (Info->getMode().DX10Clamp)
21037enum class AtomicFlushDenormalReason {
21040 IgnoreDenormalMode,
21041 FunctionFlushesDenormals
21046enum class GlobalFPAtomicLegality {
21048 AgentScopeFineGrainedRemoteMemory,
21049 EmulatedSystemScope,
21051 NoFineGrainedMemory
21058static AtomicFlushDenormalReason
21060 if (RMW->
hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
21061 return AtomicFlushDenormalReason::IgnoreDenormalMode;
21066 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
21067 : AtomicFlushDenormalReason::IEEE;
21072 GlobalFPAtomicLegality MemLegality,
21073 AtomicFlushDenormalReason DenormReason) {
21076 if (MemScope.empty())
21077 MemScope =
"system";
21080 R <<
"hardware instruction generated for atomic "
21082 <<
" at " <<
ore::NV(
"SyncScope", MemScope) <<
" scope since ";
21084 switch (MemLegality) {
21085 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
21086 R <<
"fine-grained remote memory atomics work below system scope";
21088 case GlobalFPAtomicLegality::EmulatedSystemScope:
21089 R <<
"system scope atomics are emulated in hardware";
21091 case GlobalFPAtomicLegality::NoRemoteMemory:
21092 R <<
"memory is not remote (!amdgpu.no.remote.memory)";
21094 case GlobalFPAtomicLegality::NoFineGrainedMemory:
21095 R <<
"memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
21097 case GlobalFPAtomicLegality::Illegal:
21101 switch (DenormReason) {
21102 case AtomicFlushDenormalReason::Native:
21104 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21105 R <<
", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21107 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21108 R <<
", and the floating-point environment flushes denormals";
21110 case AtomicFlushDenormalReason::IEEE:
21119 Type *EltTy = VT->getElementType();
21120 return VT->getNumElements() == 2 &&
21140 unsigned BW =
IT->getBitWidth();
21141 return BW == 32 || BW == 64;
21155 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
21156 return BW == 32 || BW == 64;
21159 if (Ty->isFloatTy() || Ty->isDoubleTy())
21163 return VT->getNumElements() == 2 &&
21164 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21172static GlobalFPAtomicLegality
21181 if (HasSystemScope) {
21182 if (
Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21184 return GlobalFPAtomicLegality::NoRemoteMemory;
21185 if (
Subtarget.hasEmulatedSystemScopeAtomics())
21186 return GlobalFPAtomicLegality::EmulatedSystemScope;
21187 }
else if (
Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21188 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21190 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory")
21191 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21192 : GlobalFPAtomicLegality::Illegal;
21205 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
21213 return STI.hasGloballyAddressableScratch()
21231 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
21235 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21236 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21246 bool HasSystemScope =
21278 if (!Subtarget->hasSubClampInsts() ||
21280 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21282 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21287 if (!
IT ||
IT->getBitWidth() != 32)
21293 if (Subtarget->hasEmulatedSystemScopeAtomics())
21309 if (!HasSystemScope &&
21310 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21322 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
21331 ConstVal && ConstVal->isNullValue() &&
21370 if (Ty->isFloatTy()) {
21375 if (Ty->isDoubleTy()) {
21396 if (Ty->isFloatTy() &&
21397 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21399 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21405 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21412 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21416 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21420 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21425 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21430 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21434 if (Ty->isFloatTy()) {
21437 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21440 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21445 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21453 if (Subtarget->hasFlatAtomicFaddF32Inst())
21462 if (Subtarget->hasLDSFPAtomicAddF32()) {
21463 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21465 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21485 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21495 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21497 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21501 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21503 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21557 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21558 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21559 : &AMDGPU::SReg_32RegClass;
21560 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21561 return TRI->getEquivalentSGPRClass(RC);
21562 if (
TRI->isSGPRClass(RC) && isDivergent) {
21563 if (Subtarget->hasGFX90AInsts())
21564 return TRI->getEquivalentAVClass(RC);
21565 return TRI->getEquivalentVGPRClass(RC);
21578 unsigned WaveSize) {
21583 if (!
IT ||
IT->getBitWidth() != WaveSize)
21588 if (!Visited.
insert(
V).second)
21590 bool Result =
false;
21591 for (
const auto *U :
V->users()) {
21593 if (
V == U->getOperand(1)) {
21598 case Intrinsic::amdgcn_if_break:
21599 case Intrinsic::amdgcn_if:
21600 case Intrinsic::amdgcn_else:
21605 if (
V == U->getOperand(0)) {
21610 case Intrinsic::amdgcn_end_cf:
21611 case Intrinsic::amdgcn_loop:
21617 Result =
hasCFUser(U, Visited, WaveSize);
21626 const Value *V)
const {
21628 if (CI->isInlineAsm()) {
21637 for (
auto &TC : TargetConstraints) {
21651 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21679 return MRI.hasOneNonDBGUse(N0);
21686 if (
I.getMetadata(
"amdgpu.noclobber"))
21688 if (
I.getMetadata(
"amdgpu.last.use"))
21690 if (
MDNode *
N =
I.getMetadata(
"amdgpu.cfs")) {
21695 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21760 Alignment = RMW->getAlign();
21773 bool FullFlatEmulation =
21775 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21776 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21777 RMW->getType()->isDoubleTy()));
21780 bool ReturnValueIsUsed = !AI->
use_empty();
21789 if (FullFlatEmulation) {
21800 std::prev(BB->
end())->eraseFromParent();
21801 Builder.SetInsertPoint(BB);
21803 Value *LoadedShared =
nullptr;
21804 if (FullFlatEmulation) {
21805 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21806 {Addr},
nullptr,
"is.shared");
21807 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21808 Builder.SetInsertPoint(SharedBB);
21809 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21815 LoadedShared = Clone;
21817 Builder.CreateBr(PhiBB);
21818 Builder.SetInsertPoint(CheckPrivateBB);
21821 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21822 {Addr},
nullptr,
"is.private");
21823 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21825 Builder.SetInsertPoint(PrivateBB);
21827 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21830 Value *LoadedPrivate;
21832 LoadedPrivate = Builder.CreateAlignedLoad(
21833 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21837 LoadedPrivate, RMW->getValOperand());
21839 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21840 RMW->isVolatile());
21848 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21851 Builder.CreateBr(PhiBB);
21853 Builder.SetInsertPoint(GlobalBB);
21857 if (FullFlatEmulation) {
21858 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21867 if (!FullFlatEmulation) {
21872 MDNode *RangeNotPrivate =
21875 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21879 Builder.CreateBr(PhiBB);
21881 Builder.SetInsertPoint(PhiBB);
21883 if (ReturnValueIsUsed) {
21886 if (FullFlatEmulation)
21887 Loaded->addIncoming(LoadedShared, SharedBB);
21888 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21889 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21890 Loaded->takeName(AI);
21893 Builder.CreateBr(ExitBB);
21897 unsigned PtrOpIdx) {
21898 Value *PtrOp =
I->getOperand(PtrOpIdx);
21905 I->setOperand(PtrOpIdx, ASCast);
21917 ConstVal && ConstVal->isNullValue() &&
21948 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21956 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
static bool isMul(MachineInstr *MI)
static unsigned getIntrinsicID(const SDNode *N)
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
iv Induction Variable Users
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
static constexpr MCPhysReg SPReg
MachineBasicBlock * Folded
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
#define FP_DENORM_FLUSH_NONE
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static AtomicFlushDenormalReason getAtomicFlushDenormalReason(const AtomicRMWInst *RMW)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, Intrinsic::ID IntrinsicID)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static bool isFrexpExp(SDValue V, SDValue &FrexpInput)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static GlobalFPAtomicLegality getGlobalMemoryFPAtomicLegality(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW, GlobalFPAtomicLegality MemLegality, AtomicFlushDenormalReason DenormReason)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void initializeM0ToZeroForClusterLoad(SDValue Op, SelectionDAG &DAG, SDLoc DL)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > get32BitAbsoluteAddress(const GlobalValue &GV, unsigned AS)
void setUsesDynamicLDS(bool DynLDS)
bool isBottomOfStack() const
uint32_t getLDSSize() const
bool isEntryFunction() const
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
static KnownBits computeKnownBitsForMul24(const KnownBits &LHSKnown, const KnownBits &RHSKnown, unsigned BitWidth, bool IsSigned, bool SelfMultiply)
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
static bool EnableObjectLinking
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned AndSaveExecOpc
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
LLVM_READONLY int getExactLog2Abs() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
bool isMask(unsigned numBits) const
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
const Function * getParent() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getCompareOperand()
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
iterator_range< arg_iterator > args()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Argument * getArg(unsigned i) const
const SIInstrInfo * getInstrInfo() const override
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool hasKernargSegmentPtr() const
bool hasDispatchID() const
bool hasPrivateSegmentBuffer() const
unsigned getNumFreeUserSGPRs()
bool hasImplicitBufferPtr() const
bool hasPrivateSegmentSize() const
bool hasDispatchPtr() const
bool hasFlatScratchInit() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
Evaluate a known-bits query with an explicit worklist instead of recursive descent.
int64_t getOffset() const
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
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.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
const MDOperand & getOperand(unsigned I) const
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
ISD::CondCode getOperandCondCode(unsigned Num) const
Helper method returns the CondCode of a CondCodeSDNode.
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool isWholeWaveFunction() const
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
unsigned getBytesInStackArgArea() const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
Align getPrefLoopAlignment(MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const override
Return the preferred loop alignment.
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
bool isUniformLoad(const LoadSDNode *Load) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr, const MachineBasicBlock *BlockToAlign=nullptr) const
Return the preferred loop alignment.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
OSType getOS() const
Get the parsed operating system type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM_ABI void set(Value *Val)
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
APInt getExponentOnlyScaleDemandedBits()
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)
std::optional< unsigned > getExponentOnlyScaleArgIdx(unsigned IntrID)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ TowardZeroF32_TowardNegativeF64
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
unsigned getBarrierMemberCountBitMask(const IsaVersion &Version)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
CondCode getUnsignedSetCC(CondCode Code)
Convert a signed integer condition code to unsigned.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
static const MachineMemOperand::Flags MOCFSB1
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
LLVM_ABI bool isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be undef, but may be poison.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
ArgDescriptor WorkItemIDZ
ArgDescriptor WorkItemIDY
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static MCRegister getPrivateSegmentBufferReg(CallingConv::ID CC)
Returns the register a non-entry function with calling convention CC expects the private segment buff...
ArgDescriptor WorkItemIDX
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
unsigned AtomicNoRetBaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const
Return a subset of the known bits from [bitPosition,bitPosition+numBits).
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
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