47#include "llvm/IR/IntrinsicsAMDGPU.h"
48#include "llvm/IR/IntrinsicsR600.h"
60#define DEBUG_TYPE "si-lower"
79 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
80 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
82 return AMDGPU::SGPR0 +
Reg;
98 TRI->getDefaultVectorSuperClassForBitWidth(32);
104 TRI->getDefaultVectorSuperClassForBitWidth(64);
142 TRI->getDefaultVectorSuperClassForBitWidth(320));
146 TRI->getDefaultVectorSuperClassForBitWidth(352));
150 TRI->getDefaultVectorSuperClassForBitWidth(384));
154 TRI->getDefaultVectorSuperClassForBitWidth(512));
161 TRI->getDefaultVectorSuperClassForBitWidth(1024));
163 if (Subtarget->has16BitInsts()) {
164 if (Subtarget->useRealTrue16Insts()) {
194 TRI->getDefaultVectorSuperClassForBitWidth(1024));
210 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
211 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
212 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
213 MVT::i1, MVT::v32i32},
217 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
218 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
219 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
220 MVT::i1, MVT::v32i32},
238 if (Subtarget->hasBF16PackedInsts()) {
305 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
312 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
313 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
314 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
317 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
318 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
319 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
323 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
324 MVT::v3i16, MVT::v4i16, MVT::Other},
329 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
345 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
346 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
347 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
348 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
349 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
350 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
351 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
352 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
387 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
401 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
415 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
429 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
443 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
458 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
459 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
462 if (Subtarget->hasPkMovB32()) {
483 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
484 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
489 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
493 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
494 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
495 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
496 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
520 if (Subtarget->hasSMemRealTime() ||
525 if (Subtarget->has16BitInsts()) {
535 if (Subtarget->hasMadMacF32Insts())
553 if (Subtarget->hasIntClamp())
556 if (Subtarget->hasAddNoCarryInsts())
562 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
565 {MVT::f64, MVT::f32},
Legal);
569 {MVT::f64, MVT::f32},
Custom);
574 {MVT::f64, MVT::f32},
Legal);
577 if (Subtarget->haveRoundOpsF64())
607 if (Subtarget->has16BitInsts()) {
655 if (!Subtarget->useRealTrue16Insts() ||
656 !Subtarget->d16PreservesUnusedBits()) {
657 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
663 if (!Subtarget->useRealTrue16Insts()) {
664 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
676 if (Subtarget->hasBF16TransInsts())
692 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
693 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
694 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
729 if (Subtarget->hasVCvtPkIU16F32())
732 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
739 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
839 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
840 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
841 MVT::v32f16, MVT::v32bf16},
843 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
850 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
Custom);
861 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
865 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
870 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
871 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
878 if (Subtarget->hasVOP3PInsts()) {
889 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
892 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
893 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
894 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
897 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
905 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
911 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
921 {MVT::v2f16, MVT::v4f16},
Custom);
927 if (Subtarget->hasBF16PackedInsts()) {
933 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
941 if (Subtarget->hasAnyPackedFP32Ops()) {
945 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
948 if (Subtarget->hasAnyPackedFP64Ops()) {
954 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
956 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
963 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
972 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
977 if (Subtarget->hasAnyPackedU64Ops()) {
981 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
988 if (Subtarget->has16BitInsts()) {
1003 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1004 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1005 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1006 MVT::v32f16, MVT::v32bf16},
1011 if (Subtarget->useVMulU64Inst())
1013 else if (Subtarget->hasScalarSMulU64())
1016 if (Subtarget->hasMad64_32())
1019 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1025 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1027 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
1030 if (Subtarget->hasMinimum3Maximum3F32())
1033 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1037 if (!Subtarget->hasMinimum3Maximum3F16())
1043 if (Subtarget->hasVOP3PInsts()) {
1046 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1050 if (Subtarget->useMinMaxI64Insts())
1055 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1056 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1061 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1062 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1063 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1064 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1079 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1084 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1085 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1086 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1087 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1102 if (Subtarget->hasBF16ConversionInsts()) {
1104 {MVT::bf16, MVT::v2bf16},
Custom);
1108 if (Subtarget->hasBF16TransInsts()) {
1112 const bool HasE5M3ConversionInsts =
1113 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1114 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1125 if (Subtarget->hasFP8F16ConversionInsts()) {
1130 if (Subtarget->hasCvtPkF16F32Inst()) {
1132 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1185 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1226 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1239 EVT DestVT,
EVT SrcVT)
const {
1241 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1242 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1244 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1251 LLT DestTy,
LLT SrcTy)
const {
1252 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1255 SrcTy.getScalarSizeInBits() == 16 &&
1276 return Subtarget->has16BitInsts()
1282 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1286 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1308 return (NumElts + 1) / 2;
1314 return NumElts * ((
Size + 31) / 32);
1323 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1332 MVT SimpleIntermediateVT =
1334 IntermediateVT = SimpleIntermediateVT;
1335 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1336 NumIntermediates = (NumElts + 1) / 2;
1337 return (NumElts + 1) / 2;
1342 IntermediateVT = RegisterVT;
1343 NumIntermediates = NumElts;
1344 return NumIntermediates;
1349 RegisterVT = MVT::i16;
1350 IntermediateVT = ScalarVT;
1351 NumIntermediates = NumElts;
1352 return NumIntermediates;
1356 RegisterVT = MVT::i32;
1357 IntermediateVT = ScalarVT;
1358 NumIntermediates = NumElts;
1359 return NumIntermediates;
1363 RegisterVT = MVT::i32;
1364 IntermediateVT = RegisterVT;
1365 NumIntermediates = NumElts * ((
Size + 31) / 32);
1366 return NumIntermediates;
1371 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1376 unsigned MaxNumLanes) {
1377 assert(MaxNumLanes != 0);
1381 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1386 return TLI.getValueType(
DL, Ty);
1392 unsigned MaxNumLanes) {
1398 assert(ST->getNumContainedTypes() == 2 &&
1399 ST->getContainedType(1)->isIntegerTy(32));
1413 return MVT::amdgpuBufferFatPointer;
1415 DL.getPointerSizeInBits(AS) == 192)
1416 return MVT::amdgpuBufferStridedPointer;
1425 DL.getPointerSizeInBits(AS) == 160) ||
1427 DL.getPointerSizeInBits(AS) == 192))
1434 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1435 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1436 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1438 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1439 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1440 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1441 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1442 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1443 case Intrinsic::amdgcn_flat_load_monitor_b32:
1444 case Intrinsic::amdgcn_global_load_monitor_b32:
1446 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1447 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1448 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1449 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1450 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1451 case Intrinsic::amdgcn_flat_load_monitor_b64:
1452 case Intrinsic::amdgcn_global_load_monitor_b64:
1454 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1455 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1456 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1457 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1458 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1459 case Intrinsic::amdgcn_flat_load_monitor_b128:
1460 case Intrinsic::amdgcn_global_load_monitor_b128:
1496 unsigned IntrID)
const {
1498 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1512 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1526 if (RsrcIntr->IsImage) {
1541 Info.ptrVal = RsrcArg;
1545 if (RsrcIntr->IsImage) {
1546 unsigned MaxNumLanes = 4;
1561 std::numeric_limits<unsigned>::max());
1571 if (RsrcIntr->IsImage) {
1591 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1593 Info.memVT = MVT::i32;
1600 case Intrinsic::amdgcn_raw_buffer_load_lds:
1601 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1602 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1603 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1604 case Intrinsic::amdgcn_struct_buffer_load_lds:
1605 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1606 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1607 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1621 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1630 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1631 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1632 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1633 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1636 std::numeric_limits<unsigned>::max());
1649 case Intrinsic::amdgcn_ds_ordered_add:
1650 case Intrinsic::amdgcn_ds_ordered_swap: {
1664 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1665 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1668 Info.ptrVal =
nullptr;
1674 case Intrinsic::amdgcn_ds_append:
1675 case Intrinsic::amdgcn_ds_consume: {
1689 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1690 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1691 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1696 Info.memVT = MVT::i64;
1704 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1705 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1706 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1709 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1712 ->getElementType(0));
1721 case Intrinsic::amdgcn_global_atomic_fmin_num:
1722 case Intrinsic::amdgcn_global_atomic_fmax_num:
1723 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1724 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1725 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1736 case Intrinsic::amdgcn_cluster_load_b32:
1737 case Intrinsic::amdgcn_cluster_load_b64:
1738 case Intrinsic::amdgcn_cluster_load_b128:
1739 case Intrinsic::amdgcn_ds_load_tr6_b96:
1740 case Intrinsic::amdgcn_ds_load_tr4_b64:
1741 case Intrinsic::amdgcn_ds_load_tr8_b64:
1742 case Intrinsic::amdgcn_ds_load_tr16_b128:
1743 case Intrinsic::amdgcn_global_load_tr6_b96:
1744 case Intrinsic::amdgcn_global_load_tr4_b64:
1745 case Intrinsic::amdgcn_global_load_tr_b64:
1746 case Intrinsic::amdgcn_global_load_tr_b128:
1747 case Intrinsic::amdgcn_ds_read_tr4_b64:
1748 case Intrinsic::amdgcn_ds_read_tr6_b96:
1749 case Intrinsic::amdgcn_ds_read_tr8_b64:
1750 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1759 case Intrinsic::amdgcn_flat_load_monitor_b32:
1760 case Intrinsic::amdgcn_flat_load_monitor_b64:
1761 case Intrinsic::amdgcn_flat_load_monitor_b128:
1762 case Intrinsic::amdgcn_global_load_monitor_b32:
1763 case Intrinsic::amdgcn_global_load_monitor_b64:
1764 case Intrinsic::amdgcn_global_load_monitor_b128: {
1775 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1776 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1777 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1788 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1789 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1790 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1801 case Intrinsic::amdgcn_ds_gws_init:
1802 case Intrinsic::amdgcn_ds_gws_barrier:
1803 case Intrinsic::amdgcn_ds_gws_sema_v:
1804 case Intrinsic::amdgcn_ds_gws_sema_br:
1805 case Intrinsic::amdgcn_ds_gws_sema_p:
1806 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1816 Info.memVT = MVT::i32;
1818 Info.align =
Align(4);
1820 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1827 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1828 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1829 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1830 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1831 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1832 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1833 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1834 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1849 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1850 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1851 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1852 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1867 case Intrinsic::amdgcn_av_load_b8:
1868 case Intrinsic::amdgcn_av_load_b16:
1869 case Intrinsic::amdgcn_av_load_b32:
1870 case Intrinsic::amdgcn_av_load_b64:
1871 case Intrinsic::amdgcn_av_load_b128:
1872 case Intrinsic::amdgcn_av_store_b8:
1873 case Intrinsic::amdgcn_av_store_b16:
1874 case Intrinsic::amdgcn_av_store_b32:
1875 case Intrinsic::amdgcn_av_store_b64:
1876 case Intrinsic::amdgcn_av_store_b128: {
1882 Info.align =
Align(Info.memVT.getStoreSize());
1890 unsigned ScopeIdx = CI.
arg_size() - 1;
1894 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1898 case Intrinsic::amdgcn_load_to_lds:
1899 case Intrinsic::amdgcn_load_async_to_lds:
1900 case Intrinsic::amdgcn_global_load_lds:
1901 case Intrinsic::amdgcn_global_load_async_lds: {
1920 Width * 8 * Subtarget->getWavefrontSize());
1926 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1927 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1928 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1929 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1939 Info.memVT = MVT::i32;
1941 Info.align =
Align(4);
1947 case Intrinsic::amdgcn_s_prefetch_data:
1948 case Intrinsic::amdgcn_s_prefetch_inst:
1949 case Intrinsic::amdgcn_flat_prefetch:
1950 case Intrinsic::amdgcn_global_prefetch: {
1965 Type *&AccessTy)
const {
1966 Value *Ptr =
nullptr;
1967 switch (
II->getIntrinsicID()) {
1968 case Intrinsic::amdgcn_cluster_load_b128:
1969 case Intrinsic::amdgcn_cluster_load_b64:
1970 case Intrinsic::amdgcn_cluster_load_b32:
1971 case Intrinsic::amdgcn_ds_append:
1972 case Intrinsic::amdgcn_ds_consume:
1973 case Intrinsic::amdgcn_ds_load_tr8_b64:
1974 case Intrinsic::amdgcn_ds_load_tr16_b128:
1975 case Intrinsic::amdgcn_ds_load_tr4_b64:
1976 case Intrinsic::amdgcn_ds_load_tr6_b96:
1977 case Intrinsic::amdgcn_ds_read_tr4_b64:
1978 case Intrinsic::amdgcn_ds_read_tr6_b96:
1979 case Intrinsic::amdgcn_ds_read_tr8_b64:
1980 case Intrinsic::amdgcn_ds_read_tr16_b64:
1981 case Intrinsic::amdgcn_ds_ordered_add:
1982 case Intrinsic::amdgcn_ds_ordered_swap:
1983 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1984 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1985 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1986 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1987 case Intrinsic::amdgcn_global_atomic_fmax_num:
1988 case Intrinsic::amdgcn_global_atomic_fmin_num:
1989 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1990 case Intrinsic::amdgcn_global_load_tr_b64:
1991 case Intrinsic::amdgcn_global_load_tr_b128:
1992 case Intrinsic::amdgcn_global_load_tr4_b64:
1993 case Intrinsic::amdgcn_global_load_tr6_b96:
1994 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1995 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1996 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1997 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1998 case Intrinsic::amdgcn_av_load_b8:
1999 case Intrinsic::amdgcn_av_load_b16:
2000 case Intrinsic::amdgcn_av_load_b32:
2001 case Intrinsic::amdgcn_av_load_b64:
2002 case Intrinsic::amdgcn_av_load_b128:
2003 case Intrinsic::amdgcn_av_store_b8:
2004 case Intrinsic::amdgcn_av_store_b16:
2005 case Intrinsic::amdgcn_av_store_b32:
2006 case Intrinsic::amdgcn_av_store_b64:
2007 case Intrinsic::amdgcn_av_store_b128:
2008 Ptr =
II->getArgOperand(0);
2010 case Intrinsic::amdgcn_load_to_lds:
2011 case Intrinsic::amdgcn_load_async_to_lds:
2012 case Intrinsic::amdgcn_global_load_lds:
2013 case Intrinsic::amdgcn_global_load_async_lds:
2014 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2015 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2016 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2017 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2018 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2019 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2020 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2021 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2022 Ptr =
II->getArgOperand(1);
2027 AccessTy =
II->getType();
2033 unsigned AddrSpace)
const {
2034 if (!Subtarget->hasFlatInstOffsets()) {
2041 FlatAddrSpace FlatVariant =
2044 : FlatAddrSpace::FLAT;
2046 return AM.
Scale == 0 &&
2047 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2048 AM.
BaseOffs, AddrSpace, FlatVariant));
2052 if (Subtarget->hasFlatGlobalInsts())
2055 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2068 return isLegalMUBUFAddressingMode(AM);
2071bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2082 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2094 if (AM.HasBaseReg) {
2126 return isLegalMUBUFAddressingMode(AM);
2128 if (!Subtarget->hasScalarSubwordLoads()) {
2133 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2181 return Subtarget->hasFlatScratchEnabled()
2183 : isLegalMUBUFAddressingMode(AM);
2230 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2239 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2242 Align RequiredAlignment(
2244 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2245 Alignment < RequiredAlignment)
2260 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2266 RequiredAlignment =
Align(4);
2268 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2284 *IsFast = (Alignment >= RequiredAlignment) ? 64
2285 : (Alignment <
Align(4)) ? 32
2292 if (!Subtarget->hasDS96AndDS128())
2298 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2307 *IsFast = (Alignment >= RequiredAlignment) ? 96
2308 : (Alignment <
Align(4)) ? 32
2315 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2321 RequiredAlignment =
Align(8);
2323 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2332 *IsFast = (Alignment >= RequiredAlignment) ? 128
2333 : (Alignment <
Align(4)) ? 32
2350 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2352 return Alignment >= RequiredAlignment ||
2353 Subtarget->hasUnalignedDSAccessEnabled();
2361 bool AlignedBy4 = Alignment >=
Align(4);
2362 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2364 *IsFast = AlignedBy4 ?
Size : 1;
2369 *IsFast = AlignedBy4;
2380 return Alignment >=
Align(4) ||
2381 Subtarget->hasUnalignedBufferAccessEnabled();
2394 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2409 return Size >= 32 && Alignment >=
Align(4);
2414 unsigned *IsFast)
const {
2416 Alignment, Flags, IsFast);
2427 if (
Op.size() >= 16 &&
2431 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2449 unsigned DestAS)
const {
2452 Subtarget->hasGloballyAddressableScratch()) {
2483 unsigned Index)
const {
2497 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2502 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2529 if (Subtarget->hasScalarSubwordLoads() &&
N->getOpcode() ==
ISD::LOAD &&
2580 auto [InputPtrReg, RC, ArgTy] =
2590 Chain, SL,
MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2596 const SDLoc &SL)
const {
2603 const SDLoc &SL)
const {
2606 std::optional<uint32_t> KnownSize =
2608 if (KnownSize.has_value())
2635 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2650SDValue SITargetLowering::lowerKernargMemParameter(
2655 MachinePointerInfo PtrInfo =
2664 int64_t OffsetDiff =
Offset - AlignDownOffset;
2670 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2681 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2686 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2700 const SDLoc &SL)
const {
2769 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2772 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2773 if (ConvertedVal == ArgValue)
2774 return ConvertedVal;
2779SDValue SITargetLowering::lowerWorkGroupId(
2784 if (!Subtarget->hasClusters())
2785 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2793 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2794 SDLoc SL(ClusterIdXYZ);
2795 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2798 SDValue ClusterWorkGroupIdXYZ =
2799 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2809 return ClusterIdXYZ;
2811 using namespace AMDGPU::Hwreg;
2815 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2826SDValue SITargetLowering::getPreloadedValue(
2829 const ArgDescriptor *
Reg =
nullptr;
2834 const ArgDescriptor WorkGroupIDX =
2842 const ArgDescriptor WorkGroupIDZ =
2844 const ArgDescriptor ClusterWorkGroupIDX =
2846 const ArgDescriptor ClusterWorkGroupIDY =
2848 const ArgDescriptor ClusterWorkGroupIDZ =
2850 const ArgDescriptor ClusterWorkGroupMaxIDX =
2852 const ArgDescriptor ClusterWorkGroupMaxIDY =
2854 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2856 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2859 auto LoadConstant = [&](
unsigned N) {
2863 if (Subtarget->hasArchitectedSGPRs() &&
2871 Reg = &WorkGroupIDX;
2872 RC = &AMDGPU::SReg_32RegClass;
2876 Reg = &WorkGroupIDY;
2877 RC = &AMDGPU::SReg_32RegClass;
2881 Reg = &WorkGroupIDZ;
2882 RC = &AMDGPU::SReg_32RegClass;
2886 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2887 return LoadConstant(0);
2888 Reg = &ClusterWorkGroupIDX;
2889 RC = &AMDGPU::SReg_32RegClass;
2893 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2894 return LoadConstant(0);
2895 Reg = &ClusterWorkGroupIDY;
2896 RC = &AMDGPU::SReg_32RegClass;
2900 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2901 return LoadConstant(0);
2902 Reg = &ClusterWorkGroupIDZ;
2903 RC = &AMDGPU::SReg_32RegClass;
2908 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2909 Reg = &ClusterWorkGroupMaxIDX;
2910 RC = &AMDGPU::SReg_32RegClass;
2915 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2916 Reg = &ClusterWorkGroupMaxIDY;
2917 RC = &AMDGPU::SReg_32RegClass;
2922 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2923 Reg = &ClusterWorkGroupMaxIDZ;
2924 RC = &AMDGPU::SReg_32RegClass;
2928 Reg = &ClusterWorkGroupMaxFlatID;
2929 RC = &AMDGPU::SReg_32RegClass;
2960 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2964 "vector type argument should have been split");
2969 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2977 "unexpected vector split in ps argument type");
2991 Info->markPSInputAllocated(PSInputNum);
2993 Info->markPSInputEnabled(PSInputNum);
3009 if (Info.hasWorkItemIDX()) {
3011 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3015 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3019 if (Info.hasWorkItemIDY()) {
3020 assert(Info.hasWorkItemIDX());
3021 if (Subtarget->hasPackedTID()) {
3022 Info.setWorkItemIDY(
3025 unsigned Reg = AMDGPU::VGPR1;
3026 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3033 if (Info.hasWorkItemIDZ()) {
3034 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3035 if (Subtarget->hasPackedTID()) {
3036 Info.setWorkItemIDZ(
3039 unsigned Reg = AMDGPU::VGPR2;
3040 MRI.setType(MF.
addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3050 unsigned NumArgRegs) {
3053 if (RegIdx == ArgSGPRs.
size())
3056 unsigned Reg = ArgSGPRs[RegIdx];
3101 const unsigned Mask = 0x3ff;
3110 auto &
ArgInfo = Info.getArgInfo();
3122 if (Info.hasImplicitArgPtr())
3130 if (Info.hasWorkGroupIDX())
3133 if (Info.hasWorkGroupIDY())
3136 if (Info.hasWorkGroupIDZ())
3139 if (Info.hasLDSKernelId())
3150 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3151 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3157 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3158 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3163 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3164 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3170 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3176 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3185 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3190 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3191 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3196 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3197 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3212 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3214 bool InPreloadSequence =
true;
3216 bool AlignedForImplictArgs =
false;
3217 unsigned ImplicitArgOffset = 0;
3218 for (
auto &Arg :
F.args()) {
3219 if (!InPreloadSequence || !Arg.hasInRegAttr())
3222 unsigned ArgIdx = Arg.getArgNo();
3225 if (InIdx < Ins.
size() &&
3226 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3229 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3230 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3232 assert(ArgLocs[ArgIdx].isMemLoc());
3233 auto &ArgLoc = ArgLocs[InIdx];
3235 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3237 unsigned NumAllocSGPRs =
3238 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3241 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3242 if (!AlignedForImplictArgs) {
3244 alignTo(LastExplicitArgOffset,
3245 Subtarget->getAlignmentForImplicitArgPtr()) -
3246 LastExplicitArgOffset;
3247 AlignedForImplictArgs =
true;
3249 ArgOffset += ImplicitArgOffset;
3253 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3254 assert(InIdx >= 1 &&
"No previous SGPR");
3255 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3256 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3260 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3261 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3264 InPreloadSequence =
false;
3270 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3272 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3274 if (PreloadRegs->
size() > 1)
3275 RC = &AMDGPU::SGPR_32RegClass;
3276 for (
auto &Reg : *PreloadRegs) {
3282 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3291 if (Info.hasLDSKernelId()) {
3292 Register Reg = Info.addLDSKernelId();
3293 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3302 bool IsShader)
const {
3303 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3304 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3310 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3312 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3316 unsigned NumRequiredSystemSGPRs =
3317 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3318 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3319 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3320 Register Reg = Info.addReservedUserSGPR();
3321 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3326 if (!HasArchitectedSGPRs) {
3327 if (Info.hasWorkGroupIDX()) {
3328 Register Reg = Info.addWorkGroupIDX();
3329 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3333 if (Info.hasWorkGroupIDY()) {
3334 Register Reg = Info.addWorkGroupIDY();
3335 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3339 if (Info.hasWorkGroupIDZ()) {
3340 Register Reg = Info.addWorkGroupIDZ();
3341 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3346 if (Info.hasWorkGroupInfo()) {
3347 Register Reg = Info.addWorkGroupInfo();
3348 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3352 if (Info.hasPrivateSegmentWaveByteOffset()) {
3354 unsigned PrivateSegmentWaveByteOffsetReg;
3357 PrivateSegmentWaveByteOffsetReg =
3358 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3362 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3364 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3367 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3369 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3370 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3373 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3374 Info.getNumPreloadedSGPRs() >= 16);
3389 if (HasStackObjects)
3390 Info.setHasNonSpillStackObjects(
true);
3395 HasStackObjects =
true;
3399 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3401 if (!ST.hasFlatScratchEnabled()) {
3402 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3409 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3411 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3421 Info.setScratchRSrcReg(ReservedBufferReg);
3440 if (!
MRI.isLiveIn(AMDGPU::SGPR32)) {
3441 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3448 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3449 if (!
MRI.isLiveIn(
Reg)) {
3450 Info.setStackPtrOffsetReg(
Reg);
3455 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3462 if (ST.getFrameLowering()->hasFP(MF)) {
3463 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3479 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3488 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3489 RC = &AMDGPU::SGPR_64RegClass;
3490 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3491 RC = &AMDGPU::SGPR_32RegClass;
3497 Entry->addLiveIn(*
I);
3502 for (
auto *Exit : Exits)
3504 TII->get(TargetOpcode::COPY), *
I)
3519 bool IsError =
false;
3523 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3541 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3542 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3544 if (!Subtarget->hasFlatScratchEnabled())
3549 !Subtarget->hasArchitectedSGPRs())
3550 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3551 !Info->hasWorkGroupIDZ());
3554 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3572 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3573 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3576 Info->markPSInputAllocated(0);
3577 Info->markPSInputEnabled(0);
3579 if (Subtarget->isAmdPalOS()) {
3588 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3589 if ((PsInputBits & 0x7F) == 0 ||
3590 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3593 }
else if (IsKernel) {
3594 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3606 if (IsKernel && Subtarget->hasKernargPreload())
3610 }
else if (!IsGraphics) {
3615 if (!Subtarget->hasFlatScratchEnabled())
3627 Info->setNumWaveDispatchSGPRs(
3629 Info->setNumWaveDispatchVGPRs(
3631 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3632 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3637 if (IsWholeWaveFunc) {
3639 {MVT::i1, MVT::Other}, Chain);
3651 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3662 if (IsEntryFunc && VA.
isMemLoc()) {
3686 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3690 int64_t OffsetDiff =
Offset - AlignDownOffset;
3697 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3708 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3709 Ins[i].Flags.isSExt(), &Ins[i]);
3717 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3720 if (PreloadRegs.
size() == 1) {
3721 Register VReg =
MRI.getLiveInVirtReg(PreloadRegs[0]);
3726 TRI->getRegSizeInBits(*RC)));
3734 for (
auto Reg : PreloadRegs) {
3741 PreloadRegs.size()),
3758 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3759 Ins[i].Flags.isSExt(), &Ins[i]);
3771 "hidden argument in kernel signature was not preloaded",
3777 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3778 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3798 if (!IsEntryFunc && VA.
isMemLoc()) {
3799 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3810 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3811 RC = &AMDGPU::VGPR_32RegClass;
3812 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3813 RC = &AMDGPU::SGPR_32RegClass;
3819 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3825 ReadFirstLane, Val);
3834 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3843 Info->setBytesInStackArgArea(StackArgSize);
3845 return Chains.
empty() ? Chain
3854 const Type *RetTy)
const {
3862 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3867 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3868 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3869 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3870 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3893 Info->setIfReturnsVoid(Outs.
empty());
3894 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3913 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3914 ++
I, ++RealRVLocIdx) {
3918 SDValue Arg = OutVals[RealRVLocIdx];
3941 ReadFirstLane, Arg);
3948 if (!Info->isEntryFunction()) {
3954 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3956 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3969 unsigned Opc = AMDGPUISD::ENDPGM;
3971 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3972 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3973 : AMDGPUISD::RET_GLUE;
4078 const auto [OutgoingArg, ArgRC, ArgTy] =
4083 const auto [IncomingArg, IncomingArgRC, Ty] =
4085 assert(IncomingArgRC == ArgRC);
4088 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4096 InputReg = getImplicitArgPtr(DAG,
DL);
4098 std::optional<uint32_t> Id =
4100 if (Id.has_value()) {
4111 if (OutgoingArg->isRegister()) {
4112 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4113 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4116 unsigned SpecialArgOffset =
4127 auto [OutgoingArg, ArgRC, Ty] =
4130 std::tie(OutgoingArg, ArgRC, Ty) =
4133 std::tie(OutgoingArg, ArgRC, Ty) =
4148 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4149 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4150 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4155 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4163 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4173 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4182 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4183 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4194 : IncomingArgY ? *IncomingArgY
4201 if (OutgoingArg->isRegister()) {
4203 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4229 if (Callee->isDivergent())
4236 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4240 if (!CallerPreserved)
4243 bool CCMatch = CallerCC == CalleeCC;
4256 if (Arg.hasByValAttr())
4270 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4271 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4280 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4293 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4295 if (!CCVA.isRegLoc())
4300 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4302 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4326enum ChainCallArgIdx {
4348 bool UsesDynamicVGPRs =
false;
4349 if (IsChainCallConv) {
4354 auto RequestedExecIt =
4356 return Arg.OrigArgIndex == 2;
4358 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4360 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4363 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4366 "Haven't popped all the special args");
4369 CLI.
Args[ChainCallArgIdx::Exec];
4370 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4378 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4380 ChainCallSpecialArgs.
push_back(Arg.Node);
4383 PushNodeOrTargetConstant(RequestedExecArg);
4389 if (FlagsValue.
isZero()) {
4390 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4392 "no additional args allowed if flags == 0");
4394 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4398 if (!Subtarget->isWave32()) {
4400 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4403 UsesDynamicVGPRs =
true;
4404 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4405 CLI.
Args.end(), PushNodeOrTargetConstant);
4414 bool IsSibCall =
false;
4428 "unsupported call to variadic function ");
4436 "unsupported required tail call to function ");
4441 Outs, OutVals, Ins, DAG);
4445 "site marked musttail or on llvm.amdgcn.cs.chain");
4452 if (!TailCallOpt && IsTailCall)
4476 if (!Subtarget->hasFlatScratchEnabled()) {
4499 auto *
TRI = Subtarget->getRegisterInfo();
4506 if (!IsSibCall || IsChainCallConv) {
4507 if (!Subtarget->hasFlatScratchEnabled()) {
4513 RegsToPass.emplace_back(
4521 const unsigned NumSpecialInputs = RegsToPass.size();
4523 MVT PtrVT = MVT::i32;
4526 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4554 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4562 int32_t
Offset = LocMemOffset;
4569 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4575 ? Flags.getNonZeroByValAlign()
4602 if (Outs[i].Flags.isByVal()) {
4604 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4607 Outs[i].Flags.getNonZeroByValAlign(),
4608 Outs[i].Flags.getNonZeroByValAlign(),
4610 nullptr, std::nullopt, DstInfo,
4616 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4622 if (!MemOpChains.
empty())
4638 unsigned ArgIdx = 0;
4639 for (
auto [Reg, Val] : RegsToPass) {
4640 if (ArgIdx++ >= NumSpecialInputs &&
4641 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4667 if (IsTailCall && !IsSibCall) {
4672 std::vector<SDValue>
Ops({Chain});
4678 Ops.push_back(Callee);
4695 Ops.push_back(Callee);
4706 if (IsChainCallConv)
4711 for (
auto &[Reg, Val] : RegsToPass)
4715 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4716 assert(Mask &&
"Missing call preserved mask for calling convention");
4726 MVT::Glue, GlueOps),
4731 Ops.push_back(InGlue);
4737 unsigned OPC = AMDGPUISD::TC_RETURN;
4740 OPC = AMDGPUISD::TC_RETURN_GFX;
4744 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4745 : AMDGPUISD::TC_RETURN_CHAIN;
4751 if (Info->isWholeWaveFunction())
4752 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4762 Chain =
Call.getValue(0);
4763 InGlue =
Call.getValue(1);
4765 uint64_t CalleePopBytes = NumBytes;
4786 EVT VT =
Op.getValueType();
4800 "Stack grows upwards for AMDGPU");
4802 Chain = BaseAddr.getValue(1);
4804 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4805 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4808 if (Alignment > StackAlign) {
4809 uint64_t ScaledAlignment = Alignment.value()
4810 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4811 uint64_t StackAlignMask = ScaledAlignment - 1;
4818 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4827 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4838 if (!HasFlatScratch) {
4841 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4858 if (
Op.getValueType() != MVT::i32)
4877 assert(
Op.getValueType() == MVT::i32);
4886 Op.getOperand(0), IntrinID, GetRoundBothImm);
4920 SDValue RoundModeTimesNumBits =
4940 TableEntry, EnumOffset);
4956 static_cast<uint32_t>(ConstMode->getZExtValue()),
4968 if (UseReducedTable) {
4974 SDValue RoundModeTimesNumBits =
4994 SDValue RoundModeTimesNumBits =
5003 NewMode = TruncTable;
5012 ReadFirstLaneID, NewMode);
5025 IntrinID, RoundBothImm, NewMode);
5033 return Op.getOperand(0);
5038 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5056 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5057 EVT SrcVT = Src.getValueType();
5066 EVT DstVT =
Op.getValueType();
5075 if (
Op.getValueType() != MVT::i64)
5089 Op.getOperand(0), IntrinID, ModeHwRegImm);
5091 Op.getOperand(0), IntrinID, TrapHwRegImm);
5105 if (
Op.getOperand(1).getValueType() != MVT::i64)
5117 ReadFirstLaneID, NewModeReg);
5119 ReadFirstLaneID, NewTrapReg);
5121 unsigned ModeHwReg =
5124 unsigned TrapHwReg =
5132 IntrinID, ModeHwRegImm, NewModeReg);
5135 IntrinID, TrapHwRegImm, NewTrapReg);
5143 .
Case(
"m0", AMDGPU::M0)
5144 .
Case(
"exec", AMDGPU::EXEC)
5145 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5146 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5147 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5148 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5149 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5150 .
Case(
"src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5151 .
Case(
"src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5152 .
Case(
"src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5158 if (!Subtarget->hasFlatScrRegister() &&
5159 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5162 if (!Subtarget->hasGloballyAddressableScratch() &&
5163 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5168 case AMDGPU::EXEC_LO:
5169 case AMDGPU::EXEC_HI:
5170 case AMDGPU::FLAT_SCR_LO:
5171 case AMDGPU::FLAT_SCR_HI:
5172 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5173 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5178 case AMDGPU::FLAT_SCR:
5179 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5198 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5207static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5229 auto Next = std::next(
I);
5240 MBB.addSuccessor(LoopBB);
5242 return std::pair(LoopBB, RemainderBB);
5249 auto I =
MI.getIterator();
5250 auto E = std::next(
I);
5272 Src->setIsKill(
false);
5282 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5288 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5291 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5315 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5316 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5326 Register PhiExec =
MRI.createVirtualRegister(BoolRC);
5327 Register NewExec =
MRI.createVirtualRegister(BoolRC);
5329 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5330 Register CondReg =
MRI.createVirtualRegister(BoolRC);
5338 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5345 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5349 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5351 .
addReg(Idx.getReg(), {}, Idx.getSubReg());
5358 MRI.setSimpleHint(NewExec, CondReg);
5360 if (UseGPRIdxMode) {
5362 SGPRIdxReg = CurrentIdxReg;
5364 SGPRIdxReg =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5365 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5376 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5409 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5410 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5418 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5420 Register SaveExec =
MRI.createVirtualRegister(BoolXExecRC);
5421 Register TmpExec =
MRI.createVirtualRegister(BoolXExecRC);
5437 InitResultReg, DstReg, PhiReg, TmpExec,
5438 Offset, UseGPRIdxMode, SGPRIdxReg);
5444 LoopBB->removeSuccessor(RemainderBB);
5446 LoopBB->addSuccessor(LandingPad);
5457static std::pair<unsigned, int>
5461 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5466 return std::pair(AMDGPU::sub0,
Offset);
5480 assert(Idx->getReg() != AMDGPU::NoRegister);
5505 return Idx->getReg();
5507 Register Tmp =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5525 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5526 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5532 std::tie(SubReg,
Offset) =
5535 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5538 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5542 if (UseGPRIdxMode) {
5549 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5558 .
addReg(SrcReg, {}, SubReg)
5562 MI.eraseFromParent();
5571 Register PhiReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5572 Register InitReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5578 UseGPRIdxMode, SGPRIdxReg);
5582 if (UseGPRIdxMode) {
5584 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5586 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5591 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5592 .
addReg(SrcReg, {}, SubReg)
5596 MI.eraseFromParent();
5613 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5621 std::tie(SubReg,
Offset) =
5623 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5625 if (Idx->getReg() == AMDGPU::NoRegister) {
5636 MI.eraseFromParent();
5641 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5645 if (UseGPRIdxMode) {
5649 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5658 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5659 TRI.getRegSizeInBits(*VecRC), 32,
false);
5665 MI.eraseFromParent();
5672 Register PhiReg =
MRI.createVirtualRegister(VecRC);
5676 UseGPRIdxMode, SGPRIdxReg);
5679 if (UseGPRIdxMode) {
5681 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5683 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5689 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5690 TRI.getRegSizeInBits(*VecRC), 32,
false);
5691 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5697 MI.eraseFromParent();
5713 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5714 if (ST.hasScalarAddSub64()) {
5716 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5726 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5727 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5730 MI,
MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5732 MI,
MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5735 MI,
MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5737 MI,
MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5742 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5743 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5749 Hi.setOperandDead(3);
5756 MI.eraseFromParent();
5770 Register SrcCond =
MI.getOperand(3).getReg();
5772 Register DstLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5773 Register DstHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5775 Register SrcCondCopy =
MRI.createVirtualRegister(CondRC);
5778 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5780 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5782 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5784 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5787 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5789 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5792 MI,
MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5794 MI,
MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5797 MI,
MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5799 MI,
MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5821 MI.eraseFromParent();
5826 case AMDGPU::S_MIN_U32:
5827 return std::numeric_limits<uint32_t>::max();
5828 case AMDGPU::S_MIN_I32:
5829 return std::numeric_limits<int32_t>::max();
5830 case AMDGPU::S_MAX_U32:
5831 return std::numeric_limits<uint32_t>::min();
5832 case AMDGPU::S_MAX_I32:
5833 return std::numeric_limits<int32_t>::min();
5834 case AMDGPU::V_ADD_F32_e64:
5836 case AMDGPU::V_SUB_F32_e64:
5838 case AMDGPU::S_ADD_I32:
5839 case AMDGPU::S_SUB_I32:
5840 case AMDGPU::S_OR_B32:
5841 case AMDGPU::S_XOR_B32:
5842 return std::numeric_limits<uint32_t>::min();
5843 case AMDGPU::S_AND_B32:
5844 return std::numeric_limits<uint32_t>::max();
5845 case AMDGPU::V_MIN_F32_e64:
5846 case AMDGPU::V_MAX_F32_e64:
5848 case AMDGPU::V_CMP_LT_U64_e64:
5849 return std::numeric_limits<uint64_t>::max();
5850 case AMDGPU::V_CMP_LT_I64_e64:
5851 return std::numeric_limits<int64_t>::max();
5852 case AMDGPU::V_CMP_GT_U64_e64:
5853 return std::numeric_limits<uint64_t>::min();
5854 case AMDGPU::V_CMP_GT_I64_e64:
5855 return std::numeric_limits<int64_t>::min();
5856 case AMDGPU::V_MIN_F64_e64:
5857 case AMDGPU::V_MAX_F64_e64:
5858 case AMDGPU::V_MIN_NUM_F64_e64:
5859 case AMDGPU::V_MAX_NUM_F64_e64:
5860 return 0x7FF8000000000000;
5861 case AMDGPU::S_ADD_U64_PSEUDO:
5862 case AMDGPU::S_SUB_U64_PSEUDO:
5863 case AMDGPU::S_OR_B64:
5864 case AMDGPU::S_XOR_B64:
5865 return std::numeric_limits<uint64_t>::min();
5866 case AMDGPU::S_AND_B64:
5867 return std::numeric_limits<uint64_t>::max();
5868 case AMDGPU::V_ADD_F64_e64:
5869 case AMDGPU::V_ADD_F64_pseudo_e64:
5870 return 0x8000000000000000;
5877 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5878 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5879 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5880 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5881 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5882 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5883 Opc == AMDGPU::V_SUB_F32_e64;
5887 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5888 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5889 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5890 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5891 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5894static std::tuple<unsigned, unsigned>
5898 case AMDGPU::S_MIN_U32:
5899 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5901 case AMDGPU::S_MIN_I32:
5902 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5904 case AMDGPU::S_MAX_U32:
5905 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5907 case AMDGPU::S_MAX_I32:
5908 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5910 case AMDGPU::S_ADD_I32:
5911 case AMDGPU::S_SUB_I32:
5912 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5913 : AMDGPU::V_ADD_CO_U32_dpp;
5915 case AMDGPU::S_AND_B32:
5916 DPPOpc = AMDGPU::V_AND_B32_dpp;
5918 case AMDGPU::S_OR_B32:
5919 DPPOpc = AMDGPU::V_OR_B32_dpp;
5921 case AMDGPU::S_XOR_B32:
5922 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5924 case AMDGPU::V_ADD_F32_e64:
5925 case AMDGPU::V_SUB_F32_e64:
5926 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5928 case AMDGPU::V_MIN_F32_e64:
5929 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5931 case AMDGPU::V_MAX_F32_e64:
5932 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5934 case AMDGPU::V_CMP_LT_U64_e64:
5935 case AMDGPU::V_CMP_LT_I64_e64:
5936 case AMDGPU::V_CMP_GT_U64_e64:
5937 case AMDGPU::V_CMP_GT_I64_e64:
5938 case AMDGPU::S_ADD_U64_PSEUDO:
5939 case AMDGPU::S_SUB_U64_PSEUDO:
5940 case AMDGPU::S_AND_B64:
5941 case AMDGPU::S_OR_B64:
5942 case AMDGPU::S_XOR_B64:
5943 case AMDGPU::V_MIN_NUM_F64_e64:
5944 case AMDGPU::V_MIN_F64_e64:
5945 case AMDGPU::V_MAX_NUM_F64_e64:
5946 case AMDGPU::V_MAX_F64_e64:
5947 case AMDGPU::V_ADD_F64_pseudo_e64:
5948 case AMDGPU::V_ADD_F64_e64:
5949 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5954 unsigned ClampOpc =
Opc;
5955 if (
Opc == AMDGPU::V_SUB_F32_e64)
5956 ClampOpc = AMDGPU::V_ADD_F32_e64;
5957 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5958 if (
Opc == AMDGPU::S_SUB_I32)
5959 ClampOpc = AMDGPU::S_ADD_I32;
5960 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5961 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5962 else if (
Opc == AMDGPU::S_AND_B64)
5963 ClampOpc = AMDGPU::V_AND_B32_e64;
5964 else if (
Opc == AMDGPU::S_OR_B64)
5965 ClampOpc = AMDGPU::V_OR_B32_e64;
5966 else if (
Opc == AMDGPU::S_XOR_B64)
5967 ClampOpc = AMDGPU::V_XOR_B32_e64;
5969 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5971 return {DPPOpc, ClampOpc};
5974static std::pair<Register, Register>
5981 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5983 TII->buildExtractSubReg(
MI,
MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5985 TII->buildExtractSubReg(
MI,
MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5986 return {Op1L, Op1H};
6000 bool isSGPR =
TRI->isSGPRClass(
MRI.getRegClass(SrcReg));
6002 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
6003 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
6005 unsigned MIOpc =
MI.getOpcode();
6019 case AMDGPU::S_MIN_U32:
6020 case AMDGPU::S_MIN_I32:
6021 case AMDGPU::V_MIN_F32_e64:
6022 case AMDGPU::S_MAX_U32:
6023 case AMDGPU::S_MAX_I32:
6024 case AMDGPU::V_MAX_F32_e64:
6025 case AMDGPU::S_AND_B32:
6026 case AMDGPU::S_OR_B32: {
6032 case AMDGPU::V_CMP_LT_U64_e64:
6033 case AMDGPU::V_CMP_LT_I64_e64:
6034 case AMDGPU::V_CMP_GT_U64_e64:
6035 case AMDGPU::V_CMP_GT_I64_e64:
6036 case AMDGPU::V_MIN_F64_e64:
6037 case AMDGPU::V_MIN_NUM_F64_e64:
6038 case AMDGPU::V_MAX_F64_e64:
6039 case AMDGPU::V_MAX_NUM_F64_e64:
6040 case AMDGPU::S_AND_B64:
6041 case AMDGPU::S_OR_B64: {
6047 case AMDGPU::S_XOR_B32:
6048 case AMDGPU::S_XOR_B64:
6049 case AMDGPU::S_ADD_I32:
6050 case AMDGPU::S_ADD_U64_PSEUDO:
6051 case AMDGPU::V_ADD_F32_e64:
6052 case AMDGPU::V_ADD_F64_e64:
6053 case AMDGPU::V_ADD_F64_pseudo_e64:
6054 case AMDGPU::S_SUB_I32:
6055 case AMDGPU::S_SUB_U64_PSEUDO:
6056 case AMDGPU::V_SUB_F32_e64: {
6059 Register ExecMask =
MRI.createVirtualRegister(WaveMaskRegClass);
6061 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6063 bool IsWave32 = ST.isWave32();
6064 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6065 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6066 unsigned BitCountOpc =
6067 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6071 auto NewAccumulator =
6077 case AMDGPU::S_XOR_B32:
6078 case AMDGPU::S_XOR_B64: {
6084 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6086 .
addReg(NewAccumulator->getOperand(0).getReg())
6090 if (
TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6092 if (
Opc == AMDGPU::S_XOR_B32) {
6097 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6099 BuildRegSequence(BB,
MI, DstReg, ParityRegister, DstHi);
6103 if (
Opc == AMDGPU::S_XOR_B32) {
6109 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6111 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6113 MRI.getRegClass(SrcReg), ST,
MRI);
6120 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6124 case AMDGPU::S_SUB_I32: {
6125 Register NegatedVal =
MRI.createVirtualRegister(DstRegClass);
6133 .
addReg(NewAccumulator->getOperand(0).getReg());
6136 case AMDGPU::S_ADD_I32: {
6138 if (
TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6141 .
addReg(NewAccumulator->getOperand(0).getReg());
6146 .
addReg(NewAccumulator->getOperand(0).getReg());
6149 case AMDGPU::S_ADD_U64_PSEUDO:
6150 case AMDGPU::S_SUB_U64_PSEUDO: {
6151 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6152 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6154 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6156 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6158 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6159 Register AddReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6161 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6163 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6165 MRI.getRegClass(SrcReg), ST,
MRI);
6167 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO &&
6168 TII->getImmOrMaterializedImm(
MRI, SrcReg) == 1) {
6170 Register DstHi =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6172 BuildRegSequence(BB,
MI, DstReg,
6173 NewAccumulator->getOperand(0).getReg(), DstHi);
6176 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6179 .
addReg(NewAccumulator->getOperand(0).getReg())
6189 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6191 : NewAccumulator->getOperand(0).getReg();
6195 if (ST.hasScalarMulHiInsts()) {
6201 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6203 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6206 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6209 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6216 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6222 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6228 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6231 case AMDGPU::V_ADD_F32_e64:
6232 case AMDGPU::V_ADD_F64_e64:
6233 case AMDGPU::V_ADD_F64_pseudo_e64:
6234 case AMDGPU::V_SUB_F32_e64: {
6237 Register ActiveLanesVreg =
MRI.createVirtualRegister(VregRC);
6238 Register DstVreg =
MRI.createVirtualRegister(VregRC);
6241 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6242 : AMDGPU::V_CVT_F64_I32_e64),
6244 .
addReg(NewAccumulator->getOperand(0).getReg())
6249 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6250 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6253 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6255 ? AMDGPU::V_MUL_F64_pseudo_e64
6256 : AMDGPU::V_MUL_F64_e64;
6266 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6270 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6272 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6283 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6295 bool NeedsMovDPP = !is32BitOpc;
6300 bool IsWave32 = ST.isWave32();
6301 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6302 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6303 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6317 Register LoopIterator =
MRI.createVirtualRegister(WaveMaskRegClass);
6318 Register IdentityValReg =
MRI.createVirtualRegister(DstRegClass);
6319 Register AccumulatorReg =
MRI.createVirtualRegister(DstRegClass);
6320 Register ActiveBitsReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6321 Register NewActiveBitsReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6322 Register FF1Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6323 Register LaneValueReg =
MRI.createVirtualRegister(DstRegClass);
6329 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6333 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6334 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6343 I = ComputeLoop->begin();
6345 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6349 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6353 I = ComputeLoop->end();
6357 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6362 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6363 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6364 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6365 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6367 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6369 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6371 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6372 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6376 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6378 Register LaneValVgpr =
MRI.createVirtualRegister(SrcRegClass);
6379 Register VgprResultReg =
MRI.createVirtualRegister(SrcRegClass);
6380 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6382 OpDstReg = VgprResultReg;
6383 LaneValueReg = LaneValVgpr;
6386 if (hasSrc0Modifier)
6388 OpInstr.addReg(AccumulatorReg);
6389 if (hasSrc1Modifier)
6391 OpInstr.addReg(LaneValueReg);
6399 OpInstr.setOperandDead(3);
6400 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6401 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6407 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6409 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6411 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6413 MRI.getRegClass(SrcReg), ST,
MRI);
6415 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6419 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6423 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6424 LaneValueLoReg, LaneValueHiReg);
6426 case AMDGPU::S_OR_B64:
6427 case AMDGPU::S_AND_B64:
6428 case AMDGPU::S_XOR_B64: {
6431 .
addReg(LaneValue->getOperand(0).getReg())
6435 case AMDGPU::V_CMP_GT_I64_e64:
6436 case AMDGPU::V_CMP_GT_U64_e64:
6437 case AMDGPU::V_CMP_LT_I64_e64:
6438 case AMDGPU::V_CMP_LT_U64_e64: {
6439 Register LaneMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6441 MRI.createVirtualRegister(WaveMaskRegClass);
6443 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6445 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6446 Register AccumulatorVReg =
MRI.createVirtualRegister(VregClass);
6449 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6452 .
addReg(LaneValue->getOperand(0).getReg())
6453 .
addReg(AccumulatorVReg);
6455 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6456 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6460 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6461 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6462 .
addReg(LaneValue->getOperand(0).getReg())
6466 case AMDGPU::V_MIN_F64_e64:
6467 case AMDGPU::V_MIN_NUM_F64_e64:
6468 case AMDGPU::V_MAX_F64_e64:
6469 case AMDGPU::V_MAX_NUM_F64_e64:
6470 case AMDGPU::V_ADD_F64_e64:
6471 case AMDGPU::V_ADD_F64_pseudo_e64: {
6473 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6475 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6476 Register AccumulatorVReg =
MRI.createVirtualRegister(VregRC);
6477 Register DstVreg =
MRI.createVirtualRegister(VregRC);
6479 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6481 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6482 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6485 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6491 .
addReg(LaneValue->getOperand(0).getReg())
6498 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6503 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6505 ReadLaneLo.addReg(Op1L);
6506 ReadLaneHi.addReg(Op1H);
6508 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6511 case AMDGPU::S_ADD_U64_PSEUDO:
6512 case AMDGPU::S_SUB_U64_PSEUDO: {
6515 .
addReg(LaneValue->getOperand(0).getReg())
6524 unsigned BITSETOpc =
6525 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6526 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6532 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6536 if (!ST.hasScalarCompareEq64()) {
6538 Register LaneMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6539 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6541 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6544 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6545 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6547 SetSCCInstr.
addReg(NewActiveBitsReg);
6548 if (ST.hasScalarCompareEq64())
6551 SetSCCInstr.
addReg(NewActiveBitsReg);
6552 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6557 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6559 Register SrcWithIdentity =
MRI.createVirtualRegister(SrcRegClass);
6560 Register IdentityVGPR =
MRI.createVirtualRegister(SrcRegClass);
6561 Register IdentitySGPR =
MRI.createVirtualRegister(DstRegClass);
6562 Register DPPRowShr1 =
MRI.createVirtualRegister(SrcRegClass);
6563 Register DPPRowShr2 =
MRI.createVirtualRegister(SrcRegClass);
6564 Register DPPRowShr4 =
MRI.createVirtualRegister(SrcRegClass);
6565 Register DPPRowShr8 =
MRI.createVirtualRegister(SrcRegClass);
6566 Register RowBcast15 =
MRI.createVirtualRegister(SrcRegClass);
6567 Register ReducedValSGPR =
MRI.createVirtualRegister(DstRegClass);
6568 Register NegatedReducedVal =
MRI.createVirtualRegister(DstRegClass);
6569 Register RowBcast31 =
MRI.createVirtualRegister(SrcRegClass);
6570 Register UndefExec =
MRI.createVirtualRegister(WaveMaskRegClass);
6574 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6578 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6579 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6582 auto IdentityCopyInstr =
6585 unsigned DPPOpc, ClampOpc;
6601 if (isFPOp && !NeedsMovDPP)
6604 if (isFPOp && !NeedsMovDPP)
6608 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6617 bool isAddSub =
false,
6618 bool needsCarryIn =
false,
6620 unsigned InstrOpc = ClampOpc;
6621 Register CarryOutReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6623 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6624 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6629 ClampInstr.addReg(CarryOutReg,
6635 ClampInstr.addReg(Src0);
6638 ClampInstr.addReg(Src1);
6640 ClampInstr.addReg(CarryIn);
6641 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6642 ClampInstr.addImm(0);
6644 ClampInstr.addImm(0);
6645 LastBcastInstr = ClampInstr;
6650 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6651 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6652 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6653 Register ReturnReg =
MRI.createVirtualRegister(SrcRegClass);
6654 if (isAddSubOpc || isBitWiseOpc) {
6655 Register ResLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6656 Register ResHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6661 auto [Src0Lo, Src0Hi] =
6663 auto [Src1Lo, Src1Hi] =
6665 Register CarryReg = BuildClampInstr(
6666 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6667 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6668 isAddSubOpc, CarryReg);
6669 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6680 Register CmpMaskReg =
MRI.createVirtualRegister(WaveMaskRegClass);
6698 SrcWithIdentityInstr =
6699 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6702 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6704 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6706 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST,
MRI);
6707 auto [SrcReg0Sub0, SrcReg0Sub1] =
6710 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6712 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6713 SrcWithIdentityInstr =
6714 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6721 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6724 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6726 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6729 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6731 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6734 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6736 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6739 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6741 if (ST.hasDPPBroadcasts()) {
6744 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6753 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6759 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6762 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6764 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6765 Register SwizzledValue64 =
MRI.createVirtualRegister(SrcRegClass);
6780 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6783 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6785 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6788 FinalDPPResult = RowBcast15;
6790 if (ST.hasDPPBroadcasts()) {
6793 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6796 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6798 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6799 Register PermutedValue =
MRI.createVirtualRegister(SrcRegClass);
6801 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6803 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6805 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6807 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6809 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6813 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6819 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6827 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6832 .
addReg(ShiftedThreadID);
6837 .
addReg(PermuteByteOffset)
6842 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6844 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6847 auto [RowBcast15Lo, RowBcast15Hi] =
6851 .
addReg(PermuteByteOffset)
6856 .
addReg(PermuteByteOffset)
6859 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6863 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6865 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6867 FinalDPPResult = RowBcast31;
6869 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6870 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6871 Register NegatedValVGPR =
MRI.createVirtualRegister(SrcRegClass);
6880 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6883 FinalDPPResult = NegatedValVGPR;
6890 .
addImm(ST.getWavefrontSize() - 1);
6893 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6895 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6905 .
addImm(ST.getWavefrontSize() - 1);
6909 .
addImm(ST.getWavefrontSize() - 1);
6910 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6913 if (
Opc == AMDGPU::S_SUB_I32) {
6914 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6918 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6919 auto NegatedValInstr =
6928 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6934 MI.eraseFromParent();
6949 switch (
MI.getOpcode()) {
6950 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6952 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6954 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6956 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6958 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6960 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6963 ? AMDGPU::V_MIN_NUM_F64_e64
6964 : AMDGPU::V_MIN_F64_e64);
6965 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6967 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6969 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6971 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6973 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6975 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6978 ? AMDGPU::V_MAX_NUM_F64_e64
6979 : AMDGPU::V_MAX_F64_e64);
6980 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6982 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6984 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6986 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6989 ? AMDGPU::V_ADD_F64_pseudo_e64
6990 : AMDGPU::V_ADD_F64_e64);
6991 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6993 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6995 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6997 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7002 ? AMDGPU::V_ADD_F64_pseudo_e64
7003 : AMDGPU::V_ADD_F64_e64);
7004 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7006 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7008 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7010 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7012 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7014 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7016 case AMDGPU::S_UADDO_PSEUDO:
7017 case AMDGPU::S_USUBO_PSEUDO: {
7023 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7025 : AMDGPU::S_SUB_U32;
7033 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7036 MI.eraseFromParent();
7039 case AMDGPU::S_ADD_U64_PSEUDO:
7040 case AMDGPU::S_SUB_U64_PSEUDO: {
7043 case AMDGPU::V_ADD_U64_PSEUDO:
7044 case AMDGPU::V_SUB_U64_PSEUDO: {
7045 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7051 if (ST.hasAddSubU64Insts()) {
7053 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7054 : AMDGPU::V_SUB_U64_e64),
7059 TII->legalizeOperands(*
I);
7060 MI.eraseFromParent();
7064 if (IsAdd && ST.hasLshlAddU64Inst()) {
7070 TII->legalizeOperands(*
Add);
7071 MI.eraseFromParent();
7075 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7077 Register DestSub0 =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7078 Register DestSub1 =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7080 Register CarryReg =
MRI.createVirtualRegister(CarryRC);
7081 Register DeadCarryReg =
MRI.createVirtualRegister(CarryRC);
7084 ?
MRI.getRegClass(Src0.getReg())
7085 : &AMDGPU::VReg_64RegClass;
7087 ?
MRI.getRegClass(Src1.getReg())
7088 : &AMDGPU::VReg_64RegClass;
7091 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7093 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7096 MI,
MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7098 MI,
MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7101 MI,
MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7103 MI,
MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7106 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7113 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7127 TII->legalizeOperands(*LoHalf);
7128 TII->legalizeOperands(*HiHalf);
7129 MI.eraseFromParent();
7132 case AMDGPU::S_ADD_CO_PSEUDO:
7133 case AMDGPU::S_SUB_CO_PSEUDO: {
7143 if (Src0.isReg() &&
TRI->isVectorRegister(
MRI, Src0.getReg())) {
7144 Register RegOp0 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7145 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7147 Src0.setReg(RegOp0);
7149 if (Src1.isReg() &&
TRI->isVectorRegister(
MRI, Src1.getReg())) {
7150 Register RegOp1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7151 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7153 Src1.setReg(RegOp1);
7155 Register RegOp2 =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7156 if (
TRI->isVectorRegister(
MRI, Src2.getReg())) {
7157 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7159 Src2.setReg(RegOp2);
7162 if (ST.isWave64()) {
7163 if (ST.hasScalarCompareEq64()) {
7170 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7172 MII,
MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7174 MII,
MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7175 Register Src2_32 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7177 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7191 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7192 ? AMDGPU::S_ADDC_U32
7193 : AMDGPU::S_SUBB_U32;
7198 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7204 MI.eraseFromParent();
7207 case AMDGPU::SI_INIT_M0: {
7210 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7213 MI.eraseFromParent();
7216 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7219 TII->get(AMDGPU::S_CMP_EQ_U32))
7224 case AMDGPU::GET_GROUPSTATICSIZE: {
7228 .
add(
MI.getOperand(0))
7230 MI.eraseFromParent();
7233 case AMDGPU::GET_SHADERCYCLESHILO: {
7246 Register RegHi1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7248 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7249 Register RegLo1 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7251 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7252 Register RegHi2 =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7254 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7258 Register RegLo =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7263 .
add(
MI.getOperand(0))
7268 MI.eraseFromParent();
7271 case AMDGPU::SI_INDIRECT_SRC_V1:
7272 case AMDGPU::SI_INDIRECT_SRC_V2:
7273 case AMDGPU::SI_INDIRECT_SRC_V3:
7274 case AMDGPU::SI_INDIRECT_SRC_V4:
7275 case AMDGPU::SI_INDIRECT_SRC_V5:
7276 case AMDGPU::SI_INDIRECT_SRC_V6:
7277 case AMDGPU::SI_INDIRECT_SRC_V7:
7278 case AMDGPU::SI_INDIRECT_SRC_V8:
7279 case AMDGPU::SI_INDIRECT_SRC_V9:
7280 case AMDGPU::SI_INDIRECT_SRC_V10:
7281 case AMDGPU::SI_INDIRECT_SRC_V11:
7282 case AMDGPU::SI_INDIRECT_SRC_V12:
7283 case AMDGPU::SI_INDIRECT_SRC_V16:
7284 case AMDGPU::SI_INDIRECT_SRC_V32:
7286 case AMDGPU::SI_INDIRECT_DST_V1:
7287 case AMDGPU::SI_INDIRECT_DST_V2:
7288 case AMDGPU::SI_INDIRECT_DST_V3:
7289 case AMDGPU::SI_INDIRECT_DST_V4:
7290 case AMDGPU::SI_INDIRECT_DST_V5:
7291 case AMDGPU::SI_INDIRECT_DST_V6:
7292 case AMDGPU::SI_INDIRECT_DST_V7:
7293 case AMDGPU::SI_INDIRECT_DST_V8:
7294 case AMDGPU::SI_INDIRECT_DST_V9:
7295 case AMDGPU::SI_INDIRECT_DST_V10:
7296 case AMDGPU::SI_INDIRECT_DST_V11:
7297 case AMDGPU::SI_INDIRECT_DST_V12:
7298 case AMDGPU::SI_INDIRECT_DST_V16:
7299 case AMDGPU::SI_INDIRECT_DST_V32:
7301 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7302 case AMDGPU::SI_KILL_I1_PSEUDO:
7304 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7308 case AMDGPU::SI_BR_UNDEF: {
7310 .
add(
MI.getOperand(0));
7312 MI.eraseFromParent();
7315 case AMDGPU::ADJCALLSTACKUP:
7316 case AMDGPU::ADJCALLSTACKDOWN: {
7323 case AMDGPU::SI_CALL_ISEL: {
7324 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7335 MI.eraseFromParent();
7338 case AMDGPU::V_ADDC_U32_e32:
7339 case AMDGPU::V_SUBB_U32_e32:
7340 case AMDGPU::V_SUBBREV_U32_e32:
7343 TII->legalizeOperands(
MI);
7345 case AMDGPU::DS_GWS_INIT:
7346 case AMDGPU::DS_GWS_SEMA_BR:
7347 case AMDGPU::DS_GWS_BARRIER:
7348 case AMDGPU::DS_GWS_SEMA_V:
7349 case AMDGPU::DS_GWS_SEMA_P:
7350 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7358 case AMDGPU::S_SETREG_B32: {
7368 auto [ID,
Offset, Width] =
7374 const unsigned SetMask = WidthMask <<
Offset;
7377 unsigned SetDenormOp = 0;
7378 unsigned SetRoundOp = 0;
7386 SetRoundOp = AMDGPU::S_ROUND_MODE;
7387 SetDenormOp = AMDGPU::S_DENORM_MODE;
7389 SetRoundOp = AMDGPU::S_ROUND_MODE;
7391 SetDenormOp = AMDGPU::S_DENORM_MODE;
7394 if (SetRoundOp || SetDenormOp) {
7396 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7397 unsigned ImmVal = Def->getOperand(1).getImm();
7411 MI.eraseFromParent();
7420 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7424 case AMDGPU::S_INVERSE_BALLOT_U32:
7425 case AMDGPU::S_INVERSE_BALLOT_U64:
7428 MI.setDesc(
TII->get(AMDGPU::COPY));
7430 case AMDGPU::ENDPGM_TRAP: {
7432 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7452 MI.eraseFromParent();
7455 case AMDGPU::SIMULATED_TRAP: {
7456 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7458 TII->insertSimulatedTrap(
MRI, *BB,
MI,
MI.getDebugLoc());
7459 MI.eraseFromParent();
7462 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7463 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7469 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7470 Register OriginalExec = Setup->getOperand(0).getReg();
7471 MI.getOperand(0).setReg(OriginalExec);
7474 case AMDGPU::V_DOT2_F32_F16:
7475 case AMDGPU::V_DOT2_F32_BF16: {
7479 MRI.setSimpleHint(
MI.getOperand(0).getReg(),
MI.getOperand(6).getReg());
7482 case AMDGPU::SCHED_BARRIER:
7483 case AMDGPU::SCHED_GROUP_BARRIER:
7484 MI.getOperand(0).setImm(
MI.getOperand(0).getImm() &
7521 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7525 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7554 if (!Subtarget->hasMadMacF32Insts())
7555 return Subtarget->hasFastFMAF32();
7561 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7564 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7570 return Subtarget->has16BitInsts() &&
7588 F.getDenormalFPEnv());
7593 switch (Ty.getScalarSizeInBits()) {
7611 return Subtarget->hasMadMacF32Insts() &&
7614 return Subtarget->hasMadF16() &&
7625 if (Ty.getScalarSizeInBits() == 16)
7627 if (Ty.getScalarSizeInBits() == 32)
7642 F.getDenormalFPEnv());
7653 unsigned Opc =
Op.getOpcode();
7654 EVT VT =
Op.getValueType();
7666 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7667 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7680 [[maybe_unused]]
EVT VT =
Op.getValueType();
7682 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7683 VT == MVT::v16i32) &&
7684 "Unexpected ValueType.");
7693 unsigned Opc =
Op.getOpcode();
7694 EVT VT =
Op.getValueType();
7703 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7705 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7712 unsigned Opc =
Op.getOpcode();
7713 EVT VT =
Op.getValueType();
7730 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7732 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7738 switch (
Op.getOpcode()) {
7742 return LowerBRCOND(
Op, DAG);
7744 return LowerRETURNADDR(
Op, DAG);
7746 return LowerSPONENTRY(
Op, DAG);
7749 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7750 "Load should return a value and a chain");
7754 EVT VT =
Op.getValueType();
7756 return lowerFSQRTF32(
Op, DAG);
7758 return lowerFSQRTF64(
Op, DAG);
7763 return LowerTrig(
Op, DAG);
7765 return LowerSELECT(
Op, DAG);
7767 return LowerFDIV(
Op, DAG);
7769 return LowerFFREXP(
Op, DAG);
7771 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7773 return LowerSTORE(
Op, DAG);
7777 return LowerGlobalAddress(MFI,
Op, DAG);
7782 return LowerExternalSymbol(
Op, DAG);
7784 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7786 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7788 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7790 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7792 return LowerINTRINSIC_VOID(
Op, DAG);
7794 return lowerADDRSPACECAST(
Op, DAG);
7796 return lowerINSERT_SUBVECTOR(
Op, DAG);
7798 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7800 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7802 return lowerVECTOR_SHUFFLE(
Op, DAG);
7804 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7806 return lowerBUILD_VECTOR(
Op, DAG);
7809 return lowerFP_ROUND(
Op, DAG);
7811 return lowerTRAP(
Op, DAG);
7813 return lowerDEBUGTRAP(
Op, DAG);
7822 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7823 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7827 if (
Op.getValueType() == MVT::bf16) {
7857 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7860 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7863 return lowerFLDEXP(
Op, DAG);
7868 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7869 Op.getOperand(0).getValueType() == MVT::f32) {
7895 return lowerFCOPYSIGN(
Op, DAG);
7897 return lowerMUL(
Op, DAG);
7900 return lowerXMULO(
Op, DAG);
7903 return lowerXMUL_LOHI(
Op, DAG);
7924 return LowerINLINEASM(
Op, DAG);
7930static std::pair<SDValue, SDValue>
7960 EVT FittingLoadVT = LoadVT;
7992SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7995 bool IsIntrinsic)
const {
7998 bool IsTFE =
M->getNumValues() == 3;
7999 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8000 EVT LoadVT =
M->getValueType(0);
8002 EVT EquivLoadVT = LoadVT;
8019 SDVTList VTList = DAG.
getVTList(LoadDWordsVT, MVT::Other);
8021 Opcode,
DL, VTList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
8029 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
8033 M->getMemoryVT(),
M->getMemOperand());
8044 EVT LoadVT =
M->getValueType(0);
8053 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
8057 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
8058 bool IsTFE =
M->getNumValues() == 3;
8060 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8063 "TFE D16 format buffer load is not supported on this GPU",
8066 M->getOperand(0),
DL);
8069 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8070 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8071 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8072 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8073 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8074 : AMDGPUISD::BUFFER_LOAD;
8077 return adjustLoadValueType(
Opc, M, DAG,
Ops);
8081 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
8085 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
8086 M->getMemOperand(), DAG);
8090 SDVTList VTList = IsTFE ? DAG.
getVTList(CastVT, MVT::i32, MVT::Other)
8093 M->getMemOperand(), DAG);
8103 EVT VT =
N->getValueType(0);
8127 Exec = AMDGPU::EXEC_LO;
8129 Exec = AMDGPU::EXEC;
8146 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8148 EVT VT =
Op.getValueType();
8153 if (VT != MVT::i32) {
8161 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8170 EVT VT =
N->getValueType(0);
8172 unsigned IID =
N->getConstantOperandVal(0);
8173 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8174 IID == Intrinsic::amdgcn_permlanex16;
8175 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8176 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8177 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8178 IID == Intrinsic::amdgcn_permlane_up ||
8179 IID == Intrinsic::amdgcn_permlane_down ||
8180 IID == Intrinsic::amdgcn_permlane_xor;
8185 unsigned SplitSize = 32;
8186 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8187 ST->hasDPALU_DPP() &&
8195 case Intrinsic::amdgcn_permlane16:
8196 case Intrinsic::amdgcn_permlanex16:
8197 case Intrinsic::amdgcn_update_dpp:
8202 case Intrinsic::amdgcn_writelane:
8203 case Intrinsic::amdgcn_permlane_bcast:
8204 case Intrinsic::amdgcn_permlane_up:
8205 case Intrinsic::amdgcn_permlane_down:
8206 case Intrinsic::amdgcn_permlane_xor:
8209 case Intrinsic::amdgcn_readlane:
8210 case Intrinsic::amdgcn_set_inactive:
8211 case Intrinsic::amdgcn_set_inactive_chain_arg:
8212 case Intrinsic::amdgcn_mov_dpp8:
8215 case Intrinsic::amdgcn_readfirstlane:
8216 case Intrinsic::amdgcn_permlane64:
8226 if (
SDNode *GL =
N->getGluedNode()) {
8228 GL = GL->getOperand(0).getNode();
8238 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8239 IID == Intrinsic::amdgcn_mov_dpp8 ||
8240 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8241 IsPermlaneShuffle) {
8242 Src1 =
N->getOperand(2);
8243 if (IID == Intrinsic::amdgcn_writelane ||
8244 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8246 Src2 =
N->getOperand(3);
8249 if (ValSize == SplitSize) {
8259 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8264 if (IID == Intrinsic::amdgcn_writelane) {
8269 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8271 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8274 if (ValSize % SplitSize != 0)
8278 EVT VT =
N->getValueType(0);
8282 unsigned NumOperands =
N->getNumOperands();
8284 SDNode *GL =
N->getGluedNode();
8289 for (
unsigned i = 0; i != NE; ++i) {
8290 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8292 SDValue Operand =
N->getOperand(j);
8322 if (SplitSize == 32) {
8324 return unrollLaneOp(LaneOp.
getNode());
8330 unsigned SubVecNumElt =
8334 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8335 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8339 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8345 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8346 }
else if (IID == Intrinsic::amdgcn_writelane) {
8350 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8352 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8355 EltIdx += SubVecNumElt;
8369 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8372 if (IID == Intrinsic::amdgcn_writelane)
8375 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8382 EVT VT =
N->getValueType(0);
8400 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8409 if (
TLI.getSubtarget()->supportsWaveWideBPermute()) {
8410 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8411 {ShiftedIndex, ValueI32});
8421 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8422 {ValueI32, PoisonVal});
8423 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8424 {ShiftedIndex, PoisonVal});
8427 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8430 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8431 {WWMIndex, WWMValue});
8432 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8433 MVT::i32, {WWMIndex, Swapped});
8435 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8443 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8451 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8461 switch (
N->getOpcode()) {
8478 unsigned IID =
N->getConstantOperandVal(0);
8480 case Intrinsic::amdgcn_wave_reduce_min:
8481 case Intrinsic::amdgcn_wave_reduce_umin:
8482 case Intrinsic::amdgcn_wave_reduce_max:
8483 case Intrinsic::amdgcn_wave_reduce_umax:
8484 case Intrinsic::amdgcn_wave_reduce_add:
8485 case Intrinsic::amdgcn_wave_reduce_sub:
8486 case Intrinsic::amdgcn_wave_reduce_and:
8487 case Intrinsic::amdgcn_wave_reduce_or:
8488 case Intrinsic::amdgcn_wave_reduce_xor: {
8489 EVT VT =
N->getValueType(0);
8493 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8494 IID == Intrinsic::amdgcn_wave_reduce_max ||
8495 IID == Intrinsic::amdgcn_wave_reduce_add ||
8496 IID == Intrinsic::amdgcn_wave_reduce_sub;
8500 N->getOperand(0), ExtSrc,
N->getOperand(2));
8504 case Intrinsic::amdgcn_make_buffer_rsrc:
8505 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8507 case Intrinsic::amdgcn_cvt_pkrtz: {
8512 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8516 case Intrinsic::amdgcn_cvt_pknorm_i16:
8517 case Intrinsic::amdgcn_cvt_pknorm_u16:
8518 case Intrinsic::amdgcn_cvt_pk_i16:
8519 case Intrinsic::amdgcn_cvt_pk_u16: {
8525 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8526 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8527 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8528 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8529 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8530 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8532 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8534 EVT VT =
N->getValueType(0);
8543 case Intrinsic::amdgcn_s_buffer_load: {
8545 EVT VT =
Op.getValueType();
8547 Op.getOperand(1),
Op.getOperand(2),
8548 Op.getOperand(3), DAG));
8551 case Intrinsic::amdgcn_dead: {
8552 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8560 if (
N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8561 N->getValueType(0).isSimple() &&
8562 SBufferLoadDiagnosticVTs[
N->getSimpleValueType(0).SimpleTy])
8567 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8568 Results.push_back(Res.getOperand(
I));
8571 for (
unsigned I = 0;
I <
N->getNumValues(); ++
I)
8572 Results.push_back(Res.getValue(
I));
8581 EVT VT =
N->getValueType(0);
8586 EVT SelectVT = NewVT;
8587 if (NewVT.
bitsLT(MVT::i32)) {
8590 SelectVT = MVT::i32;
8596 if (NewVT != SelectVT)
8602 if (
N->getValueType(0) != MVT::v2f16)
8614 if (
N->getValueType(0) != MVT::v2f16)
8626 if (
N->getValueType(0) != MVT::f16)
8641 if (U.get() !=
Value)
8644 if (U.getUser()->getOpcode() == Opcode)
8650unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8653 case Intrinsic::amdgcn_if:
8654 return AMDGPUISD::IF;
8655 case Intrinsic::amdgcn_else:
8656 return AMDGPUISD::ELSE;
8657 case Intrinsic::amdgcn_loop:
8658 return AMDGPUISD::LOOP;
8659 case Intrinsic::amdgcn_end_cf:
8679 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8703 assert(GVar->isDeclaration() &&
8704 "AS 3 & 13 GVs should be declaration here "
8705 "when object linking is enabled");
8720 SDNode *Intr = BRCOND.getOperand(1).getNode();
8737 Intr =
LHS.getNode();
8745 assert(BR &&
"brcond missing unconditional branch user");
8750 unsigned CFNode = isCFIntrinsic(Intr);
8768 Ops.push_back(Target);
8791 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8810 MVT VT =
Op.getSimpleValueType();
8813 if (
Op.getConstantOperandVal(0) != 0)
8817 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8819 if (
Info->isEntryFunction())
8836 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8850 return Op.getValueType().bitsLE(VT)
8858 EVT DstVT =
Op.getValueType();
8865 unsigned Opc =
Op.getOpcode();
8876 bool IsStrict =
Op->isStrictFPOpcode();
8877 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8878 EVT SrcVT = Src.getValueType();
8879 EVT DstVT =
Op.getValueType();
8882 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8885 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8892 if (DstVT == MVT::f16) {
8897 if (!Subtarget->has16BitInsts()) {
8902 if (
Op->getFlags().hasApproximateFuncs()) {
8913 "custom lower FP_ROUND for f16 or bf16");
8914 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8931 EVT VT =
Op.getValueType();
8933 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8934 bool IsIEEEMode =
Info->getMode().IEEE;
8940 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8943 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8944 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8945 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8946 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8952SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8954 EVT VT =
Op.getValueType();
8956 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8957 bool IsIEEEMode =
Info->getMode().IEEE;
8959 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8962 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8963 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8964 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8965 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8972 EVT VT =
Op.getValueType();
8976 EVT ExpVT =
Exp.getValueType();
8977 if (ExpVT == MVT::i16)
8998 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
9005 switch (
Op->getOpcode()) {
9038SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
9039 DAGCombinerInfo &DCI)
const {
9040 EVT OpTy =
Op.getValueType();
9041 SelectionDAG &DAG = DCI.DAG;
9058 DAGCombinerInfo &DCI)
const {
9059 const unsigned Opc =
Op.getOpcode();
9068 :
Op->getOperand(0).getValueType();
9069 auto &DAG = DCI.DAG;
9072 if (DCI.isBeforeLegalizeOps() ||
9080 LHS =
Op->getOperand(1);
9081 RHS =
Op->getOperand(2);
9083 LHS =
Op->getOperand(0);
9084 RHS =
Op->getOperand(1);
9126 EVT SignVT =
Sign.getValueType();
9128 if (MagVT == SignVT)
9149 EVT VT =
Op.getValueType();
9155 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9182 if (
Op->isDivergent())
9195 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9197 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9200 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9202 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9208 EVT VT =
Op.getValueType();
9215 const APInt &
C = RHSC->getAPIntValue();
9217 if (
C.isPowerOf2()) {
9219 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9246 if (
Op->isDivergent()) {
9250 if (Subtarget->hasSMulHi()) {
9261 if (!Subtarget->hasTrapHandler() ||
9263 return lowerTrapEndpgm(
Op, DAG);
9265 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9266 : lowerTrapHsaQueuePtr(
Op, DAG);
9272 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9276SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9278 ImplicitParameter Param)
const {
9282 MachinePointerInfo PtrInfo =
9299 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9302 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9305 if (UserSGPR == AMDGPU::NoRegister) {
9322 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9331 if (Subtarget->hasPrivEnabledTrap2NopBug())
9332 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9336 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9344 if (!Subtarget->hasTrapHandler() ||
9348 "debugtrap handler not supported",
9356 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9366 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9367 SmallSet<Register, 8> SGPRInputRegs;
9369 unsigned NumVals = 0;
9372 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9373 NumVals =
Flags.getNumOperandRegisters();
9377 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9378 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9380 for (
unsigned J = 0; J < NumVals; ++J) {
9382 if (
const RegisterSDNode *RegNode =
9391 if (SGPRInputRegs.
empty())
9396 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9408 ReadFirstLaneID, SrcVal);
9412 if (
N->getNumOperands() > 3)
9413 Ops.push_back(
N->getOperand(3));
9419 SDNode *
Next =
nullptr;
9420 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9421 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9422 Next =
N->getOperand(
I).getNode();
9432SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9434 unsigned BaseAS = AS;
9439 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9449SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9453 if (Subtarget->hasApertureRegs()) {
9454 const unsigned ApertureRegNo =
9455 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9456 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9457 !Subtarget->hasGloballyAddressableScratch()) &&
9458 "Cannot use src_private_base with globally addressable scratch!");
9478 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9482 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9484 if (UserSGPR == AMDGPU::NoRegister) {
9495 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9529 const AMDGPUTargetMachine &TM =
9533 unsigned SrcAS = ASC->getSrcAddressSpace();
9534 SDValue Src = ASC->getOperand(0);
9535 unsigned DestAS = ASC->getDestAddressSpace();
9536 bool IsNonNull = ASC->getFlags().hasNonNull();
9547 Subtarget->hasGloballyAddressableScratch()) {
9552 AMDGPU::S_MOV_B32, SL, MVT::i32,
9553 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9576 Subtarget->hasGloballyAddressableScratch()) {
9585 if (Subtarget->isWave64())
9591 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9599 AMDGPU::S_MOV_B64, SL, MVT::i64,
9600 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9602 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9604 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9625 Op.getValueType() == MVT::i64) {
9626 const SIMachineFunctionInfo *
Info =
9628 if (
Info->get32BitAddressHighBits() == 0)
9637 Src.getValueType() == MVT::i64)
9660 unsigned IdxVal =
Idx->getAsZExtVal();
9665 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9670 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9672 MVT::i32, InsNumElts / 2);
9677 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9679 if (InsNumElts == 2) {
9692 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9715 if (NumElts == 4 && EltSize == 16 && KIdx) {
9726 unsigned Idx = KIdx->getZExtValue();
9727 bool InsertLo =
Idx < 2;
9731 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9737 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9751 unsigned PieceSize = std::min(VecSize, 64u);
9752 unsigned NumPieces =
VecSize / PieceSize;
9753 unsigned EltsPerPiece = PieceSize / EltSize;
9788 InsertIntoPiece(DAG.
getBitcast(IntVT, Vec), BFM));
9800 for (
unsigned I = 0;
I != NumPieces; ++
I) {
9806 Pieces.
push_back(InsertIntoPiece(Piece, Mask));
9816 EVT ResultVT =
Op.getValueType();
9829 if (
SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9832 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9836 if (VecSize == 128) {
9844 }
else if (VecSize == 256) {
9847 for (
unsigned P = 0;
P < 4; ++
P) {
9853 Parts[0], Parts[1]));
9855 Parts[2], Parts[3]));
9861 for (
unsigned P = 0;
P < 8; ++
P) {
9868 Parts[0], Parts[1], Parts[2], Parts[3]));
9871 Parts[4], Parts[5], Parts[6], Parts[7]));
9874 EVT IdxVT =
Idx.getValueType();
9891 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9906 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9916 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9921 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9922 !(Mask[Elt + 1] & 1);
9928 EVT ResultVT =
Op.getValueType();
9931 const int NewSrcNumElts = 2;
9933 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9949 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9971 if (ShouldUseConsecutiveExtract &&
9974 int VecIdx =
Idx < SrcNumElts ? 0 : 1;
9975 int EltIdx =
Idx < SrcNumElts ?
Idx :
Idx - SrcNumElts;
9987 if (Idx0 >= SrcNumElts) {
9992 if (Idx1 >= SrcNumElts) {
9997 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9998 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
10006 int NewMaskIdx0 = Idx0 - AlignedIdx0;
10007 int NewMaskIdx1 = Idx1 - AlignedIdx1;
10012 if (SubVec0 != SubVec1) {
10013 NewMaskIdx1 += NewSrcNumElts;
10020 {NewMaskIdx0, NewMaskIdx1});
10025 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10026 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10027 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10028 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10047 EVT ResultVT =
Op.getValueType();
10063 EVT VT =
Op.getValueType();
10065 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10066 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10072 if (
Hi.isUndef()) {
10102 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10128 if (!Subtarget->isAmdHsaOS())
10171 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10180 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10188 EVT PtrVT =
Op.getValueType();
10190 const GlobalValue *GV = GSD->
getGlobal();
10203 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10224 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10227 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10228 if (Subtarget->has64BitLiterals()) {
10237 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10241 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10259 MachinePointerInfo PtrInfo =
10272 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10294 unsigned Offset)
const {
10296 SDValue Param = lowerKernargMemParameter(
10307 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10315 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10323 unsigned NumElts = Elts.
size();
10325 if (NumElts <= 12) {
10329 Type = MVT::v16f32;
10334 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10340 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10349 SDValue Src,
int ExtraElts) {
10350 EVT SrcVT = Src.getValueType();
10360 while (ExtraElts--)
10371 bool Unpacked,
bool IsD16,
int DMaskPop,
10372 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10376 EVT ReqRetVT = ResultTypes[0];
10378 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10379 ? (ReqRetNumElts + 1) / 2
10382 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10385 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10388 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10393 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10397 SDValue(Result, 0), ZeroIdx);
10400 SDValue(Result, 0), ZeroIdx);
10404 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10406 NumDataDwords - MaskPopDwords);
10411 EVT LegalReqRetVT = ReqRetVT;
10413 if (!
Data.getValueType().isInteger())
10415 Data.getValueType().changeTypeToInteger(),
Data);
10436 if (Result->getNumValues() == 1)
10443 SDValue *LWE,
bool &IsTexFail) {
10463 unsigned DimIdx,
unsigned EndIdx,
10464 unsigned NumGradients) {
10466 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10474 if (((
I + 1) >= EndIdx) ||
10475 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10476 I == DimIdx + NumGradients - 1))) {
10508 !
Op.getNode()->hasAnyUseOfValue(0))
10510 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10521 ResultTypes.erase(&ResultTypes[0]);
10523 bool IsD16 =
false;
10524 bool IsG16 =
false;
10525 bool IsA16 =
false;
10527 int NumVDataDwords = 0;
10528 bool AdjustRetType =
false;
10529 bool IsAtomicPacked16Bit =
false;
10532 const unsigned ArgOffset = WithChain ? 2 : 1;
10535 unsigned DMaskLanes = 0;
10537 if (BaseOpcode->
Atomic) {
10538 VData =
Op.getOperand(2);
10540 IsAtomicPacked16Bit =
10541 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10542 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10543 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10544 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10549 "unsupported image atomic data type");
10561 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10563 DMask = Is64Bit ? 0xf : 0x3;
10564 NumVDataDwords = Is64Bit ? 4 : 2;
10566 DMask = Is64Bit ? 0x3 : 0x1;
10567 NumVDataDwords = Is64Bit ? 2 : 1;
10570 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10573 if (BaseOpcode->
Store) {
10574 VData =
Op.getOperand(2);
10578 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10581 "unsupported image store data type");
10583 if (StoreScalarVT == MVT::f16) {
10584 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10588 VData = handleD16VData(VData, DAG,
true);
10591 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10592 }
else if (!BaseOpcode->
NoReturn) {
10597 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10600 "unsupported image load data type");
10602 if (LoadScalarVT == MVT::f16) {
10603 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10611 (!LoadVT.
isVector() && DMaskLanes > 1))
10617 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10618 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10619 NumVDataDwords = (DMaskLanes + 1) / 2;
10621 NumVDataDwords = DMaskLanes;
10623 AdjustRetType =
true;
10627 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10634 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10635 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10637 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10639 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10640 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10644 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10650 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10654 "Bias needs to be converted to 16 bit in A16 mode");
10659 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10663 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10664 "require 16 bit args for both gradients and addresses");
10669 if (!
ST->hasA16()) {
10670 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10671 "support 16 bit addresses\n");
10681 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10683 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10685 IntrOpcode = G16MappingInfo->
G16;
10708 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10726 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10727 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10728 const bool UseNSA =
ST->hasNSAEncoding() &&
10729 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10730 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10731 const bool UsePartialNSA =
10732 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10735 if (UsePartialNSA) {
10737 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10738 }
else if (!UseNSA) {
10749 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10757 bool IsTexFail =
false;
10758 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10767 NumVDataDwords = 1;
10769 NumVDataDwords += 1;
10770 AdjustRetType =
true;
10775 if (AdjustRetType) {
10778 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10787 MVT::i32, NumVDataDwords)
10790 ResultTypes[0] = NewVT;
10791 if (ResultTypes.size() == 3) {
10795 ResultTypes.erase(&ResultTypes[1]);
10809 Ops.push_back(VData);
10810 if (UsePartialNSA) {
10812 Ops.push_back(VAddr);
10816 Ops.push_back(VAddr);
10819 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10820 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10822 Ops.push_back(Rsrc);
10823 bool IsSampIndexed =
false;
10827 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10828 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10830 Ops.push_back(Samp);
10835 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10836 Ops.push_back(Unorm);
10838 Ops.push_back(IsA16 &&
10839 ST->hasFeature(AMDGPU::FeatureR128A16)
10845 if (!Subtarget->hasGFX90AInsts())
10846 Ops.push_back(TFE);
10850 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10853 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10854 Ops.push_back(LWE);
10860 Ops.push_back(
Op.getOperand(0));
10862 int NumVAddrDwords =
10869 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10870 }
else if (IsGFX12Plus) {
10872 NumVDataDwords, NumVAddrDwords);
10873 }
else if (IsGFX11Plus) {
10875 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10876 : AMDGPU::MIMGEncGfx11Default,
10877 NumVDataDwords, NumVAddrDwords);
10878 }
else if (IsGFX10Plus) {
10880 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10881 : AMDGPU::MIMGEncGfx10Default,
10882 NumVDataDwords, NumVAddrDwords);
10884 if (Subtarget->hasGFX90AInsts()) {
10886 NumVDataDwords, NumVAddrDwords);
10887 if (Opcode == -1) {
10889 DAG,
Op, OrigResultTypes,
DL,
10890 "requested image instruction is not supported on this GPU");
10893 if (Opcode == -1 &&
10896 NumVDataDwords, NumVAddrDwords);
10899 NumVDataDwords, NumVAddrDwords);
10906 MachineMemOperand *MemRef = MemOp->getMemOperand();
10925 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10926 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10935 bool HasChainResult = MMO !=
nullptr;
10939 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10940 Subtarget->hasScalarSubwordLoads();
10943 MF.
getFunction(),
"unsupported s_buffer_load result type",
10944 DL.getDebugLoc()));
10945 EVT ResultTypes[] = {VT, MVT::Other};
10947 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain,
DL);
10950 if (!HasChainResult) {
10962 if (!
Offset->isDivergent()) {
10970 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) ->
SDValue {
10972 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10975 if (HasChainResult)
10979 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10980 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10982 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10983 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10988 !Subtarget->hasScalarDwordx3Loads()) {
10992 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10997 if (HasChainResult)
11019 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11020 Subtarget->hasScalarSubwordLoads()) {
11024 if (HasChainResult)
11030 unsigned NumLoads = 1;
11036 if (NumElts == 8 || NumElts == 16) {
11037 NumLoads = NumElts / 4;
11041 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
11046 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
11050 for (
unsigned i = 0; i < NumLoads; ++i) {
11053 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
11054 LoadVT, LoadMMO, DAG));
11057 if (NumElts == 8 || NumElts == 16) {
11059 if (HasChainResult) {
11074 if (!Subtarget->hasArchitectedSGPRs())
11079 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11086 unsigned Width)
const {
11088 using namespace AMDGPU::Hwreg;
11090 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11130 EVT DstVT =
Op.getValueType();
11132 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11133 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11137 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11139 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11152SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11161 const bool HasE5M3ConversionInsts =
11162 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11163 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11167 EVT DstVT =
Op.getValueType();
11171 !Subtarget->hasFP8F16ConversionInsts())
11181 "only the v2f32 vector result is custom lowered");
11187 auto ConvertByte = [&](
unsigned ByteSel) {
11188 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11193 return ConvertByte(0);
11194 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11199 if (Src.getValueType() != MVT::i32) {
11209 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11210 return lowerFromFP8(
Op, IsBF8, DAG);
11218 EVT ResVT =
Op.getValueType();
11219 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11220 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11221 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11223 "only the v2i8 vector result is custom lowered");
11227 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11232 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11233 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11234 : AMDGPUISD::CVT_PK_FP8_F32;
11242 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11254SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11263 const bool HasE5M3ConversionInsts =
11264 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11265 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11275 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11278 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11281 if (SrcEltVT == MVT::f32)
11282 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11283 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11284 Subtarget->hasF16FP8ConversionInsts()) {
11287 if (!
Op.getValueType().isVector())
11289 return lowerToFP8(
Op, IsBF8,
false, DAG);
11297 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11299 EVT VT =
Op.getValueType();
11301 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11305 switch (IntrinsicID) {
11306 case Intrinsic::amdgcn_wave_reduce_min:
11307 case Intrinsic::amdgcn_wave_reduce_umin:
11308 case Intrinsic::amdgcn_wave_reduce_fmin:
11309 case Intrinsic::amdgcn_wave_reduce_max:
11310 case Intrinsic::amdgcn_wave_reduce_umax:
11311 case Intrinsic::amdgcn_wave_reduce_fmax:
11312 case Intrinsic::amdgcn_wave_reduce_add:
11313 case Intrinsic::amdgcn_wave_reduce_fadd:
11314 case Intrinsic::amdgcn_wave_reduce_sub:
11315 case Intrinsic::amdgcn_wave_reduce_fsub:
11316 case Intrinsic::amdgcn_wave_reduce_and:
11317 case Intrinsic::amdgcn_wave_reduce_or:
11318 case Intrinsic::amdgcn_wave_reduce_xor: {
11319 EVT SrcVT =
Op.getOperand(1).getValueType();
11322 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11323 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11324 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11325 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11329 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11330 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11334 Op.getOperand(0), ExtendedSrc, Strategy);
11343 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11344 if (!MFI->getUserSGPRInfo().hasImplicitBufferPtr()) {
11345 const char *
Error =
11346 Subtarget->hasArchitectedFlatScratch()
11347 ?
"intrinsic not supported on subtarget"
11348 : !Subtarget->isMesa3DOS()
11349 ?
"intrinsic not supported for OS"
11350 :
"intrinsic not supported for calling convention";
11356 return getPreloadedValue(DAG, *MFI, VT,
11359 case Intrinsic::amdgcn_dispatch_ptr:
11360 case Intrinsic::amdgcn_queue_ptr: {
11361 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11363 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11364 DL.getDebugLoc()));
11368 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11371 return getPreloadedValue(DAG, *MFI, VT, RegID);
11373 case Intrinsic::amdgcn_implicitarg_ptr: {
11375 return getImplicitArgPtr(DAG,
DL);
11376 return getPreloadedValue(DAG, *MFI, VT,
11379 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11385 return getPreloadedValue(DAG, *MFI, VT,
11388 case Intrinsic::amdgcn_dispatch_id: {
11391 case Intrinsic::amdgcn_rcp:
11392 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11393 case Intrinsic::amdgcn_rsq:
11394 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11395 case Intrinsic::amdgcn_rsq_legacy:
11399 case Intrinsic::amdgcn_rcp_legacy:
11402 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11403 case Intrinsic::amdgcn_fma_legacy:
11404 case Intrinsic::amdgcn_sudot4:
11405 case Intrinsic::amdgcn_sudot8:
11406 case Intrinsic::amdgcn_tanh:
11408 case Intrinsic::amdgcn_rsq_clamp: {
11410 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11422 case Intrinsic::r600_read_ngroups_x:
11423 if (Subtarget->isAmdHsaOS())
11426 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11429 case Intrinsic::r600_read_ngroups_y:
11430 if (Subtarget->isAmdHsaOS())
11433 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11436 case Intrinsic::r600_read_ngroups_z:
11437 if (Subtarget->isAmdHsaOS())
11440 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11443 case Intrinsic::r600_read_local_size_x:
11444 if (Subtarget->isAmdHsaOS())
11447 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11449 case Intrinsic::r600_read_local_size_y:
11450 if (Subtarget->isAmdHsaOS())
11453 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11455 case Intrinsic::r600_read_local_size_z:
11456 if (Subtarget->isAmdHsaOS())
11459 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11461 case Intrinsic::amdgcn_workgroup_id_x:
11462 return lowerWorkGroupId(DAG, *MFI, VT,
11466 case Intrinsic::amdgcn_workgroup_id_y:
11467 return lowerWorkGroupId(DAG, *MFI, VT,
11471 case Intrinsic::amdgcn_workgroup_id_z:
11472 return lowerWorkGroupId(DAG, *MFI, VT,
11476 case Intrinsic::amdgcn_cluster_id_x:
11477 return Subtarget->hasClusters()
11478 ? getPreloadedValue(DAG, *MFI, VT,
11480 : DAG.getPOISON(VT);
11481 case Intrinsic::amdgcn_cluster_id_y:
11482 return Subtarget->hasClusters()
11483 ? getPreloadedValue(DAG, *MFI, VT,
11486 case Intrinsic::amdgcn_cluster_id_z:
11487 return Subtarget->hasClusters()
11488 ? getPreloadedValue(DAG, *MFI, VT,
11491 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11492 return Subtarget->hasClusters()
11493 ? getPreloadedValue(
11497 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11498 return Subtarget->hasClusters()
11499 ? getPreloadedValue(
11503 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11504 return Subtarget->hasClusters()
11505 ? getPreloadedValue(
11509 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11510 return Subtarget->hasClusters()
11513 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11514 return Subtarget->hasClusters()
11515 ? getPreloadedValue(
11519 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11520 return Subtarget->hasClusters()
11521 ? getPreloadedValue(
11525 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11526 return Subtarget->hasClusters()
11527 ? getPreloadedValue(
11531 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11532 return Subtarget->hasClusters()
11533 ? getPreloadedValue(
11537 case Intrinsic::amdgcn_wave_id:
11538 return lowerWaveID(DAG,
Op);
11539 case Intrinsic::amdgcn_lds_kernel_id: {
11541 return getLDSKernelId(DAG,
DL);
11542 return getPreloadedValue(DAG, *MFI, VT,
11545 case Intrinsic::amdgcn_workitem_id_x:
11546 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11547 case Intrinsic::amdgcn_workitem_id_y:
11548 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11549 case Intrinsic::amdgcn_workitem_id_z:
11550 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11551 case Intrinsic::amdgcn_wavefrontsize:
11553 SDLoc(
Op), MVT::i32);
11554 case Intrinsic::amdgcn_s_buffer_load: {
11555 unsigned CPol =
Op.getConstantOperandVal(3);
11563 Op.getOperand(2),
Op.getOperand(3), DAG);
11565 case Intrinsic::amdgcn_fdiv_fast:
11566 return lowerFDIV_FAST(
Op, DAG);
11567 case Intrinsic::amdgcn_sin:
11568 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11570 case Intrinsic::amdgcn_cos:
11571 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11573 case Intrinsic::amdgcn_mul_u24:
11574 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11576 case Intrinsic::amdgcn_mul_i24:
11577 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11580 case Intrinsic::amdgcn_log_clamp: {
11586 case Intrinsic::amdgcn_fract:
11587 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11589 case Intrinsic::amdgcn_class: {
11591 EVT SrcVT = Src.getValueType();
11592 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11593 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11597 "llvm.amdgcn.class only supports f16, f32, and f64",
11598 DL.getDebugLoc()));
11601 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11603 case Intrinsic::amdgcn_div_fmas:
11604 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11605 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11607 case Intrinsic::amdgcn_div_fixup:
11608 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11609 Op.getOperand(2),
Op.getOperand(3));
11611 case Intrinsic::amdgcn_div_scale: {
11617 SDValue Denominator =
Op.getOperand(2);
11626 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11627 Denominator, Numerator);
11629 case Intrinsic::amdgcn_ballot:
11631 case Intrinsic::amdgcn_fmed3:
11632 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11633 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11634 case Intrinsic::amdgcn_fdot2:
11635 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11636 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11637 case Intrinsic::amdgcn_fmul_legacy:
11638 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11640 case Intrinsic::amdgcn_sbfe:
11641 case Intrinsic::amdgcn_ubfe:
11643 case Intrinsic::amdgcn_cvt_pkrtz:
11644 case Intrinsic::amdgcn_cvt_pknorm_i16:
11645 case Intrinsic::amdgcn_cvt_pknorm_u16:
11646 case Intrinsic::amdgcn_cvt_pk_i16:
11647 case Intrinsic::amdgcn_cvt_pk_u16: {
11649 EVT VT =
Op.getValueType();
11652 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11653 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11654 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11655 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11656 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11657 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11658 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11659 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11661 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11664 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11667 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11670 case Intrinsic::amdgcn_fmad_ftz:
11671 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11672 Op.getOperand(2),
Op.getOperand(3));
11674 case Intrinsic::amdgcn_if_break:
11676 Op->getOperand(1),
Op->getOperand(2)),
11679 case Intrinsic::amdgcn_groupstaticsize: {
11685 const GlobalValue *GV =
11691 case Intrinsic::amdgcn_is_shared:
11692 case Intrinsic::amdgcn_is_private: {
11699 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11703 Subtarget->hasGloballyAddressableScratch()) {
11706 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11707 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11716 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11719 case Intrinsic::amdgcn_perm:
11720 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11721 Op.getOperand(2),
Op.getOperand(3));
11722 case Intrinsic::amdgcn_reloc_constant: {
11732 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11733 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11734 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11735 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11736 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11737 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11738 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11739 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11740 if (
Op.getOperand(4).getValueType() == MVT::i32)
11746 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11747 Op.getOperand(3), IndexKeyi32);
11749 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11750 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11751 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11752 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11753 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11754 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11755 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11756 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11757 if (
Op.getOperand(4).getValueType() == MVT::i64)
11762 Op.getOperand(4).getValueType() == MVT::v2i32
11766 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11767 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11768 Op.getOperand(6)});
11770 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11771 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11772 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11773 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11774 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11775 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11776 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11779 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11784 Op.getOperand(6).getValueType().isVector()
11788 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11789 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11790 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11791 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11792 Args.push_back(
Op.getOperand(9));
11795 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11796 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11797 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11798 if (
Op.getOperand(6).getValueType() == MVT::i32)
11804 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11805 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11806 IndexKeyi32, Op.getOperand(7)});
11808 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11809 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11810 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11811 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11812 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11813 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11817 "invalid matrix and scale format combination in wmma call");
11823 case Intrinsic::amdgcn_readlane:
11824 case Intrinsic::amdgcn_readfirstlane:
11825 case Intrinsic::amdgcn_writelane:
11826 case Intrinsic::amdgcn_permlane16:
11827 case Intrinsic::amdgcn_permlanex16:
11828 case Intrinsic::amdgcn_permlane64:
11829 case Intrinsic::amdgcn_set_inactive:
11830 case Intrinsic::amdgcn_set_inactive_chain_arg:
11831 case Intrinsic::amdgcn_mov_dpp8:
11832 case Intrinsic::amdgcn_update_dpp:
11833 case Intrinsic::amdgcn_permlane_bcast:
11834 case Intrinsic::amdgcn_permlane_up:
11835 case Intrinsic::amdgcn_permlane_down:
11836 case Intrinsic::amdgcn_permlane_xor:
11838 case Intrinsic::amdgcn_dead: {
11840 for (
const EVT ValTy :
Op.getNode()->values())
11844 case Intrinsic::amdgcn_wave_shuffle:
11847 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11849 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11860 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11866 unsigned NewOpcode)
const {
11873 "unsupported buffer atomic data type");
11875 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11876 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11894 M->getMemOperand());
11899 unsigned NewOpcode)
const {
11906 "unsupported buffer atomic data type");
11908 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11909 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11927 M->getMemOperand());
11934 unsigned NumOperands =
N->getNumOperands();
11935 if (
N->getOperand(NumOperands - 1) ==
Zero)
11944 unsigned IntrID =
Op.getConstantOperandVal(1);
11948 case Intrinsic::amdgcn_cluster_load_b32:
11949 case Intrinsic::amdgcn_cluster_load_b64:
11950 case Intrinsic::amdgcn_cluster_load_b128: {
11951 if (Subtarget->hasGFX1250_STRICT())
11955 case Intrinsic::amdgcn_ds_ordered_add:
11956 case Intrinsic::amdgcn_ds_ordered_swap: {
11961 unsigned IndexOperand =
M->getConstantOperandVal(7);
11962 unsigned WaveRelease =
M->getConstantOperandVal(8);
11963 unsigned WaveDone =
M->getConstantOperandVal(9);
11965 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11966 IndexOperand &= ~0x3f;
11967 unsigned CountDw = 0;
11970 CountDw = (IndexOperand >> 24) & 0xf;
11971 IndexOperand &= ~(0xf << 24);
11973 if (CountDw < 1 || CountDw > 4) {
11976 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11977 DL.getDebugLoc()));
11982 if (IndexOperand) {
11985 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11988 if (WaveDone && !WaveRelease) {
11992 Fn,
"ds_ordered_count: wave_done requires wave_release",
11993 DL.getDebugLoc()));
11996 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11997 unsigned ShaderType =
11999 unsigned Offset0 = OrderedCountIndex << 2;
12000 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
12003 Offset1 |= (CountDw - 1) << 6;
12006 Offset1 |= ShaderType << 2;
12008 unsigned Offset = Offset0 | (Offset1 << 8);
12015 M->getVTList(),
Ops,
M->getMemoryVT(),
12016 M->getMemOperand());
12018 case Intrinsic::amdgcn_ptr_s_buffer_load: {
12019 unsigned CPol =
Op.getConstantOperandVal(4);
12026 return lowerSBuffer(
12027 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
12028 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
12029 Op.getOperand(4), DAG,
M->getMemOperand());
12031 case Intrinsic::amdgcn_raw_buffer_load:
12032 case Intrinsic::amdgcn_raw_ptr_buffer_load:
12033 case Intrinsic::amdgcn_raw_atomic_buffer_load:
12034 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12035 case Intrinsic::amdgcn_raw_buffer_load_format:
12036 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12037 const bool IsFormat =
12038 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12039 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12041 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12042 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12056 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
12058 case Intrinsic::amdgcn_struct_buffer_load:
12059 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12060 case Intrinsic::amdgcn_struct_buffer_load_format:
12061 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12062 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12063 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12064 const bool IsFormat =
12065 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12066 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12068 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12069 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12084 case Intrinsic::amdgcn_raw_tbuffer_load:
12085 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12087 EVT LoadVT =
Op.getValueType();
12088 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12089 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12105 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12107 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12108 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12111 case Intrinsic::amdgcn_struct_tbuffer_load:
12112 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12114 EVT LoadVT =
Op.getValueType();
12115 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12116 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12132 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12134 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12135 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12138 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12139 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12140 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12141 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12142 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12143 return lowerStructBufferAtomicIntrin(
Op, DAG,
12144 AMDGPUISD::BUFFER_ATOMIC_FADD);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12147 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12148 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12149 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12150 return lowerStructBufferAtomicIntrin(
Op, DAG,
12151 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12152 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12153 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12154 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12155 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12156 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12157 return lowerStructBufferAtomicIntrin(
Op, DAG,
12158 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12159 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12160 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12161 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12162 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12163 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12164 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12165 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12166 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12167 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12168 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12169 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12170 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12171 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12172 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12173 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12174 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12175 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12176 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12177 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12179 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12180 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12182 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12183 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12185 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12186 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12187 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12188 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12189 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12190 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12191 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12192 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12193 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12194 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12195 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12196 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12197 return lowerStructBufferAtomicIntrin(
Op, DAG,
12198 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12199 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12200 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12201 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12202 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12203 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12204 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12205 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12206 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12207 return lowerStructBufferAtomicIntrin(
Op, DAG,
12208 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12209 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12210 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12211 return lowerStructBufferAtomicIntrin(
Op, DAG,
12212 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12213 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12214 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12215 return lowerStructBufferAtomicIntrin(
Op, DAG,
12216 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12217 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12218 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12219 return lowerStructBufferAtomicIntrin(
Op, DAG,
12220 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12221 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12222 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12223 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12224 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12225 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12226 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12227 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12228 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12229 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12230 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12231 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12232 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12233 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12234 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12235 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12236 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12237 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12238 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12239 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12240 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12241 return lowerStructBufferAtomicIntrin(
Op, DAG,
12242 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12243 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12244 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12245 return lowerRawBufferAtomicIntrin(
Op, DAG,
12246 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12247 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12248 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12249 return lowerStructBufferAtomicIntrin(
Op, DAG,
12250 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12251 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12252 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12254 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12257 "unsupported buffer atomic data type");
12259 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12260 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12274 EVT VT =
Op.getValueType();
12278 Op->getVTList(),
Ops, VT,
12279 M->getMemOperand());
12281 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12282 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12284 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12287 "unsupported buffer atomic data type");
12289 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12290 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12304 EVT VT =
Op.getValueType();
12308 Op->getVTList(),
Ops, VT,
12309 M->getMemOperand());
12311 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12312 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12314 SDValue NodePtr =
M->getOperand(2);
12315 SDValue RayExtent =
M->getOperand(3);
12316 SDValue InstanceMask =
M->getOperand(4);
12317 SDValue RayOrigin =
M->getOperand(5);
12318 SDValue RayDir =
M->getOperand(6);
12320 SDValue TDescr =
M->getOperand(8);
12325 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12326 const unsigned NumVDataDwords = 10;
12327 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12329 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12330 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12331 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12335 Ops.push_back(NodePtr);
12338 {DAG.getBitcast(MVT::i32, RayExtent),
12339 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12340 Ops.push_back(RayOrigin);
12341 Ops.push_back(RayDir);
12342 Ops.push_back(Offsets);
12343 Ops.push_back(TDescr);
12344 Ops.push_back(
M->getChain());
12347 MachineMemOperand *MemRef =
M->getMemOperand();
12351 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12353 SDValue NodePtr =
M->getOperand(2);
12354 SDValue RayExtent =
M->getOperand(3);
12355 SDValue RayOrigin =
M->getOperand(4);
12356 SDValue RayDir =
M->getOperand(5);
12357 SDValue RayInvDir =
M->getOperand(6);
12358 SDValue TDescr =
M->getOperand(7);
12370 const unsigned NumVDataDwords = 4;
12371 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12372 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12373 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12376 const unsigned BaseOpcodes[2][2] = {
12377 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12378 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12379 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12383 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12384 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12385 : AMDGPU::MIMGEncGfx10NSA,
12386 NumVDataDwords, NumVAddrDwords);
12390 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12391 : AMDGPU::MIMGEncGfx10Default,
12392 NumVDataDwords, NumVAddrDwords);
12398 auto packLanes = [&DAG, &
Ops, &
DL](
SDValue Op,
bool IsAligned) {
12401 if (Lanes[0].getValueSizeInBits() == 32) {
12402 for (
unsigned I = 0;
I < 3; ++
I)
12409 Ops.push_back(Lanes[2]);
12421 if (UseNSA && IsGFX11Plus) {
12422 Ops.push_back(NodePtr);
12424 Ops.push_back(RayOrigin);
12429 for (
unsigned I = 0;
I < 3; ++
I) {
12432 {DirLanes[I], InvDirLanes[I]})));
12436 Ops.push_back(RayDir);
12437 Ops.push_back(RayInvDir);
12444 Ops.push_back(NodePtr);
12447 packLanes(RayOrigin,
true);
12448 packLanes(RayDir,
true);
12449 packLanes(RayInvDir,
false);
12454 if (NumVAddrDwords > 12) {
12462 Ops.push_back(MergedOps);
12465 Ops.push_back(TDescr);
12467 Ops.push_back(
M->getChain());
12470 MachineMemOperand *MemRef =
M->getMemOperand();
12474 case Intrinsic::amdgcn_global_atomic_fmin_num:
12475 case Intrinsic::amdgcn_global_atomic_fmax_num:
12476 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12477 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12484 unsigned Opcode = 0;
12486 case Intrinsic::amdgcn_global_atomic_fmin_num:
12487 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12491 case Intrinsic::amdgcn_global_atomic_fmax_num:
12492 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12499 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12500 Ops,
M->getMemOperand());
12502 case Intrinsic::amdgcn_s_alloc_vgpr: {
12510 ReadFirstLaneID, NumVGPRs);
12513 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12515 case Intrinsic::amdgcn_s_get_barrier_state:
12516 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12523 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12524 BarID = BarID & 0x3F;
12525 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12528 Ops.push_back(Chain);
12530 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12531 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12542 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12543 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12544 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12548 EVT VT =
Op->getValueType(0);
12552 case Intrinsic::amdgcn_av_load_b8:
12553 case Intrinsic::amdgcn_av_load_b16:
12554 case Intrinsic::amdgcn_av_load_b32:
12555 case Intrinsic::amdgcn_av_load_b64:
12556 case Intrinsic::amdgcn_av_load_b128: {
12560 EVT VT =
Op->getValueType(0);
12567 case Intrinsic::amdgcn_flat_load_monitor_b32:
12568 case Intrinsic::amdgcn_flat_load_monitor_b64:
12569 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12574 Op->getVTList(), {Chain, Ptr},
12577 case Intrinsic::amdgcn_global_load_monitor_b32:
12578 case Intrinsic::amdgcn_global_load_monitor_b64:
12579 case Intrinsic::amdgcn_global_load_monitor_b128: {
12584 Op->getVTList(), {Chain, Ptr},
12589 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12591 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12599SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12606 EVT VT = VTList.
VTs[0];
12609 bool IsTFE = VTList.
NumVTs == 3;
12612 unsigned NumOpDWords = NumValueDWords + 1;
12614 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12615 MachineMemOperand *OpDWordsMMO =
12617 SDValue Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12618 OpDWordsVT, OpDWordsMMO, DAG);
12623 if (!Subtarget->hasDwordx3LoadStores() &&
12624 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12628 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12630 WidenedMemVT, WidenedMMO);
12640 bool ImageStore)
const {
12650 if (Subtarget->hasUnpackedD16VMem()) {
12664 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12675 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12681 if ((NumElements % 2) == 1) {
12683 unsigned I = Elts.
size() / 2;
12699 if (NumElements == 3) {
12718 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12719 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12720 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12721 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12722 case Intrinsic::amdgcn_load_async_to_lds:
12723 case Intrinsic::amdgcn_global_load_async_lds:
12733 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12735 switch (IntrinsicID) {
12736 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12737 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12738 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12739 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12740 if (Subtarget->hasGFX1250_STRICT())
12744 case Intrinsic::amdgcn_exp_compr: {
12765 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12769 case Intrinsic::amdgcn_struct_tbuffer_store:
12770 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12774 VData = handleD16VData(VData, DAG);
12775 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12776 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12790 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12791 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12794 M->getMemoryVT(),
M->getMemOperand());
12797 case Intrinsic::amdgcn_raw_tbuffer_store:
12798 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12802 VData = handleD16VData(VData, DAG);
12803 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12804 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12818 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12819 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12822 M->getMemoryVT(),
M->getMemOperand());
12825 case Intrinsic::amdgcn_raw_buffer_store:
12826 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12827 case Intrinsic::amdgcn_raw_buffer_store_format:
12828 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12829 const bool IsFormat =
12830 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12831 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12841 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12846 VData = handleD16VData(VData, DAG);
12856 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12857 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12871 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12872 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12877 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12880 M->getMemoryVT(),
M->getMemOperand());
12883 case Intrinsic::amdgcn_struct_buffer_store:
12884 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12885 case Intrinsic::amdgcn_struct_buffer_store_format:
12886 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12887 const bool IsFormat =
12888 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12889 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12899 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12904 VData = handleD16VData(VData, DAG);
12914 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12915 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12929 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12930 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12934 EVT VDataType = VData.getValueType().getScalarType();
12936 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12939 M->getMemoryVT(),
M->getMemOperand());
12941 case Intrinsic::amdgcn_raw_buffer_load_lds:
12942 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12943 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12944 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12945 case Intrinsic::amdgcn_struct_buffer_load_lds:
12946 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12947 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12948 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12951 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12952 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12953 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12954 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12955 unsigned OpOffset = HasVIndex ? 1 : 0;
12956 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12958 unsigned Size =
Op->getConstantOperandVal(4);
12964 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12965 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12966 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12967 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12970 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12971 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12972 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12973 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12976 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12977 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12978 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12979 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12982 if (!Subtarget->hasLDSLoadB96_B128())
12984 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12985 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12986 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12987 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12990 if (!Subtarget->hasLDSLoadB96_B128())
12992 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12993 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12994 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12995 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
13003 if (HasVIndex && HasVOffset)
13007 else if (HasVIndex)
13008 Ops.push_back(
Op.getOperand(5));
13009 else if (HasVOffset)
13010 Ops.push_back(VOffset);
13012 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
13013 Ops.push_back(Rsrc);
13014 Ops.push_back(
Op.getOperand(6 + OpOffset));
13015 Ops.push_back(
Op.getOperand(7 + OpOffset));
13017 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
13040 case Intrinsic::amdgcn_load_to_lds:
13041 case Intrinsic::amdgcn_load_async_to_lds:
13042 case Intrinsic::amdgcn_global_load_lds:
13043 case Intrinsic::amdgcn_global_load_async_lds: {
13044 if (!Subtarget->hasVMemToLDSLoad())
13048 unsigned Size =
Op->getConstantOperandVal(4);
13053 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13056 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13059 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13062 if (!Subtarget->hasLDSLoadB96_B128())
13064 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13067 if (!Subtarget->hasLDSLoadB96_B128())
13069 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13085 if (
LHS->isDivergent())
13089 RHS.getOperand(0).getValueType() == MVT::i32) {
13092 VOffset =
RHS.getOperand(0);
13096 Ops.push_back(Addr);
13104 Ops.push_back(VOffset);
13107 Ops.push_back(
Op.getOperand(5));
13109 unsigned Aux =
Op.getConstantOperandVal(6);
13124 case Intrinsic::amdgcn_end_cf:
13126 Op->getOperand(2), Chain),
13128 case Intrinsic::amdgcn_s_barrier_signal_var: {
13135 if (CntC && CntC->isZero()) {
13140 std::optional<uint64_t> BarVal;
13142 BarVal =
C->getZExtValue();
13146 BarVal = *Addr + GA->getOffset();
13149 unsigned BarID = *BarVal & 0x3F;
13151 Ops.push_back(Chain);
13153 Op->getVTList(),
Ops);
13159 case Intrinsic::amdgcn_s_barrier_init: {
13166 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13167 ? AMDGPU::S_BARRIER_INIT_M0
13168 : AMDGPU::S_BARRIER_SIGNAL_M0;
13178 constexpr unsigned ShAmt = 16;
13189 case Intrinsic::amdgcn_s_wakeup_barrier: {
13190 if (!Subtarget->hasSWakeupBarrier())
13194 case Intrinsic::amdgcn_s_barrier_join: {
13203 switch (IntrinsicID) {
13206 case Intrinsic::amdgcn_s_barrier_join:
13207 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13209 case Intrinsic::amdgcn_s_wakeup_barrier:
13210 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13214 unsigned BarID = BarVal & 0x3F;
13217 Ops.push_back(Chain);
13219 switch (IntrinsicID) {
13222 case Intrinsic::amdgcn_s_barrier_join:
13223 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13225 case Intrinsic::amdgcn_s_wakeup_barrier:
13226 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13238 case Intrinsic::amdgcn_s_prefetch_data:
13239 case Intrinsic::amdgcn_s_prefetch_inst: {
13242 return Op.getOperand(0);
13245 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13247 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13254 Op->getVTList(),
Ops,
M->getMemoryVT(),
13255 M->getMemOperand());
13257 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13258 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13259 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13267 case Intrinsic::amdgcn_av_store_b8:
13268 case Intrinsic::amdgcn_av_store_b16:
13269 case Intrinsic::amdgcn_av_store_b32:
13270 case Intrinsic::amdgcn_av_store_b64:
13271 case Intrinsic::amdgcn_av_store_b128: {
13279 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13281 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13297 return PtrVT == MVT::i64;
13311std::pair<SDValue, SDValue>
13324 bool CheckNUW =
Subtarget->hasGFX1250Insts();
13332 unsigned ImmOffset =
C1->getZExtValue();
13341 unsigned Overflow = ImmOffset & ~MaxImm;
13342 ImmOffset -= Overflow;
13343 if ((int32_t)Overflow < 0) {
13344 Overflow += ImmOffset;
13349 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13368void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13370 Align Alignment)
const {
13372 SDLoc
DL(CombinedOffset);
13374 uint32_t
Imm =
C->getZExtValue();
13375 uint32_t SOffset, ImmOffset;
13376 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13387 bool CheckNUW = Subtarget->hasGFX1250Insts();
13390 uint32_t SOffset, ImmOffset;
13393 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13401 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13410SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13413 return MaybePointer;
13427 SDValue NumRecords =
Op->getOperand(3);
13433 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13436 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13455 SDValue ExtShiftedStrideVec =
13467 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13469 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13474 auto [LowHalf, HighHalf] =
13475 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13485 NumRecords, Flags);
13497 bool IsTFE)
const {
13502 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13503 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13506 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13518 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13519 : AMDGPUISD::BUFFER_LOAD_USHORT;
13521 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13535 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13539 Ops[1] = BufferStoreExt;
13540 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13541 : AMDGPUISD::BUFFER_STORE_SHORT;
13544 M->getMemOperand());
13569 DAGCombinerInfo &DCI)
const {
13570 SelectionDAG &DAG = DCI.DAG;
13571 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13575 unsigned AS = Ld->getAddressSpace();
13584 EVT MemVT = Ld->getMemoryVT();
13585 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13592 "unexpected vector extload");
13595 SDValue Ptr = Ld->getBasePtr();
13598 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13599 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13604 "unexpected fp extload");
13619 EVT VT = Ld->getValueType(0);
13622 DCI.AddToWorklist(Cvt.
getNode());
13627 DCI.AddToWorklist(Cvt.
getNode());
13638 if (Info.isEntryFunction())
13639 return Info.getUserSGPRInfo().hasFlatScratchInit();
13647 EVT MemVT =
Load->getMemoryVT();
13648 MachineMemOperand *MMO =
Load->getMemOperand();
13655 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13662 BasePtr, MVT::i16, MMO);
13685 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13713 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13714 "Custom lowering for non-i32 vectors hasn't been implemented.");
13717 unsigned AS =
Load->getAddressSpace();
13718 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13725 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13729 !Subtarget->hasMultiDwordFlatScratchAddressing())
13741 Alignment >=
Align(4) && NumElements < 32) {
13743 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13755 if (NumElements > 4)
13758 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13768 switch (Subtarget->getMaxPrivateElementSize()) {
13774 if (NumElements > 2)
13779 if (NumElements > 4)
13782 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13791 auto Flags =
Load->getMemOperand()->getFlags();
13793 Load->getAlign(), Flags, &
Fast) &&
13802 MemVT, *
Load->getMemOperand())) {
13811 EVT VT =
Op.getValueType();
13848 EVT VT =
Op.getValueType();
13849 const SDNodeFlags
Flags =
Op->getFlags();
13851 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13857 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13860 if (CLHS->isOne()) {
13873 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13877 if (CLHS->isMinusOne()) {
13880 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13886 if (!AllowInaccurateRcp &&
13887 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13901 EVT VT =
Op.getValueType();
13902 const SDNodeFlags
Flags =
Op->getFlags();
13904 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13905 if (!AllowInaccurateDiv)
13929 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13941 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13951 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13955 return DAG.
getNode(Opcode, SL, VTList,
13964 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13974 Opcode = AMDGPUISD::FMA_W_CHAIN;
13978 return DAG.
getNode(Opcode, SL, VTList,
13984 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13985 return FastLowered;
13988 EVT VT =
Op.getValueType();
13995 if (VT == MVT::bf16) {
14018 unsigned FMADOpCode =
14022 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
14025 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14027 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
14028 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14038 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
14044 SDNodeFlags
Flags =
Op->getFlags();
14054 const APFloat K0Val(0x1p+96f);
14057 const APFloat K1Val(0x1p-32f);
14084 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
14085 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14086 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14091 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
14092 return FastLowered;
14098 SDNodeFlags
Flags =
Op->getFlags();
14099 Flags.setNoFPExcept(
true);
14107 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
14116 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14120 using namespace AMDGPU::Hwreg;
14121 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14125 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
14126 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
14129 const bool HasDynamicDenormals =
14135 if (!PreservesDenormals) {
14140 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14143 if (HasDynamicDenormals) {
14147 SavedDenormMode =
SDValue(GetReg, 0);
14153 SDNode *EnableDenorm;
14154 if (Subtarget->hasDenormModeInst()) {
14155 const SDValue EnableDenormValue =
14158 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14162 const SDValue EnableDenormValue =
14164 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14165 {EnableDenormValue,
BitField, Glue});
14175 ApproxRcp, One, NegDivScale0, Flags);
14178 ApproxRcp, Fma0, Flags);
14184 NumeratorScaled,
Mul, Flags);
14190 NumeratorScaled, Fma3, Flags);
14192 if (!PreservesDenormals) {
14193 SDNode *DisableDenorm;
14194 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14198 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14200 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14204 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14205 const SDValue DisableDenormValue =
14206 HasDynamicDenormals
14211 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14222 {Fma4, Fma1, Fma3, Scale},
Flags);
14224 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14228 if (
SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14229 return FastLowered;
14237 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14243 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14261 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14291 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14293 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14297 EVT VT =
Op.getValueType();
14299 if (VT == MVT::f32)
14300 return LowerFDIV32(
Op, DAG);
14302 if (VT == MVT::f64)
14303 return LowerFDIV64(
Op, DAG);
14305 if (VT == MVT::f16 || VT == MVT::bf16)
14306 return LowerFDIV16(
Op, DAG);
14315 EVT ResultExpVT =
Op->getValueType(1);
14316 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14326 if (Subtarget->hasFractBug()) {
14344 EVT VT =
Store->getMemoryVT();
14346 if (VT == MVT::i1) {
14350 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14354 Store->getValue().getValueType().getScalarType() == MVT::i32);
14356 unsigned AS =
Store->getAddressSpace();
14357 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14365 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14369 !Subtarget->hasMultiDwordFlatScratchAddressing())
14376 if (NumElements > 4)
14379 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14383 VT, *
Store->getMemOperand()))
14389 switch (Subtarget->getMaxPrivateElementSize()) {
14393 if (NumElements > 2)
14397 if (NumElements > 4 ||
14398 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14406 auto Flags =
Store->getMemOperand()->getFlags();
14425 assert(!Subtarget->has16BitInsts());
14426 SDNodeFlags
Flags =
Op->getFlags();
14440 SDNodeFlags
Flags =
Op->getFlags();
14441 MVT VT =
Op.getValueType().getSimpleVT();
14549 SDNodeFlags
Flags =
Op->getFlags();
14558 if (!
Flags.hasApproximateFuncs()) {
14590 if (!
Flags.hasApproximateFuncs()) {
14599 ScaleDownFactor, ZeroInt);
14606 if (
Flags.hasNoInfs()) {
14622 EVT VT =
Op.getValueType();
14633 if (!
V.getValueType().isVector())
14641 if (Subtarget->hasTrigReducedRange()) {
14643 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14648 switch (
Op.getOpcode()) {
14650 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14653 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14659 return UnrollIfVec(TrigVal);
14679 EVT VT =
Op.getValueType();
14687 Op->getVTList(),
Ops, VT,
14696SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14697 DAGCombinerInfo &DCI)
const {
14698 EVT VT =
N->getValueType(0);
14700 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14703 SelectionDAG &DAG = DCI.DAG;
14707 EVT SrcVT = Src.getValueType();
14713 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14716 DCI.AddToWorklist(Cvt.
getNode());
14719 if (ScalarVT != MVT::f32) {
14731 DAGCombinerInfo &DCI)
const {
14742 SelectionDAG &DAG = DCI.DAG;
14761 for (
unsigned I = 0;
I != NumElts; ++
I) {
14785 if (NewElts.
size() == 1)
14807 for (
unsigned I = 0;
I != NumElts; ++
I) {
14842SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14844 DAGCombinerInfo &DCI)
const {
14861 SelectionDAG &DAG = DCI.DAG;
14874 AM.BaseOffs =
Offset.getSExtValue();
14879 EVT VT =
N->getValueType(0);
14885 Flags.setNoUnsignedWrap(
14886 N->getFlags().hasNoUnsignedWrap() &&
14898 switch (
N->getOpcode()) {
14909 DAGCombinerInfo &DCI)
const {
14910 SelectionDAG &DAG = DCI.DAG;
14917 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14918 N->getMemoryVT(), DCI);
14922 NewOps[PtrIdx] = NewPtr;
14931 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14932 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14941SDValue SITargetLowering::splitBinaryBitConstantOp(
14945 uint32_t ValLo =
Lo_32(Val);
14946 uint32_t ValHi =
Hi_32(Val);
14953 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14967 if (V.getValueType() != MVT::i1)
14969 switch (V.getOpcode()) {
14974 case AMDGPUISD::FP_CLASS:
14986 return V.getResNo() == 1;
14988 unsigned IntrinsicID = V.getConstantOperandVal(0);
14989 switch (IntrinsicID) {
14990 case Intrinsic::amdgcn_is_shared:
14991 case Intrinsic::amdgcn_is_private:
15008 if (!(
C & 0x000000ff))
15009 ZeroByteMask |= 0x000000ff;
15010 if (!(
C & 0x0000ff00))
15011 ZeroByteMask |= 0x0000ff00;
15012 if (!(
C & 0x00ff0000))
15013 ZeroByteMask |= 0x00ff0000;
15014 if (!(
C & 0xff000000))
15015 ZeroByteMask |= 0xff000000;
15016 uint32_t NonZeroByteMask = ~ZeroByteMask;
15017 if ((NonZeroByteMask &
C) != NonZeroByteMask)
15030 assert(
V.getValueSizeInBits() == 32);
15032 if (
V.getNumOperands() != 2)
15041 switch (
V.getOpcode()) {
15046 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15051 return (0x03020100 & ~ConstMask) | ConstMask;
15058 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
15064 return uint32_t(0x0c0c0c0c03020100ull >>
C);
15071 DAGCombinerInfo &DCI)
const {
15072 if (DCI.isBeforeLegalize())
15075 SelectionDAG &DAG = DCI.DAG;
15076 EVT VT =
N->getValueType(0);
15081 if (VT == MVT::i64 && CRHS) {
15083 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
15087 if (CRHS && VT == MVT::i32) {
15097 unsigned Shift = CShift->getZExtValue();
15099 unsigned Offset = NB + Shift;
15100 if ((
Offset & (Bits - 1)) == 0) {
15103 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
15124 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15126 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15136 if (Shift && Shift->getZExtValue() < 16 &&
15155 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
15160 if (
X !=
LHS.getOperand(1))
15164 const ConstantFPSDNode *
C1 =
15166 if (!
C1 || !
C1->isInfinity() ||
C1->isNegative())
15181 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15187 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15190 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15198 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15199 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15201 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15202 :
Mask->getZExtValue() & OrdMask;
15205 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15223 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15226 if (LHSMask != ~0u && RHSMask != ~0u) {
15229 if (LHSMask > RHSMask) {
15236 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15237 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15240 if (!(LHSUsedLanes & RHSUsedLanes) &&
15243 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15249 uint32_t
Mask = LHSMask & RHSMask;
15250 for (
unsigned I = 0;
I < 32;
I += 8) {
15251 uint32_t ByteSel = 0xff <<
I;
15252 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15253 Mask &= (0x0c <<
I) & 0xffffffff;
15258 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15261 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15311static const std::optional<ByteProvider<SDValue>>
15313 unsigned Depth = 0) {
15316 return std::nullopt;
15318 if (
Op.getValueSizeInBits() < 8)
15319 return std::nullopt;
15321 if (
Op.getValueType().isVector())
15324 switch (
Op->getOpcode()) {
15337 NarrowVT = VTSign->getVT();
15340 return std::nullopt;
15343 if (SrcIndex >= NarrowByteWidth)
15344 return std::nullopt;
15352 return std::nullopt;
15354 uint64_t BitShift = ShiftOp->getZExtValue();
15356 if (BitShift % 8 != 0)
15357 return std::nullopt;
15359 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15360 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15361 return std::nullopt;
15380static const std::optional<ByteProvider<SDValue>>
15382 unsigned StartingIndex = 0) {
15386 return std::nullopt;
15388 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15390 return std::nullopt;
15392 return std::nullopt;
15394 bool IsVec =
Op.getValueType().isVector();
15395 switch (
Op.getOpcode()) {
15398 return std::nullopt;
15403 return std::nullopt;
15407 return std::nullopt;
15410 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15411 return std::nullopt;
15412 if (!
LHS ||
LHS->isConstantZero())
15414 if (!
RHS ||
RHS->isConstantZero())
15416 return std::nullopt;
15421 return std::nullopt;
15425 return std::nullopt;
15427 uint32_t BitMask = BitMaskOp->getZExtValue();
15429 uint32_t IndexMask = 0xFF << (Index * 8);
15431 if ((IndexMask & BitMask) != IndexMask) {
15434 if (IndexMask & BitMask)
15435 return std::nullopt;
15444 return std::nullopt;
15448 if (!ShiftOp ||
Op.getValueType().isVector())
15449 return std::nullopt;
15451 uint64_t BitsProvided =
Op.getValueSizeInBits();
15452 if (BitsProvided % 8 != 0)
15453 return std::nullopt;
15455 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15457 return std::nullopt;
15459 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15460 uint64_t ByteShift = BitShift / 8;
15462 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15463 uint64_t BytesProvided = BitsProvided / 8;
15464 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15465 NewIndex %= BytesProvided;
15472 return std::nullopt;
15476 return std::nullopt;
15478 uint64_t BitShift = ShiftOp->getZExtValue();
15480 return std::nullopt;
15482 auto BitsProvided =
Op.getScalarValueSizeInBits();
15483 if (BitsProvided % 8 != 0)
15484 return std::nullopt;
15486 uint64_t BytesProvided = BitsProvided / 8;
15487 uint64_t ByteShift = BitShift / 8;
15488 if (Index + ByteShift < BytesProvided)
15490 Index + ByteShift);
15493 return std::nullopt;
15499 return std::nullopt;
15503 return std::nullopt;
15505 uint64_t BitShift = ShiftOp->getZExtValue();
15506 if (BitShift % 8 != 0)
15507 return std::nullopt;
15508 uint64_t ByteShift = BitShift / 8;
15514 return Index < ByteShift
15517 Depth + 1, StartingIndex);
15526 return std::nullopt;
15534 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15536 if (NarrowBitWidth % 8 != 0)
15537 return std::nullopt;
15538 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15540 if (Index >= NarrowByteWidth)
15542 ? std::optional<ByteProvider<SDValue>>(
15550 return std::nullopt;
15554 if (NarrowByteWidth >= Index) {
15559 return std::nullopt;
15566 return std::nullopt;
15572 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15573 if (NarrowBitWidth % 8 != 0)
15574 return std::nullopt;
15575 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15580 if (Index >= NarrowByteWidth) {
15582 ? std::optional<ByteProvider<SDValue>>(
15587 if (NarrowByteWidth > Index) {
15591 return std::nullopt;
15596 return std::nullopt;
15599 Depth + 1, StartingIndex);
15605 return std::nullopt;
15606 auto VecIdx = IdxOp->getZExtValue();
15607 auto ScalarSize =
Op.getScalarValueSizeInBits();
15608 if (ScalarSize < 32)
15609 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15611 StartingIndex, Index);
15614 case AMDGPUISD::PERM: {
15616 return std::nullopt;
15620 return std::nullopt;
15623 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15624 if (IdxMask > 0x07 && IdxMask != 0x0c)
15625 return std::nullopt;
15627 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15628 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15630 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15636 return std::nullopt;
15651 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15658 auto MemVT = L->getMemoryVT();
15661 return L->getMemoryVT().getSizeInBits() == 16;
15671 int Low8 = Mask & 0xff;
15672 int Hi8 = (Mask & 0xff00) >> 8;
15674 assert(Low8 < 8 && Hi8 < 8);
15676 bool IsConsecutive = (Hi8 - Low8 == 1);
15681 bool Is16Aligned = !(Low8 % 2);
15683 return IsConsecutive && Is16Aligned;
15691 int Low16 = PermMask & 0xffff;
15692 int Hi16 = (PermMask & 0xffff0000) >> 16;
15702 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15704 if (!OtherOpIs16Bit)
15712 unsigned DWordOffset) {
15717 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15722 if (Src.getValueType().isVector()) {
15723 auto ScalarTySize = Src.getScalarValueSizeInBits();
15724 auto ScalarTy = Src.getValueType().getScalarType();
15725 if (ScalarTySize == 32) {
15729 if (ScalarTySize > 32) {
15732 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15733 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15740 assert(ScalarTySize < 32);
15749 auto NumElements =
TypeSize / ScalarTySize;
15750 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15751 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15752 auto NumElementsIn32 = 32 / ScalarTySize;
15753 auto NumAvailElements = DWordOffset < Trunc32Elements
15755 : NumElements - NormalizedTrunc;
15768 auto ShiftVal = 32 * DWordOffset;
15776 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15781 for (
int i = 0; i < 4; i++) {
15783 std::optional<ByteProvider<SDValue>>
P =
15786 if (!
P ||
P->isConstantZero())
15791 if (PermNodes.
size() != 4)
15794 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15795 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15797 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15798 auto PermOp = PermNodes[i];
15801 int SrcByteAdjust = 4;
15805 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15806 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15808 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15809 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15813 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15814 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15817 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15819 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15822 SDValue Op = *PermNodes[FirstSrc.first].Src;
15824 assert(
Op.getValueSizeInBits() == 32);
15828 int Low16 = PermMask & 0xffff;
15829 int Hi16 = (PermMask & 0xffff0000) >> 16;
15831 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15832 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15835 if (WellFormedLow && WellFormedHi)
15839 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15848 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15849 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15854 assert(
Op.getValueType().isByteSized() &&
15865 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15872 DAGCombinerInfo &DCI)
const {
15873 SelectionDAG &DAG = DCI.DAG;
15877 EVT VT =
N->getValueType(0);
15878 if (VT == MVT::i1) {
15880 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15881 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15883 if (Src !=
RHS.getOperand(0))
15888 if (!CLHS || !CRHS)
15892 static const uint32_t MaxMask = 0x3ff;
15897 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15906 LHS.getOpcode() == AMDGPUISD::PERM &&
15912 Sel |=
LHS.getConstantOperandVal(2);
15914 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15921 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15925 auto usesCombinedOperand = [](SDNode *OrUse) {
15928 !OrUse->getValueType(0).isVector())
15932 for (
auto *VUser : OrUse->users()) {
15933 if (!VUser->getValueType(0).isVector())
15940 if (VUser->getOpcode() == VectorwiseOp)
15946 if (!
any_of(
N->users(), usesCombinedOperand))
15952 if (LHSMask != ~0u && RHSMask != ~0u) {
15955 if (LHSMask > RHSMask) {
15962 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15963 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15966 if (!(LHSUsedLanes & RHSUsedLanes) &&
15969 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15971 LHSMask &= ~RHSUsedLanes;
15972 RHSMask &= ~LHSUsedLanes;
15974 LHSMask |= LHSUsedLanes & 0x04040404;
15976 uint32_t Sel = LHSMask | RHSMask;
15979 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15984 if (LHSMask == ~0u || RHSMask == ~0u) {
16025 return IdentitySrc;
16031 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
16046 if (SrcVT == MVT::i32) {
16051 DCI.AddToWorklist(LowOr.
getNode());
16052 DCI.AddToWorklist(HiBits.getNode());
16063 N->getOperand(0), CRHS))
16071 DAGCombinerInfo &DCI)
const {
16072 if (
SDValue RV = reassociateScalarOps(
N, DCI.DAG))
16079 SelectionDAG &DAG = DCI.DAG;
16081 EVT VT =
N->getValueType(0);
16082 if (CRHS && VT == MVT::i64) {
16084 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
16091 unsigned Opc =
LHS.getOpcode();
16121 LHS->getOperand(0), FNegLHS, FNegRHS);
16130SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
16131 DAGCombinerInfo &DCI)
const {
16132 if (!Subtarget->has16BitInsts() ||
16136 EVT VT =
N->getValueType(0);
16137 if (VT != MVT::i32)
16141 if (Src.getValueType() != MVT::i16)
16144 if (!Src->hasOneUse())
16147 if (
SDValue Ext = performExtendTruncShiftCombine(
N, DCI))
16154 std::optional<ByteProvider<SDValue>> BP0 =
16156 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16160 std::optional<ByteProvider<SDValue>> BP1 =
16162 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16170 SelectionDAG &DAG = DCI.DAG;
16172 uint32_t PermMask = 0x0c0c0c0c;
16175 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16180 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16183 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16191SITargetLowering::performExtendTruncShiftCombine(
SDNode *
N,
16192 DAGCombinerInfo &DCI)
const {
16196 const unsigned Opc =
N->getOpcode();
16199 if (
N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16200 Src.getOpcode() != (IsSigned ?
ISD::SRA :
ISD::SRL) || !Src.hasOneUse() ||
16206 if (!IsSigned && !Src->isDivergent())
16209 SDValue X = Src.getOperand(0).getOperand(0);
16211 if (
X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16212 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16215 SelectionDAG &DAG = DCI.DAG;
16217 const unsigned Width = 16 - Shift->getZExtValue();
16230SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16231 DAGCombinerInfo &DCI)
const {
16237 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16238 VTSign->getVT() == MVT::i8) ||
16239 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16240 VTSign->getVT() == MVT::i16))) {
16241 assert(Subtarget->hasScalarSubwordLoads() &&
16242 "s_buffer_load_{u8, i8} are supported "
16243 "in GFX12 (or newer) architectures.");
16244 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16245 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16246 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16249 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16257 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16258 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16259 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16261 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16262 VTSign->getVT() == MVT::i8) ||
16263 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16264 VTSign->getVT() == MVT::i16)) &&
16273 Src.getOperand(6), Src.getOperand(7)};
16276 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16277 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16278 ? AMDGPUISD::BUFFER_LOAD_BYTE
16279 : AMDGPUISD::BUFFER_LOAD_SHORT;
16280 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16281 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16282 return DCI.DAG.getMergeValues(
16283 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16289 DAGCombinerInfo &DCI)
const {
16290 SelectionDAG &DAG = DCI.DAG;
16297 if (
N->getOperand(0).isUndef())
16304 DAGCombinerInfo &DCI)
const {
16305 EVT VT =
N->getValueType(0);
16316 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16325 unsigned MaxDepth)
const {
16326 EVT VT =
Op.getValueType();
16328 "expected a floating-point value to query canonicality of");
16334 unsigned MaxDepth)
const {
16336 "QueryVT must be a floating-point scalar type");
16337 EVT VT =
Op.getValueType();
16341 unsigned Opcode =
Op.getOpcode();
16346 const auto &
F = CFP->getValueAPF();
16347 if (
F.isNaN() &&
F.isSignaling())
16349 if (!
F.isDenormal())
16381 case AMDGPUISD::FMUL_LEGACY:
16382 case AMDGPUISD::FMAD_FTZ:
16383 case AMDGPUISD::RCP:
16384 case AMDGPUISD::RSQ:
16385 case AMDGPUISD::RSQ_CLAMP:
16386 case AMDGPUISD::RCP_LEGACY:
16387 case AMDGPUISD::RCP_IFLAG:
16388 case AMDGPUISD::LOG:
16389 case AMDGPUISD::EXP:
16390 case AMDGPUISD::DIV_SCALE:
16391 case AMDGPUISD::DIV_FMAS:
16392 case AMDGPUISD::DIV_FIXUP:
16393 case AMDGPUISD::FRACT:
16394 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16395 case AMDGPUISD::CVT_F32_UBYTE0:
16396 case AMDGPUISD::CVT_F32_UBYTE1:
16397 case AMDGPUISD::CVT_F32_UBYTE2:
16398 case AMDGPUISD::CVT_F32_UBYTE3:
16399 case AMDGPUISD::FP_TO_FP16:
16400 case AMDGPUISD::SIN_HW:
16401 case AMDGPUISD::COS_HW:
16413 if (
Op.getValueType() == MVT::i32) {
16419 if (RHS->getZExtValue() == 0xffff0000) {
16430 return Op.getValueType().getScalarType() != MVT::f16;
16440 case AMDGPUISD::CLAMP:
16441 case AMDGPUISD::FMED3:
16442 case AMDGPUISD::FMAX3:
16443 case AMDGPUISD::FMIN3:
16444 case AMDGPUISD::FMAXIMUM3:
16445 case AMDGPUISD::FMINIMUM3: {
16451 if (Subtarget->supportsMinMaxDenormModes() ||
16461 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16476 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16510 if (
Op.getValueType() == MVT::i16) {
16522 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16524 switch (IntrinsicID) {
16525 case Intrinsic::amdgcn_update_dpp: {
16526 enum UpdateDPPOperand {
16533 if (QueryVT == MVT::f32 && (VT == MVT::i32 || VT == MVT::f32) &&
16534 Op.getConstantOperandVal(RowMask) == 0xf &&
16535 Op.getConstantOperandVal(BankMask) == 0xf &&
16536 Op.getConstantOperandVal(BoundCtrl) != 0)
16541 case Intrinsic::amdgcn_cvt_pkrtz:
16542 case Intrinsic::amdgcn_cubeid:
16543 case Intrinsic::amdgcn_frexp_mant:
16544 case Intrinsic::amdgcn_fdot2:
16545 case Intrinsic::amdgcn_rcp:
16546 case Intrinsic::amdgcn_rsq:
16547 case Intrinsic::amdgcn_rsq_clamp:
16548 case Intrinsic::amdgcn_rcp_legacy:
16549 case Intrinsic::amdgcn_rsq_legacy:
16550 case Intrinsic::amdgcn_trig_preop:
16551 case Intrinsic::amdgcn_tanh:
16552 case Intrinsic::amdgcn_log:
16553 case Intrinsic::amdgcn_exp2:
16554 case Intrinsic::amdgcn_sqrt:
16572 unsigned MaxDepth)
const {
16575 unsigned Opcode =
MI->getOpcode();
16577 if (Opcode == AMDGPU::G_FCANONICALIZE)
16580 std::optional<FPValueAndVReg> FCR;
16583 if (FCR->Value.isSignaling())
16585 if (!FCR->Value.isDenormal())
16596 case AMDGPU::G_FADD:
16597 case AMDGPU::G_FSUB:
16598 case AMDGPU::G_FMUL:
16599 case AMDGPU::G_FCEIL:
16600 case AMDGPU::G_FFLOOR:
16601 case AMDGPU::G_FRINT:
16602 case AMDGPU::G_FNEARBYINT:
16603 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16604 case AMDGPU::G_INTRINSIC_TRUNC:
16605 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16606 case AMDGPU::G_FMA:
16607 case AMDGPU::G_FMAD:
16608 case AMDGPU::G_FSQRT:
16609 case AMDGPU::G_FDIV:
16610 case AMDGPU::G_FREM:
16611 case AMDGPU::G_FPOW:
16612 case AMDGPU::G_FPEXT:
16613 case AMDGPU::G_FLOG:
16614 case AMDGPU::G_FLOG2:
16615 case AMDGPU::G_FLOG10:
16616 case AMDGPU::G_FPTRUNC:
16617 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16618 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16619 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16620 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16621 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16623 case AMDGPU::G_FNEG:
16624 case AMDGPU::G_FABS:
16625 case AMDGPU::G_FCOPYSIGN:
16627 case AMDGPU::G_FMINNUM:
16628 case AMDGPU::G_FMAXNUM:
16629 case AMDGPU::G_FMINNUM_IEEE:
16630 case AMDGPU::G_FMAXNUM_IEEE:
16631 case AMDGPU::G_FMINIMUM:
16632 case AMDGPU::G_FMAXIMUM:
16633 case AMDGPU::G_FMINIMUMNUM:
16634 case AMDGPU::G_FMAXIMUMNUM: {
16635 if (Subtarget->supportsMinMaxDenormModes() ||
16642 case AMDGPU::G_BUILD_VECTOR:
16647 case AMDGPU::G_INTRINSIC:
16648 case AMDGPU::G_INTRINSIC_CONVERGENT:
16650 case Intrinsic::amdgcn_fmul_legacy:
16651 case Intrinsic::amdgcn_fmad_ftz:
16652 case Intrinsic::amdgcn_sqrt:
16653 case Intrinsic::amdgcn_fmed3:
16654 case Intrinsic::amdgcn_sin:
16655 case Intrinsic::amdgcn_cos:
16656 case Intrinsic::amdgcn_log:
16657 case Intrinsic::amdgcn_exp2:
16658 case Intrinsic::amdgcn_log_clamp:
16659 case Intrinsic::amdgcn_rcp:
16660 case Intrinsic::amdgcn_rcp_legacy:
16661 case Intrinsic::amdgcn_rsq:
16662 case Intrinsic::amdgcn_rsq_clamp:
16663 case Intrinsic::amdgcn_rsq_legacy:
16664 case Intrinsic::amdgcn_div_scale:
16665 case Intrinsic::amdgcn_div_fmas:
16666 case Intrinsic::amdgcn_div_fixup:
16667 case Intrinsic::amdgcn_fract:
16668 case Intrinsic::amdgcn_cvt_pkrtz:
16669 case Intrinsic::amdgcn_cubeid:
16670 case Intrinsic::amdgcn_cubema:
16671 case Intrinsic::amdgcn_cubesc:
16672 case Intrinsic::amdgcn_cubetc:
16673 case Intrinsic::amdgcn_frexp_mant:
16674 case Intrinsic::amdgcn_fdot2:
16675 case Intrinsic::amdgcn_trig_preop:
16676 case Intrinsic::amdgcn_tanh:
16695 if (
C.isDenormal()) {
16708 if (
C.isSignaling()) {
16723SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16724 DAGCombinerInfo &DCI)
const {
16725 SelectionDAG &DAG = DCI.DAG;
16727 EVT VT =
N->getValueType(0);
16736 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16751 EVT EltVT =
Lo.getValueType();
16760 for (
unsigned I = 0;
I != 2; ++
I) {
16764 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16765 }
else if (
Op.isUndef()) {
16800 return AMDGPUISD::FMAX3;
16802 return AMDGPUISD::FMAXIMUM3;
16804 return AMDGPUISD::SMAX3;
16806 return AMDGPUISD::UMAX3;
16810 return AMDGPUISD::FMIN3;
16812 return AMDGPUISD::FMINIMUM3;
16814 return AMDGPUISD::SMIN3;
16816 return AMDGPUISD::UMIN3;
16837 if (!MinK || !MaxK)
16849 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16850 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16851 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16875 bool IsKnownNoNaNs)
const {
16911 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16917 if (
Info->getMode().DX10Clamp) {
16926 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16958 case AMDGPUISD::FMIN_LEGACY:
16959 case AMDGPUISD::FMAX_LEGACY:
16960 return (VT == MVT::f32) || (VT == MVT::f16 &&
Subtarget.hasMin3Max3_16()) ||
16961 (VT == MVT::v2f16 &&
Subtarget.hasMin3Max3PKF16());
16964 return (VT == MVT::f32 &&
Subtarget.hasMinimum3Maximum3F32()) ||
16965 (VT == MVT::f16 &&
Subtarget.hasMinimum3Maximum3F16()) ||
16966 (VT == MVT::v2f16 &&
Subtarget.hasMinimum3Maximum3PKF16());
16971 return (VT == MVT::i32) || (VT == MVT::i16 &&
Subtarget.hasMin3Max3_16());
16980 DAGCombinerInfo &DCI)
const {
16981 SelectionDAG &DAG = DCI.DAG;
16992 auto IsTreeWithCombinableChildren = [
Opc](
SDValue Op) {
16993 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16994 Op.getOperand(0).hasOneUse()) ||
16996 Op.getOperand(1).hasOneUse());
17001 bool HasCombinableTreeChild =
17002 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
17003 IsTreeWithCombinableChildren(Op1));
17012 if (CanTreeCombineApply && !HasCombinableTreeChild) {
17050 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
17058 if (
SDValue Med3 = performIntMed3ImmCombine(
17063 if (
SDValue Med3 = performIntMed3ImmCombine(
17069 if (
SDValue Med3 = performIntMed3ImmCombine(
17074 if (
SDValue Med3 = performIntMed3ImmCombine(
17087 (
Opc == AMDGPUISD::FMIN_LEGACY &&
17088 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17089 (VT == MVT::f32 || VT == MVT::f64 ||
17090 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17091 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17092 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17093 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17095 if (
SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
17096 N->getFlags().hasNoNaNs()))
17103 const SDNodeFlags
Flags =
N->getFlags();
17105 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17109 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
17119 return (CA->isPosZero() && CB->isOne()) ||
17120 (CA->isOne() && CB->isPosZero());
17129 DAGCombinerInfo &DCI)
const {
17130 EVT VT =
N->getValueType(0);
17134 SelectionDAG &DAG = DCI.DAG;
17145 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17149 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
17153 if (
Info->getMode().DX10Clamp) {
17166 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17173 DAGCombinerInfo &DCI)
const {
17176 if (
Src0.isUndef() &&
Src1.isUndef())
17177 return DCI.DAG.getUNDEF(
N->getValueType(0));
17184SITargetLowering::performExponentOnlyScaleCombine(
SDNode *
N,
17185 DAGCombinerInfo &DCI)
const {
17186 std::optional<unsigned> ScaleArgIdx =
17192 unsigned OpIdx = *ScaleArgIdx + 1;
17193 SelectionDAG &DAG = DCI.DAG;
17200 Ops[OpIdx] = DemandedScale;
17214 bool IsDivergentIdx,
17216 if (Subtarget->getCLOpts().use_divergent_register_indexing)
17219 unsigned VecSize = EltSize * NumElem;
17222 if (VecSize <= 64 && EltSize < 32)
17231 if (IsDivergentIdx)
17235 unsigned NumInsts = NumElem +
17236 ((EltSize + 31) / 32) * NumElem ;
17240 if (Subtarget->useVGPRIndexMode())
17241 return NumInsts <= 16;
17245 if (Subtarget->hasMovrel())
17246 return NumInsts <= 15;
17252 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17263 EltSize, NumElem, Idx->isDivergent(),
getSubtarget());
17267SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17268 DAGCombinerInfo &DCI)
const {
17274 EVT ResVT =
N->getValueType(0);
17298 if (!
C ||
C->getZExtValue() != 0x1f)
17314 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17342 DCI.AddToWorklist(Elt0.
getNode());
17343 DCI.AddToWorklist(Elt1.
getNode());
17374 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17375 uint64_t KImmValue = KImm->getZExtValue();
17377 (KImmValue >> (32 *
Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17380 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17382 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17383 return DAG.
getConstant((KFPImmValue >> (32 *
Idx->getZExtValue())) &
17389 if (!DCI.isBeforeLegalize())
17396 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17399 unsigned BitIndex =
Idx->getZExtValue() * VecEltSize;
17400 unsigned EltIdx = BitIndex / 32;
17401 unsigned LeftoverBitIdx = BitIndex % 32;
17405 DCI.AddToWorklist(Cast.
getNode());
17409 DCI.AddToWorklist(Elt.
getNode());
17412 DCI.AddToWorklist(Srl.
getNode());
17416 DCI.AddToWorklist(Trunc.
getNode());
17418 if (VecEltVT == ResVT) {
17430SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17431 DAGCombinerInfo &DCI)
const {
17445 SelectionDAG &DAG = DCI.DAG;
17448 EVT IdxVT =
Idx.getValueType();
17465 Src.getOperand(0).getValueType() == MVT::f16) {
17466 return Src.getOperand(0);
17470 APFloat Val = CFP->getValueAPF();
17471 bool LosesInfo =
true;
17481 DAGCombinerInfo &DCI)
const {
17482 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17483 "combine only useful on gfx8");
17485 SDValue TruncSrc =
N->getOperand(0);
17486 EVT VT =
N->getValueType(0);
17487 if (VT != MVT::f16)
17490 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17494 SelectionDAG &DAG = DCI.DAG;
17525unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17527 const SDNode *N1)
const {
17532 if (((VT == MVT::f32 &&
17534 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17551 EVT VT =
N->getValueType(0);
17552 if (VT != MVT::i32 && VT != MVT::i64)
17558 unsigned Opc =
N->getOpcode();
17613 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17632 DAGCombinerInfo &DCI)
const {
17635 SelectionDAG &DAG = DCI.DAG;
17636 EVT VT =
N->getValueType(0);
17646 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17650 if (NumBits <= 32 || NumBits > 64)
17661 if (!Subtarget->hasFullRate64Ops()) {
17662 unsigned NumUsers = 0;
17663 for (SDNode *User :
LHS->
users()) {
17666 if (!
User->isAnyAdd())
17690 bool MulSignedLo =
false;
17691 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17700 if (VT != MVT::i64) {
17723 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17725 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17726 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17728 if (!MulLHSUnsigned32) {
17735 if (!MulRHSUnsigned32) {
17746 if (VT != MVT::i64)
17752SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17753 DAGCombinerInfo &DCI)
const {
17763 SelectionDAG &DAG = DCI.DAG;
17778 unsigned Opcode =
N->getOpcode();
17782 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17793static std::optional<ByteProvider<SDValue>>
17796 if (!Byte0 || Byte0->isConstantZero()) {
17797 return std::nullopt;
17800 if (Byte1 && !Byte1->isConstantZero()) {
17801 return std::nullopt;
17807 unsigned FirstCs =
First & 0x0c0c0c0c;
17808 unsigned SecondCs = Second & 0x0c0c0c0c;
17809 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17810 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17812 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17813 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17814 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17815 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17817 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17831 assert(Src0.Src.has_value() && Src1.Src.has_value());
17834 Src0s.
push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17835 Src0.SrcOffset / 4});
17836 Src1s.
push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17837 Src1.SrcOffset / 4});
17841 for (
int BPI = 0; BPI < 2; BPI++) {
17844 BPP = {Src1, Src0};
17846 unsigned ZeroMask = 0x0c0c0c0c;
17847 unsigned FMask = 0xFF << (8 * (3 - Step));
17849 unsigned FirstMask =
17850 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17851 unsigned SecondMask =
17852 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17856 int FirstGroup = -1;
17857 for (
int I = 0;
I < 2;
I++) {
17859 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17860 return IterElt.SrcOp == *BPP.first.Src &&
17861 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17865 if (Match != Srcs.
end()) {
17866 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17871 if (FirstGroup != -1) {
17873 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17874 return IterElt.SrcOp == *BPP.second.Src &&
17875 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17878 if (Match != Srcs.
end()) {
17879 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17881 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17889 unsigned ZeroMask = 0x0c0c0c0c;
17890 unsigned FMask = 0xFF << (8 * (3 - Step));
17894 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17895 Src0.SrcOffset / 4});
17898 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17899 Src1.SrcOffset / 4});
17907 if (Srcs.
size() == 1) {
17908 auto *Elt = Srcs.
begin();
17912 if (Elt->PermMask == 0x3020100)
17915 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17919 auto *FirstElt = Srcs.
begin();
17920 auto *SecondElt = std::next(FirstElt);
17927 auto FirstMask = FirstElt->PermMask;
17928 auto SecondMask = SecondElt->PermMask;
17930 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17931 unsigned FirstPlusFour = FirstMask | 0x04040404;
17934 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17946 FirstElt = std::next(SecondElt);
17947 if (FirstElt == Srcs.
end())
17950 SecondElt = std::next(FirstElt);
17953 if (SecondElt == Srcs.
end()) {
17958 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17959 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17965 return Perms.
size() == 2
17971 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17972 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17973 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17974 EntryMask += ZeroMask;
17979 auto Opcode =
Op.getOpcode();
17981 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17982 Opcode == AMDGPUISD::MUL_I24);
17985static std::optional<bool>
17996 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17999 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
18001 assert(!(S0IsUnsigned && S0IsSigned));
18002 assert(!(S1IsUnsigned && S1IsSigned));
18010 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
18016 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
18017 return std::nullopt;
18029 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
18030 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
18035 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
18041 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
18042 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
18043 return std::nullopt;
18049 DAGCombinerInfo &DCI)
const {
18050 SelectionDAG &DAG = DCI.DAG;
18051 EVT VT =
N->getValueType(0);
18057 if (Subtarget->hasMad64_32()) {
18063 if (
SDValue V = reassociateScalarOps(
N, DAG)) {
18067 if (VT == MVT::i64) {
18075 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
18077 std::optional<bool> IsSigned;
18083 int ChainLength = 0;
18084 for (
int I = 0;
I < 4;
I++) {
18096 TempNode->getOperand(MulIdx), *Src0, *Src1,
18097 TempNode->getOperand(MulIdx)->getOperand(0),
18098 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18102 IsSigned = *IterIsSigned;
18103 if (*IterIsSigned != *IsSigned)
18106 auto AddIdx = 1 - MulIdx;
18109 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
18110 Src2s.
push_back(TempNode->getOperand(AddIdx));
18120 TempNode->getOperand(AddIdx), *Src0, *Src1,
18121 TempNode->getOperand(AddIdx)->getOperand(0),
18122 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18126 if (*IterIsSigned != *IsSigned)
18130 ChainLength =
I + 2;
18134 TempNode = TempNode->getOperand(AddIdx);
18136 ChainLength =
I + 1;
18138 if (TempNode.getOpcode() !=
ISD::ADD)
18140 LHS = TempNode->getOperand(0);
18141 RHS = TempNode->getOperand(1);
18144 if (ChainLength < 2)
18150 if (ChainLength < 4) {
18160 bool UseOriginalSrc =
false;
18161 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
18162 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
18163 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
18164 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
18165 SmallVector<unsigned, 4> SrcBytes;
18166 auto Src0Mask = Src0s.
begin()->PermMask;
18167 SrcBytes.
push_back((Src0Mask >> 24) & 0xFF);
18168 bool UniqueEntries =
true;
18169 for (
auto I = 1;
I < 4;
I++) {
18170 auto NextByte = (Src0Mask >> ((3 -
I) * 8)) & 0xFF;
18173 UniqueEntries =
false;
18179 if (UniqueEntries) {
18180 UseOriginalSrc =
true;
18182 auto *FirstElt = Src0s.
begin();
18186 auto *SecondElt = Src1s.
begin();
18188 SecondElt->DWordOffset);
18197 if (!UseOriginalSrc) {
18204 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18207 : Intrinsic::amdgcn_udot4,
18217 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18222 unsigned Opc =
LHS.getOpcode();
18234 auto Cond =
RHS.getOperand(0);
18239 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18256 DAGCombinerInfo &DCI)
const {
18257 SelectionDAG &DAG = DCI.DAG;
18259 EVT VT =
N->getValueType(0);
18272 SDNodeFlags ShlFlags = N1->
getFlags();
18276 SDNodeFlags NewShlFlags =
18281 DCI.AddToWorklist(Inner.
getNode());
18288 if (Subtarget->hasMad64_32()) {
18298 if (VT == MVT::i64) {
18312 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18313 Y->isDivergent() !=
Z->isDivergent()) {
18322 if (
Y->isDivergent())
18325 SDNodeFlags ReassocFlags =
18328 DCI.AddToWorklist(UniformInner.
getNode());
18340 DAGCombinerInfo &DCI)
const {
18341 SelectionDAG &DAG = DCI.DAG;
18342 EVT VT =
N->getValueType(0);
18344 if (VT == MVT::i64) {
18349 if (VT != MVT::i32)
18358 unsigned Opc =
RHS.getOpcode();
18365 auto Cond =
RHS.getOperand(0);
18370 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18396 ConstantSDNode *ShiftAmt =
18398 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18409 DAGCombinerInfo &DCI)
const {
18413 SelectionDAG &DAG = DCI.DAG;
18414 EVT VT =
N->getValueType(0);
18426 if (
A ==
LHS.getOperand(1)) {
18427 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18428 if (FusedOp != 0) {
18430 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18438 if (
A ==
RHS.getOperand(1)) {
18439 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18440 if (FusedOp != 0) {
18442 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18451 DAGCombinerInfo &DCI)
const {
18455 SelectionDAG &DAG = DCI.DAG;
18457 EVT VT =
N->getValueType(0);
18470 if (
A ==
LHS.getOperand(1)) {
18471 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18472 if (FusedOp != 0) {
18476 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18485 if (
A ==
RHS.getOperand(1)) {
18486 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18487 if (FusedOp != 0) {
18489 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18498 DAGCombinerInfo &DCI)
const {
18499 SelectionDAG &DAG = DCI.DAG;
18501 EVT VT =
N->getValueType(0);
18503 if (VT != MVT::f16 && VT != MVT::bf16)
18509 SDNodeFlags
Flags =
N->getFlags();
18510 SDNodeFlags RHSFlags =
RHS->getFlags();
18516 bool IsNegative =
false;
18517 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18526 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18527 }
else if (VT == MVT::f16) {
18536 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18553 DAGCombinerInfo &DCI)
const {
18554 SelectionDAG &DAG = DCI.DAG;
18555 EVT VT =
N->getValueType(0);
18559 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18560 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18575 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18580 const ConstantFPSDNode *FalseNode =
18590 if (ScalarVT == MVT::f32 &&
18596 if (TrueNodeExpVal == INT_MIN)
18599 if (FalseNodeExpVal == INT_MIN)
18619 DAGCombinerInfo &DCI)
const {
18620 SelectionDAG &DAG = DCI.DAG;
18621 EVT VT =
N->getValueType(0);
18624 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18652 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18653 FMA->getFlags().hasApproximateFuncs();
18654 if (!AllowInaccuracy) {
18657 if (Subtarget->dot2UnconditionalFlush()) {
18669 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18705 if (Vec1 == Vec2 || Vec3 == Vec4)
18711 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18712 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18755 EVT VT =
LHS.getValueType();
18756 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18803 const std::optional<bool> KnownEq =
18844 const std::optional<bool> KnownUge =
18886 const std::optional<bool> KnownUle =
18909 DAGCombinerInfo &DCI)
const {
18910 SelectionDAG &DAG = DCI.DAG;
18915 EVT VT =
LHS.getValueType();
18944 return LHS.getOperand(0);
18958 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18959 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18964 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18967 return LHS.getOperand(0);
18973 if (VT == MVT::i64) {
18976 const KnownBits LHSKnownLo32 = LHSKnown.
trunc(32);
18977 const KnownBits RHSKnownLo32 = RHSKnown.
trunc(32);
19004 const std::optional<bool> KnownEq =
19012 const std::optional<bool> KnownEq =
19023 const std::optional<bool> KnownUge =
19043 const std::optional<bool> KnownUle =
19067 const KnownBits LHSKnownHi32 = LHSKnown.
extractBits(32, 32);
19068 const KnownBits RHSKnownHi32 = RHSKnown.
extractBits(32, 32);
19069 const std::optional<bool> KnownEq =
19072 if (KnownEq ==
true) {
19078 return DAG.
getSetCC(SL,
N->getValueType(0), LHSLo, RHSLo, NewCC);
19110 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19115 {Op0Hi, Op1Hi, CarryInHi});
19125 DCI.CombineTo(
LHS.getNode(), Result);
19129 if (VT != MVT::f32 && VT != MVT::f64 &&
19130 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19145 const unsigned IsInfMask =
19147 const unsigned IsFiniteMask =
19152 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
19157 if (VT == MVT::f64) {
19168SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
19169 DAGCombinerInfo &DCI)
const {
19170 SelectionDAG &DAG = DCI.DAG;
19172 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19191 unsigned ShiftOffset = 8 *
Offset;
19193 ShiftOffset -=
C->getZExtValue();
19195 ShiftOffset +=
C->getZExtValue();
19197 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19198 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19199 MVT::f32, Shifted);
19210 DCI.AddToWorklist(
N);
19217 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
19223 DAGCombinerInfo &DCI)
const {
19232 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19233 return DCI.DAG.getConstantFP(
Zero, SDLoc(
N),
N->getValueType(0));
19238 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
19240 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
19250 FrexpInput =
V.getOperand(0);
19260SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
19261 DAGCombinerInfo &DCI)
const {
19263 if (Subtarget->hasFractBug())
19275 bool CondSelectsZero;
19283 CondSelectsZero =
true;
19284 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19287 CondSelectsZero =
false;
19299 bool IsNonFiniteTest =
false;
19311 bool LHSMatchesFrexp =
19312 (CondLHS == FrexpInput) ||
19313 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19315 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19323 SelectionDAG &DAG = DCI.DAG;
19324 if (LHSMatchesFrexp &&
19326 IsNonFiniteTest = CondSelectsZero;
19328 IsNonFiniteTest = CondSelectsZero;
19335 IsNonFiniteTest = CondSelectsZero;
19342 IsNonFiniteTest = !CondSelectsZero;
19348 SelectionDAG &DAG = DCI.DAG;
19349 if (LHSMatchesFrexp &&
19351 IsNonFiniteTest = !CondSelectsZero;
19353 IsNonFiniteTest = !CondSelectsZero;
19357 if (!IsNonFiniteTest)
19365 DAGCombinerInfo &DCI)
const {
19386 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19387 bool isInteger =
LHS.getValueType().isInteger();
19390 if (!isFloatingPoint && !isInteger)
19395 bool isNonEquality =
19397 if (!isEquality && !isNonEquality)
19414 if (isFloatingPoint) {
19416 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19419 const std::optional<int64_t> Val =
19428 if (!(isEquality && TrueVal == ConstVal) &&
19429 !(isNonEquality && FalseVal == ConstVal))
19433 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19434 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19441 SelectLHS, SelectRHS);
19446 switch (
N->getOpcode()) {
19468 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19478 switch (
N->getOpcode()) {
19480 return performAddCombine(
N, DCI);
19482 return performPtrAddCombine(
N, DCI);
19484 return performSubCombine(
N, DCI);
19486 return performFAddCombine(
N, DCI);
19488 return performFSubCombine(
N, DCI);
19490 return performFDivCombine(
N, DCI);
19492 return performFMulCombine(
N, DCI);
19494 return performSetCCCombine(
N, DCI);
19496 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19498 if (
auto Res = performSelectCombine(
N, DCI))
19513 case AMDGPUISD::FMIN_LEGACY:
19514 case AMDGPUISD::FMAX_LEGACY:
19515 return performMinMaxCombine(
N, DCI);
19517 return performFMACombine(
N, DCI);
19519 return performAndCombine(
N, DCI);
19521 return performOrCombine(
N, DCI);
19524 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19525 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19531 return performXorCombine(
N, DCI);
19534 return performZeroOrAnyExtendCombine(
N, DCI);
19536 return performExtendTruncShiftCombine(
N, DCI);
19538 return performSignExtendInRegCombine(
N, DCI);
19539 case AMDGPUISD::FP_CLASS:
19540 return performClassCombine(
N, DCI);
19542 return performFCanonicalizeCombine(
N, DCI);
19543 case AMDGPUISD::RCP:
19544 return performRcpCombine(
N, DCI);
19546 case AMDGPUISD::FRACT:
19547 case AMDGPUISD::RSQ:
19548 case AMDGPUISD::RCP_LEGACY:
19549 case AMDGPUISD::RCP_IFLAG:
19550 case AMDGPUISD::RSQ_CLAMP: {
19559 return performUCharToFloatCombine(
N, DCI);
19561 return performFCopySignCombine(
N, DCI);
19562 case AMDGPUISD::CVT_F32_UBYTE0:
19563 case AMDGPUISD::CVT_F32_UBYTE1:
19564 case AMDGPUISD::CVT_F32_UBYTE2:
19565 case AMDGPUISD::CVT_F32_UBYTE3:
19566 return performCvtF32UByteNCombine(
N, DCI);
19567 case AMDGPUISD::FMED3:
19568 return performFMed3Combine(
N, DCI);
19569 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19570 return performCvtPkRTZCombine(
N, DCI);
19572 if (
SDValue Res = performExponentOnlyScaleCombine(
N, DCI))
19575 case AMDGPUISD::CLAMP:
19576 return performClampCombine(
N, DCI);
19579 EVT VT =
N->getValueType(0);
19582 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19585 EVT EltVT = Src.getValueType();
19586 if (EltVT != MVT::i16)
19596 return performExtractVectorEltCombine(
N, DCI);
19598 return performInsertVectorEltCombine(
N, DCI);
19600 return performFPRoundCombine(
N, DCI);
19609 return performMemSDNodeCombine(MemNode, DCI);
19640 unsigned Opcode =
Node->getMachineOpcode();
19643 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19644 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19647 SDNode *
Users[5] = {
nullptr};
19649 unsigned DmaskIdx =
19650 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19651 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19652 unsigned NewDmask = 0;
19653 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19654 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19655 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19656 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19657 unsigned TFCLane = 0;
19658 bool HasChain =
Node->getNumValues() > 1;
19660 if (OldDmask == 0) {
19668 TFCLane = OldBitsSet;
19672 for (SDUse &Use :
Node->uses()) {
19675 if (
Use.getResNo() != 0)
19678 SDNode *
User =
Use.getUser();
19681 if (!
User->isMachineOpcode() ||
19682 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19694 if (UsesTFC && Lane == TFCLane) {
19699 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19701 Dmask &= ~(1 << Comp);
19709 NewDmask |= 1 << Comp;
19714 bool NoChannels = !NewDmask;
19721 if (OldBitsSet == 1)
19727 if (NewDmask == OldDmask)
19736 unsigned NewChannels = BitsSet + UsesTFC;
19740 assert(NewOpcode != -1 &&
19741 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19742 "failed to find equivalent MIMG op");
19750 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19752 MVT ResultVT = NewChannels == 1
19755 : NewChannels == 5 ? 8
19757 SDVTList NewVTList =
19760 MachineSDNode *NewNode =
19769 if (NewChannels == 1) {
19779 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19784 if (i || !NoChannels)
19789 if (NewUser != User) {
19799 Idx = AMDGPU::sub1;
19802 Idx = AMDGPU::sub2;
19805 Idx = AMDGPU::sub3;
19808 Idx = AMDGPU::sub4;
19819 Op =
Op.getOperand(0);
19840 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19844 Node->getOperand(0), SL, VReg, SrcVal,
19850 return ToResultReg.
getNode();
19855 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19857 Ops.push_back(
Node->getOperand(i));
19863 Node->getOperand(i).getValueType(),
19864 Node->getOperand(i)),
19876 unsigned Opcode =
Node->getMachineOpcode();
19878 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19879 !
TII->isGather4(Opcode) &&
19881 return adjustWritemask(
Node, DAG);
19884 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19890 case AMDGPU::V_DIV_SCALE_F32_e64:
19891 case AMDGPU::V_DIV_SCALE_F64_e64: {
19899 if ((Src0.isMachineOpcode() &&
19900 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19901 (Src0 == Src1 || Src0 == Src2))
19904 MVT VT = Src0.getValueType().getSimpleVT();
19916 if (Src0.isMachineOpcode() &&
19917 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19918 if (Src1.isMachineOpcode() &&
19919 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19921 else if (Src2.isMachineOpcode() &&
19922 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19925 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19957 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19958 unsigned InitIdx = 0;
19960 if (
TII->isImage(
MI)) {
19968 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19969 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19970 unsigned D16Val = D16 ? D16->getImm() : 0;
19972 if (!TFEVal && !LWEVal)
19983 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19985 unsigned dmask = MO_Dmask->
getImm();
19990 bool Packed = !Subtarget->hasUnpackedD16VMem();
19992 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19999 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
20000 if (DstSize < InitIdx)
20004 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
20012 Register PrevDst =
MRI.cloneVirtualRegister(
MI.getOperand(DstIdx).getReg());
20013 unsigned NewDst = 0;
20018 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
20019 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
20022 for (; SizeLeft; SizeLeft--, CurrIdx++) {
20023 NewDst =
MRI.createVirtualRegister(
TII->getOpRegClass(
MI, DstIdx));
20025 Register SubReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
20043 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
20055 if (
TII->isVOP3(
MI.getOpcode())) {
20057 TII->legalizeOperandsVOP3(
MRI,
MI);
20059 if (
TII->isMAI(
MI)) {
20064 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
20065 AMDGPU::OpName::scale_src0);
20066 if (Src0Idx != -1) {
20067 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
20068 AMDGPU::OpName::scale_src1);
20069 if (
TII->usesConstantBus(
MRI,
MI, Src0Idx) &&
20070 TII->usesConstantBus(
MRI,
MI, Src1Idx))
20071 TII->legalizeOpWithMove(
MI, Src1Idx);
20078 if (
TII->isImage(
MI))
20079 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
20121 uint64_t RsrcDword2And3)
const {
20151std::pair<unsigned, const TargetRegisterClass *>
20158 if (Constraint.
size() == 1) {
20162 if (VT == MVT::Other)
20165 switch (Constraint[0]) {
20172 RC = &AMDGPU::SReg_32RegClass;
20175 RC = &AMDGPU::SGPR_64RegClass;
20180 return std::pair(0U,
nullptr);
20187 return std::pair(0U,
nullptr);
20189 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20190 : &AMDGPU::VGPR_32_Lo256RegClass;
20193 RC = Subtarget->hasVGPRMSBs()
20194 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
20197 return std::pair(0U,
nullptr);
20202 if (!Subtarget->hasMAIInsts())
20206 return std::pair(0U,
nullptr);
20208 RC = &AMDGPU::AGPR_32RegClass;
20213 return std::pair(0U,
nullptr);
20218 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
20222 RC = &AMDGPU::AV_32RegClass;
20225 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
20227 return std::pair(0U,
nullptr);
20236 return std::pair(0U, RC);
20239 if (Kind !=
'\0') {
20241 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20242 }
else if (Kind ==
's') {
20243 RC = &AMDGPU::SGPR_32RegClass;
20244 }
else if (Kind ==
'a') {
20245 RC = &AMDGPU::AGPR_32RegClass;
20251 return std::pair(0U,
nullptr);
20257 return std::pair(0U,
nullptr);
20261 RC =
TRI->getVGPRClassForBitWidth(Width);
20263 RC =
TRI->getSGPRClassForBitWidth(Width);
20265 RC =
TRI->getAGPRClassForBitWidth(Width);
20267 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20272 return std::pair(0U,
nullptr);
20274 return std::pair(Reg, RC);
20283 return std::pair(0U,
nullptr);
20284 if (RC && Idx < RC->getNumRegs())
20286 return std::pair(0U,
nullptr);
20292 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20293 if (!Subtarget->useRealTrue16Insts() &&
20294 TRI->getRegSizeInBits(*Ret.second) == 16)
20295 return std::pair(0U,
nullptr);
20302 if (Constraint.
size() == 1) {
20303 switch (Constraint[0]) {
20313 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20321 if (Constraint.
size() == 1) {
20322 switch (Constraint[0]) {
20330 }
else if (Constraint.
size() == 2) {
20331 if (Constraint ==
"VA")
20349 std::vector<SDValue> &
Ops,
20364 unsigned Size =
Op.getScalarValueSizeInBits();
20368 if (
Size == 16 && !Subtarget->has16BitInsts())
20372 Val =
C->getSExtValue();
20376 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20380 if (
Size != 16 ||
Op.getNumOperands() != 2)
20382 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20385 Val =
C->getSExtValue();
20389 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20398 uint64_t Val)
const {
20399 if (Constraint.
size() == 1) {
20400 switch (Constraint[0]) {
20415 }
else if (Constraint.
size() == 2) {
20416 if (Constraint ==
"DA") {
20417 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20418 int64_t LoBits =
static_cast<int32_t
>(Val);
20422 if (Constraint ==
"DB") {
20430 unsigned MaxSize)
const {
20431 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20432 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20434 MVT VT =
Op.getSimpleValueType();
20459 switch (UnalignedClassID) {
20460 case AMDGPU::VReg_64RegClassID:
20461 return AMDGPU::VReg_64_Align2RegClassID;
20462 case AMDGPU::VReg_96RegClassID:
20463 return AMDGPU::VReg_96_Align2RegClassID;
20464 case AMDGPU::VReg_128RegClassID:
20465 return AMDGPU::VReg_128_Align2RegClassID;
20466 case AMDGPU::VReg_160RegClassID:
20467 return AMDGPU::VReg_160_Align2RegClassID;
20468 case AMDGPU::VReg_192RegClassID:
20469 return AMDGPU::VReg_192_Align2RegClassID;
20470 case AMDGPU::VReg_224RegClassID:
20471 return AMDGPU::VReg_224_Align2RegClassID;
20472 case AMDGPU::VReg_256RegClassID:
20473 return AMDGPU::VReg_256_Align2RegClassID;
20474 case AMDGPU::VReg_288RegClassID:
20475 return AMDGPU::VReg_288_Align2RegClassID;
20476 case AMDGPU::VReg_320RegClassID:
20477 return AMDGPU::VReg_320_Align2RegClassID;
20478 case AMDGPU::VReg_352RegClassID:
20479 return AMDGPU::VReg_352_Align2RegClassID;
20480 case AMDGPU::VReg_384RegClassID:
20481 return AMDGPU::VReg_384_Align2RegClassID;
20482 case AMDGPU::VReg_512RegClassID:
20483 return AMDGPU::VReg_512_Align2RegClassID;
20484 case AMDGPU::VReg_1024RegClassID:
20485 return AMDGPU::VReg_1024_Align2RegClassID;
20486 case AMDGPU::AReg_64RegClassID:
20487 return AMDGPU::AReg_64_Align2RegClassID;
20488 case AMDGPU::AReg_96RegClassID:
20489 return AMDGPU::AReg_96_Align2RegClassID;
20490 case AMDGPU::AReg_128RegClassID:
20491 return AMDGPU::AReg_128_Align2RegClassID;
20492 case AMDGPU::AReg_160RegClassID:
20493 return AMDGPU::AReg_160_Align2RegClassID;
20494 case AMDGPU::AReg_192RegClassID:
20495 return AMDGPU::AReg_192_Align2RegClassID;
20496 case AMDGPU::AReg_256RegClassID:
20497 return AMDGPU::AReg_256_Align2RegClassID;
20498 case AMDGPU::AReg_512RegClassID:
20499 return AMDGPU::AReg_512_Align2RegClassID;
20500 case AMDGPU::AReg_1024RegClassID:
20501 return AMDGPU::AReg_1024_Align2RegClassID;
20517 if (Info->isEntryFunction()) {
20524 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20526 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20527 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20528 &AMDGPU::SGPR_64RegClass);
20529 Info->setSGPRForEXECCopy(SReg);
20531 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20532 Info->getStackPtrOffsetReg()));
20533 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20534 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20538 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20539 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20541 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20542 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20544 Info->limitOccupancy(MF);
20546 if (ST.isWave32() && !MF.
empty()) {
20547 for (
auto &
MBB : MF) {
20548 for (
auto &
MI :
MBB) {
20549 TII->fixImplicitOperands(
MI);
20559 if (ST.needsAlignedVGPRs()) {
20560 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
20566 if (NewClassID != -1)
20567 MRI.setRegClass(Reg,
TRI->getRegClass(NewClassID));
20576 const APInt &DemandedElts,
20578 unsigned Depth)
const {
20580 unsigned Opc =
Op.getOpcode();
20583 unsigned IID =
Op.getConstantOperandVal(0);
20585 case Intrinsic::amdgcn_mbcnt_lo:
20586 case Intrinsic::amdgcn_mbcnt_hi: {
20591 Known.Zero.setBitsFrom(
20592 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20618 unsigned MaxValue =
20625 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20629 unsigned Src1Cst = 0;
20630 if (Src1.isImm()) {
20631 Src1Cst = Src1.getImm();
20632 }
else if (Src1.isReg()) {
20636 Src1Cst = Cst->Value.getZExtValue();
20647 if (Width >= BFEWidth)
20664 unsigned Depth)
const {
20667 switch (
MI->getOpcode()) {
20668 case AMDGPU::S_BFE_I32:
20671 case AMDGPU::S_BFE_U32:
20674 case AMDGPU::S_BFE_I64:
20677 case AMDGPU::S_BFE_U64:
20680 case AMDGPU::G_INTRINSIC:
20681 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20684 case Intrinsic::amdgcn_workitem_id_x:
20687 case Intrinsic::amdgcn_workitem_id_y:
20690 case Intrinsic::amdgcn_workitem_id_z:
20693 case Intrinsic::amdgcn_mbcnt_lo:
20694 case Intrinsic::amdgcn_mbcnt_hi: {
20697 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20706 case Intrinsic::amdgcn_groupstaticsize: {
20710 Known.Zero.setHighBits(
20714 case Intrinsic::amdgcn_readfirstlane:
20715 case Intrinsic::amdgcn_readlane: {
20721 case Intrinsic::amdgcn_mul_u24:
20722 case Intrinsic::amdgcn_mul_i24: {
20729 bool SelfMultiply = LHS == RHS;
20735 LHSKnown = RHSKnown;
20743 IID == Intrinsic::amdgcn_mul_i24,
20750 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20751 Known.Zero.setHighBits(24);
20753 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20754 Known.Zero.setHighBits(16);
20756 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20759 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20761 case AMDGPU::G_AMDGPU_SMED3:
20762 case AMDGPU::G_AMDGPU_UMED3: {
20763 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20790 unsigned Depth)
const {
20799 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20820 BlockToAlign =
ML->getHeader();
20824 if (needsFetchWindowAlignment(*BlockToAlign))
20846 if (Header->getAlignment() != PrefAlign)
20847 return Header->getAlignment();
20849 unsigned LoopSize = 0;
20854 LoopSize +=
MBB->getAlignment().value() / 2;
20857 LoopSize +=
TII->getInstSizeInBytes(
MI);
20858 if (LoopSize > 192)
20863 if (LoopSize <= 64)
20866 if (LoopSize <= 128)
20867 return CacheLineAlign;
20873 auto I = Exit->getFirstNonDebugInstr();
20874 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20875 return CacheLineAlign;
20884 if (PreTerm == Pre->
begin() ||
20885 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20889 auto ExitHead = Exit->getFirstNonDebugInstr();
20890 if (ExitHead == Exit->end() ||
20891 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20896 return CacheLineAlign;
20904 if (needsFetchWindowAlignment(*
MBB))
20909bool SITargetLowering::needsFetchWindowAlignment(
20911 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20915 if (
MI.isMetaInstruction())
20918 return TII->getInstSizeInBytes(
MI) > 4;
20928 N =
N->getOperand(0).getNode();
20938 switch (
N->getOpcode()) {
20946 if (Reg.isPhysical() ||
MRI.isLiveIn(Reg))
20947 return !
TRI->isSGPRReg(
MRI, Reg);
20953 return !
TRI->isSGPRReg(
MRI, Reg);
20957 unsigned AS = L->getAddressSpace();
20967 case AMDGPUISD::ATOMIC_CMP_SWAP:
20968 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20969 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20970 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20971 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20972 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20973 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20974 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20975 case AMDGPUISD::BUFFER_ATOMIC_AND:
20976 case AMDGPUISD::BUFFER_ATOMIC_OR:
20977 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20978 case AMDGPUISD::BUFFER_ATOMIC_INC:
20979 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20980 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20981 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20982 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20983 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20989 return A->readMem() &&
A->writeMem();
21010 switch (Ty.getScalarSizeInBits()) {
21022 const APInt &DemandedElts,
21025 unsigned Depth)
const {
21026 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
21030 if (Info->getMode().DX10Clamp)
21043enum class AtomicFlushDenormalReason {
21046 IgnoreDenormalMode,
21047 FunctionFlushesDenormals
21052enum class GlobalFPAtomicLegality {
21054 AgentScopeFineGrainedRemoteMemory,
21055 EmulatedSystemScope,
21057 NoFineGrainedMemory
21064static AtomicFlushDenormalReason
21066 if (RMW->
hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
21067 return AtomicFlushDenormalReason::IgnoreDenormalMode;
21072 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
21073 : AtomicFlushDenormalReason::IEEE;
21078 GlobalFPAtomicLegality MemLegality,
21079 AtomicFlushDenormalReason DenormReason) {
21082 if (MemScope.empty())
21083 MemScope =
"system";
21086 R <<
"hardware instruction generated for atomic "
21088 <<
" at " <<
ore::NV(
"SyncScope", MemScope) <<
" scope since ";
21090 switch (MemLegality) {
21091 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
21092 R <<
"fine-grained remote memory atomics work below system scope";
21094 case GlobalFPAtomicLegality::EmulatedSystemScope:
21095 R <<
"system scope atomics are emulated in hardware";
21097 case GlobalFPAtomicLegality::NoRemoteMemory:
21098 R <<
"memory is not remote (!amdgpu.no.remote.memory)";
21100 case GlobalFPAtomicLegality::NoFineGrainedMemory:
21101 R <<
"memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
21103 case GlobalFPAtomicLegality::Illegal:
21107 switch (DenormReason) {
21108 case AtomicFlushDenormalReason::Native:
21110 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21111 R <<
", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21113 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21114 R <<
", and the floating-point environment flushes denormals";
21116 case AtomicFlushDenormalReason::IEEE:
21125 Type *EltTy = VT->getElementType();
21126 return VT->getNumElements() == 2 &&
21146 unsigned BW =
IT->getBitWidth();
21147 return BW == 32 || BW == 64;
21161 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
21162 return BW == 32 || BW == 64;
21165 if (Ty->isFloatTy() || Ty->isDoubleTy())
21169 return VT->getNumElements() == 2 &&
21170 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21178static GlobalFPAtomicLegality
21187 if (HasSystemScope) {
21188 if (
Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21190 return GlobalFPAtomicLegality::NoRemoteMemory;
21191 if (
Subtarget.hasEmulatedSystemScopeAtomics())
21192 return GlobalFPAtomicLegality::EmulatedSystemScope;
21193 }
else if (
Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21194 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21196 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory")
21197 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21198 : GlobalFPAtomicLegality::Illegal;
21211 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
21219 return STI.hasGloballyAddressableScratch()
21237 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
21241 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21242 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21252 bool HasSystemScope =
21284 if (!Subtarget->hasSubClampInsts() ||
21286 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21288 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21293 if (!
IT ||
IT->getBitWidth() != 32)
21299 if (Subtarget->hasEmulatedSystemScopeAtomics())
21315 if (!HasSystemScope &&
21316 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21328 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
21337 ConstVal && ConstVal->isNullValue() &&
21376 if (Ty->isFloatTy()) {
21381 if (Ty->isDoubleTy()) {
21402 if (Ty->isFloatTy() &&
21403 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21405 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21411 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21418 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21422 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21426 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21431 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21436 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21440 if (Ty->isFloatTy()) {
21443 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21446 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21451 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21459 if (Subtarget->hasFlatAtomicFaddF32Inst())
21468 if (Subtarget->hasLDSFPAtomicAddF32()) {
21469 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21471 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21491 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21501 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21503 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21507 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21509 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21563 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21564 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21565 : &AMDGPU::SReg_32RegClass;
21566 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21567 return TRI->getEquivalentSGPRClass(RC);
21568 if (
TRI->isSGPRClass(RC) && isDivergent) {
21569 if (Subtarget->hasGFX90AInsts())
21570 return TRI->getEquivalentAVClass(RC);
21571 return TRI->getEquivalentVGPRClass(RC);
21584 unsigned WaveSize) {
21589 if (!
IT ||
IT->getBitWidth() != WaveSize)
21594 if (!Visited.
insert(
V).second)
21596 bool Result =
false;
21597 for (
const auto *U :
V->users()) {
21599 if (
V == U->getOperand(1)) {
21604 case Intrinsic::amdgcn_if_break:
21605 case Intrinsic::amdgcn_if:
21606 case Intrinsic::amdgcn_else:
21611 if (
V == U->getOperand(0)) {
21616 case Intrinsic::amdgcn_end_cf:
21617 case Intrinsic::amdgcn_loop:
21623 Result =
hasCFUser(U, Visited, WaveSize);
21632 const Value *V)
const {
21634 if (CI->isInlineAsm()) {
21643 for (
auto &TC : TargetConstraints) {
21657 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21685 return MRI.hasOneNonDBGUse(N0);
21692 if (
I.getMetadata(
"amdgpu.noclobber"))
21694 if (
I.getMetadata(
"amdgpu.last.use"))
21696 if (
MDNode *
N =
I.getMetadata(
"amdgpu.cfs")) {
21701 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21766 Alignment = RMW->getAlign();
21779 bool FullFlatEmulation =
21781 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21782 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21783 RMW->getType()->isDoubleTy()));
21786 bool ReturnValueIsUsed = !AI->
use_empty();
21795 if (FullFlatEmulation) {
21806 std::prev(BB->
end())->eraseFromParent();
21807 Builder.SetInsertPoint(BB);
21809 Value *LoadedShared =
nullptr;
21810 if (FullFlatEmulation) {
21811 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21812 {Addr},
nullptr,
"is.shared");
21813 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21814 Builder.SetInsertPoint(SharedBB);
21815 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21821 LoadedShared = Clone;
21823 Builder.CreateBr(PhiBB);
21824 Builder.SetInsertPoint(CheckPrivateBB);
21827 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21828 {Addr},
nullptr,
"is.private");
21829 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21831 Builder.SetInsertPoint(PrivateBB);
21833 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21836 Value *LoadedPrivate;
21838 LoadedPrivate = Builder.CreateAlignedLoad(
21839 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21843 LoadedPrivate, RMW->getValOperand());
21845 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21846 RMW->isVolatile());
21854 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21857 Builder.CreateBr(PhiBB);
21859 Builder.SetInsertPoint(GlobalBB);
21863 if (FullFlatEmulation) {
21864 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21873 if (!FullFlatEmulation) {
21878 MDNode *RangeNotPrivate =
21881 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21885 Builder.CreateBr(PhiBB);
21887 Builder.SetInsertPoint(PhiBB);
21889 if (ReturnValueIsUsed) {
21892 if (FullFlatEmulation)
21893 Loaded->addIncoming(LoadedShared, SharedBB);
21894 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21895 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21896 Loaded->takeName(AI);
21899 Builder.CreateBr(ExitBB);
21903 unsigned PtrOpIdx) {
21904 Value *PtrOp =
I->getOperand(PtrOpIdx);
21911 I->setOperand(PtrOpIdx, ASCast);
21923 ConstVal && ConstVal->isNullValue() &&
21954 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21962 "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 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 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 constexpr roundingMode rmNearestTiesToEven
static constexpr const fltSemantics & IEEEhalf()
static constexpr const fltSemantics & IEEEsingle()
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,...
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.
@ 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