45#include "llvm/IR/IntrinsicsAMDGPU.h"
46#include "llvm/IR/IntrinsicsR600.h"
58#define DEBUG_TYPE "si-lower"
64 cl::desc(
"Do not align and prefetch loops"),
68 "amdgpu-use-divergent-register-indexing",
cl::Hidden,
69 cl::desc(
"Use indirect register addressing for divergent indexes"),
87 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
88 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
90 return AMDGPU::SGPR0 +
Reg;
106 TRI->getDefaultVectorSuperClassForBitWidth(32);
112 TRI->getDefaultVectorSuperClassForBitWidth(64);
150 TRI->getDefaultVectorSuperClassForBitWidth(320));
154 TRI->getDefaultVectorSuperClassForBitWidth(352));
158 TRI->getDefaultVectorSuperClassForBitWidth(384));
162 TRI->getDefaultVectorSuperClassForBitWidth(512));
169 TRI->getDefaultVectorSuperClassForBitWidth(1024));
171 if (Subtarget->has16BitInsts()) {
172 if (Subtarget->useRealTrue16Insts()) {
202 TRI->getDefaultVectorSuperClassForBitWidth(1024));
218 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
219 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
220 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
221 MVT::i1, MVT::v32i32},
225 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
226 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
227 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
228 MVT::i1, MVT::v32i32},
246 if (Subtarget->hasBF16PackedInsts()) {
310 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
317 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
318 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
319 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
322 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
323 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
324 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
328 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
329 MVT::v3i16, MVT::v4i16, MVT::Other},
334 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
350 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
351 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
352 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
353 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
354 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
355 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
356 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
357 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
390 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
404 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
418 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
432 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
446 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
461 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
462 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
465 if (Subtarget->hasPkMovB32()) {
486 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
487 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
492 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
496 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
497 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
498 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
499 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
523 if (Subtarget->hasSMemRealTime() ||
528 if (Subtarget->has16BitInsts()) {
538 if (Subtarget->hasMadMacF32Insts())
556 if (Subtarget->hasIntClamp())
559 if (Subtarget->hasAddNoCarryInsts())
565 {MVT::f32, MVT::f64},
Custom);
571 {MVT::f32, MVT::f64},
Legal);
573 if (Subtarget->haveRoundOpsF64())
603 if (Subtarget->has16BitInsts()) {
657 if (Subtarget->hasBF16TransInsts())
673 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
674 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
675 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
708 if (Subtarget->hasVCvtPkIU16F32())
711 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
718 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
838 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
839 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
840 MVT::v32f16, MVT::v32bf16},
850 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
854 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
858 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
859 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
867 if (Subtarget->hasVOP3PInsts()) {
879 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
882 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
883 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
884 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
887 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
895 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
903 {MVT::v2f16, MVT::v4f16},
Custom);
909 if (Subtarget->hasBF16PackedInsts()) {
914 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
921 if (Subtarget->hasAnyPackedFP32Ops()) {
925 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
928 if (Subtarget->hasAnyPackedFP64Ops()) {
940 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
943 if (Subtarget->hasAnyPackedU64Ops()) {
947 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
954 if (Subtarget->has16BitInsts()) {
969 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
970 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
971 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
972 MVT::v32f16, MVT::v32bf16},
977 if (Subtarget->hasVMulU64Inst())
979 else if (Subtarget->hasScalarSMulU64())
982 if (Subtarget->hasMad64_32())
985 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
988 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
990 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
993 if (Subtarget->hasMinimum3Maximum3F32())
996 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1000 if (!Subtarget->hasMinimum3Maximum3F16())
1006 if (Subtarget->hasVOP3PInsts()) {
1009 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1013 if (Subtarget->hasMinMaxI64Insts())
1018 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1019 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1024 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1025 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1026 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1027 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1031 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1032 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1033 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1034 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1049 if (Subtarget->hasBF16ConversionInsts()) {
1051 {MVT::bf16, MVT::v2bf16},
Custom);
1055 if (Subtarget->hasBF16TransInsts()) {
1059 if (Subtarget->hasOCPFP8ConversionInsts()) {
1070 if (Subtarget->hasFP8F16ConversionInsts()) {
1075 if (Subtarget->hasCvtPkF16F32Inst()) {
1077 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1128 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1169 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1182 EVT DestVT,
EVT SrcVT)
const {
1184 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1185 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1187 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1194 LLT DestTy,
LLT SrcTy)
const {
1195 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1196 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1198 SrcTy.getScalarSizeInBits() == 16 &&
1219 return Subtarget->has16BitInsts()
1225 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1229 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1251 return (NumElts + 1) / 2;
1257 return NumElts * ((
Size + 31) / 32);
1266 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1275 MVT SimpleIntermediateVT =
1277 IntermediateVT = SimpleIntermediateVT;
1278 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1279 NumIntermediates = (NumElts + 1) / 2;
1280 return (NumElts + 1) / 2;
1285 IntermediateVT = RegisterVT;
1286 NumIntermediates = NumElts;
1287 return NumIntermediates;
1292 RegisterVT = MVT::i16;
1293 IntermediateVT = ScalarVT;
1294 NumIntermediates = NumElts;
1295 return NumIntermediates;
1299 RegisterVT = MVT::i32;
1300 IntermediateVT = ScalarVT;
1301 NumIntermediates = NumElts;
1302 return NumIntermediates;
1306 RegisterVT = MVT::i32;
1307 IntermediateVT = RegisterVT;
1308 NumIntermediates = NumElts * ((
Size + 31) / 32);
1309 return NumIntermediates;
1314 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1319 unsigned MaxNumLanes) {
1320 assert(MaxNumLanes != 0);
1324 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1335 unsigned MaxNumLanes) {
1341 assert(ST->getNumContainedTypes() == 2 &&
1342 ST->getContainedType(1)->isIntegerTy(32));
1356 return MVT::amdgpuBufferFatPointer;
1358 DL.getPointerSizeInBits(AS) == 192)
1359 return MVT::amdgpuBufferStridedPointer;
1368 DL.getPointerSizeInBits(AS) == 160) ||
1370 DL.getPointerSizeInBits(AS) == 192))
1377 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1378 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1379 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1381 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1382 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1383 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1384 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1385 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1386 case Intrinsic::amdgcn_flat_load_monitor_b32:
1387 case Intrinsic::amdgcn_global_load_monitor_b32:
1389 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1390 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1391 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1392 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1393 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1394 case Intrinsic::amdgcn_flat_load_monitor_b64:
1395 case Intrinsic::amdgcn_global_load_monitor_b64:
1397 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1398 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1399 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1400 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1401 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1402 case Intrinsic::amdgcn_flat_load_monitor_b128:
1403 case Intrinsic::amdgcn_global_load_monitor_b128:
1439 unsigned IntrID)
const {
1441 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1455 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1469 if (RsrcIntr->IsImage) {
1484 Info.ptrVal = RsrcArg;
1488 if (RsrcIntr->IsImage) {
1489 unsigned MaxNumLanes = 4;
1504 std::numeric_limits<unsigned>::max());
1514 if (RsrcIntr->IsImage) {
1534 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1536 Info.memVT = MVT::i32;
1543 case Intrinsic::amdgcn_raw_buffer_load_lds:
1544 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1545 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1546 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1547 case Intrinsic::amdgcn_struct_buffer_load_lds:
1548 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1549 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1550 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1564 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1573 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1574 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1575 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1576 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1579 std::numeric_limits<unsigned>::max());
1592 case Intrinsic::amdgcn_ds_ordered_add:
1593 case Intrinsic::amdgcn_ds_ordered_swap: {
1607 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1608 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1611 Info.ptrVal =
nullptr;
1617 case Intrinsic::amdgcn_ds_append:
1618 case Intrinsic::amdgcn_ds_consume: {
1632 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1633 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1634 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1639 Info.memVT = MVT::i64;
1647 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1648 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1649 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1652 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1655 ->getElementType(0));
1664 case Intrinsic::amdgcn_global_atomic_fmin_num:
1665 case Intrinsic::amdgcn_global_atomic_fmax_num:
1666 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1667 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1668 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1679 case Intrinsic::amdgcn_cluster_load_b32:
1680 case Intrinsic::amdgcn_cluster_load_b64:
1681 case Intrinsic::amdgcn_cluster_load_b128:
1682 case Intrinsic::amdgcn_ds_load_tr6_b96:
1683 case Intrinsic::amdgcn_ds_load_tr4_b64:
1684 case Intrinsic::amdgcn_ds_load_tr8_b64:
1685 case Intrinsic::amdgcn_ds_load_tr16_b128:
1686 case Intrinsic::amdgcn_global_load_tr6_b96:
1687 case Intrinsic::amdgcn_global_load_tr4_b64:
1688 case Intrinsic::amdgcn_global_load_tr_b64:
1689 case Intrinsic::amdgcn_global_load_tr_b128:
1690 case Intrinsic::amdgcn_ds_read_tr4_b64:
1691 case Intrinsic::amdgcn_ds_read_tr6_b96:
1692 case Intrinsic::amdgcn_ds_read_tr8_b64:
1693 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1702 case Intrinsic::amdgcn_flat_load_monitor_b32:
1703 case Intrinsic::amdgcn_flat_load_monitor_b64:
1704 case Intrinsic::amdgcn_flat_load_monitor_b128:
1705 case Intrinsic::amdgcn_global_load_monitor_b32:
1706 case Intrinsic::amdgcn_global_load_monitor_b64:
1707 case Intrinsic::amdgcn_global_load_monitor_b128: {
1718 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1719 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1720 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1731 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1732 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1733 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1744 case Intrinsic::amdgcn_ds_gws_init:
1745 case Intrinsic::amdgcn_ds_gws_barrier:
1746 case Intrinsic::amdgcn_ds_gws_sema_v:
1747 case Intrinsic::amdgcn_ds_gws_sema_br:
1748 case Intrinsic::amdgcn_ds_gws_sema_p:
1749 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1759 Info.memVT = MVT::i32;
1761 Info.align =
Align(4);
1763 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1770 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1771 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1772 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1773 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1774 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1775 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1776 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1777 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1792 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1793 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1794 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1795 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1810 case Intrinsic::amdgcn_av_load_b128:
1811 case Intrinsic::amdgcn_av_store_b128: {
1812 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1814 Info.memVT = MVT::v4i32;
1816 Info.align =
Align(16);
1824 unsigned ScopeIdx = CI.
arg_size() - 1;
1828 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1832 case Intrinsic::amdgcn_load_to_lds:
1833 case Intrinsic::amdgcn_load_async_to_lds:
1834 case Intrinsic::amdgcn_global_load_lds:
1835 case Intrinsic::amdgcn_global_load_async_lds: {
1854 Width * 8 * Subtarget->getWavefrontSize());
1860 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1861 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1862 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1863 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1873 Info.memVT = MVT::i32;
1875 Info.align =
Align(4);
1881 case Intrinsic::amdgcn_s_prefetch_data:
1882 case Intrinsic::amdgcn_s_prefetch_inst:
1883 case Intrinsic::amdgcn_flat_prefetch:
1884 case Intrinsic::amdgcn_global_prefetch: {
1900 case Intrinsic::amdgcn_addrspacecast_nonnull: {
1903 unsigned SrcAS =
I.getOperand(0)->getType()->getPointerAddressSpace();
1904 unsigned DstAS =
I.getType()->getPointerAddressSpace();
1916 Type *&AccessTy)
const {
1917 Value *Ptr =
nullptr;
1918 switch (
II->getIntrinsicID()) {
1919 case Intrinsic::amdgcn_cluster_load_b128:
1920 case Intrinsic::amdgcn_cluster_load_b64:
1921 case Intrinsic::amdgcn_cluster_load_b32:
1922 case Intrinsic::amdgcn_ds_append:
1923 case Intrinsic::amdgcn_ds_consume:
1924 case Intrinsic::amdgcn_ds_load_tr8_b64:
1925 case Intrinsic::amdgcn_ds_load_tr16_b128:
1926 case Intrinsic::amdgcn_ds_load_tr4_b64:
1927 case Intrinsic::amdgcn_ds_load_tr6_b96:
1928 case Intrinsic::amdgcn_ds_read_tr4_b64:
1929 case Intrinsic::amdgcn_ds_read_tr6_b96:
1930 case Intrinsic::amdgcn_ds_read_tr8_b64:
1931 case Intrinsic::amdgcn_ds_read_tr16_b64:
1932 case Intrinsic::amdgcn_ds_ordered_add:
1933 case Intrinsic::amdgcn_ds_ordered_swap:
1934 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1935 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1936 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1937 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1938 case Intrinsic::amdgcn_global_atomic_fmax_num:
1939 case Intrinsic::amdgcn_global_atomic_fmin_num:
1940 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1941 case Intrinsic::amdgcn_global_load_tr_b64:
1942 case Intrinsic::amdgcn_global_load_tr_b128:
1943 case Intrinsic::amdgcn_global_load_tr4_b64:
1944 case Intrinsic::amdgcn_global_load_tr6_b96:
1945 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1946 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1947 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1948 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1949 case Intrinsic::amdgcn_av_load_b128:
1950 case Intrinsic::amdgcn_av_store_b128:
1951 Ptr =
II->getArgOperand(0);
1953 case Intrinsic::amdgcn_load_to_lds:
1954 case Intrinsic::amdgcn_load_async_to_lds:
1955 case Intrinsic::amdgcn_global_load_lds:
1956 case Intrinsic::amdgcn_global_load_async_lds:
1957 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1958 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1959 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1960 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1961 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1962 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1963 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1964 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1965 Ptr =
II->getArgOperand(1);
1970 AccessTy =
II->getType();
1976 unsigned AddrSpace)
const {
1977 if (!Subtarget->hasFlatInstOffsets()) {
1984 FlatAddrSpace FlatVariant =
1987 : FlatAddrSpace::FLAT;
1989 return AM.
Scale == 0 &&
1990 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
1991 AM.
BaseOffs, AddrSpace, FlatVariant));
1995 if (Subtarget->hasFlatGlobalInsts())
1998 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2011 return isLegalMUBUFAddressingMode(AM);
2014bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2025 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2037 if (AM.HasBaseReg) {
2069 return isLegalMUBUFAddressingMode(AM);
2071 if (!Subtarget->hasScalarSubwordLoads()) {
2076 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2124 return Subtarget->hasFlatScratchEnabled()
2126 : isLegalMUBUFAddressingMode(AM);
2173 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2182 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2185 Align RequiredAlignment(
2187 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2188 Alignment < RequiredAlignment)
2203 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2209 RequiredAlignment =
Align(4);
2211 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2227 *IsFast = (Alignment >= RequiredAlignment) ? 64
2228 : (Alignment <
Align(4)) ? 32
2235 if (!Subtarget->hasDS96AndDS128())
2241 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2250 *IsFast = (Alignment >= RequiredAlignment) ? 96
2251 : (Alignment <
Align(4)) ? 32
2258 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2264 RequiredAlignment =
Align(8);
2266 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2275 *IsFast = (Alignment >= RequiredAlignment) ? 128
2276 : (Alignment <
Align(4)) ? 32
2293 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2295 return Alignment >= RequiredAlignment ||
2296 Subtarget->hasUnalignedDSAccessEnabled();
2304 bool AlignedBy4 = Alignment >=
Align(4);
2305 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2307 *IsFast = AlignedBy4 ?
Size : 1;
2312 *IsFast = AlignedBy4;
2323 return Alignment >=
Align(4) ||
2324 Subtarget->hasUnalignedBufferAccessEnabled();
2337 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2352 return Size >= 32 && Alignment >=
Align(4);
2357 unsigned *IsFast)
const {
2359 Alignment, Flags, IsFast);
2364 const AttributeList &FuncAttributes)
const {
2370 if (
Op.size() >= 16 &&
2374 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2392 unsigned DestAS)
const {
2395 Subtarget->hasGloballyAddressableScratch()) {
2426 unsigned Index)
const {
2440 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2445 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2480 auto [InputPtrReg, RC, ArgTy] =
2496 const SDLoc &SL)
const {
2503 const SDLoc &SL)
const {
2506 std::optional<uint32_t> KnownSize =
2508 if (KnownSize.has_value())
2535 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2550SDValue SITargetLowering::lowerKernargMemParameter(
2555 MachinePointerInfo PtrInfo =
2564 int64_t OffsetDiff =
Offset - AlignDownOffset;
2570 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2581 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2586 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2600 const SDLoc &SL)
const {
2669 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2672 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2673 if (ConvertedVal == ArgValue)
2674 return ConvertedVal;
2679SDValue SITargetLowering::lowerWorkGroupId(
2684 if (!Subtarget->hasClusters())
2685 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2693 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2694 SDLoc SL(ClusterIdXYZ);
2695 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2698 SDValue ClusterWorkGroupIdXYZ =
2699 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2709 return ClusterIdXYZ;
2711 using namespace AMDGPU::Hwreg;
2715 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2726SDValue SITargetLowering::getPreloadedValue(
2729 const ArgDescriptor *
Reg =
nullptr;
2734 const ArgDescriptor WorkGroupIDX =
2742 const ArgDescriptor WorkGroupIDZ =
2744 const ArgDescriptor ClusterWorkGroupIDX =
2746 const ArgDescriptor ClusterWorkGroupIDY =
2748 const ArgDescriptor ClusterWorkGroupIDZ =
2750 const ArgDescriptor ClusterWorkGroupMaxIDX =
2752 const ArgDescriptor ClusterWorkGroupMaxIDY =
2754 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2756 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2759 auto LoadConstant = [&](
unsigned N) {
2763 if (Subtarget->hasArchitectedSGPRs() &&
2770 Reg = &WorkGroupIDX;
2771 RC = &AMDGPU::SReg_32RegClass;
2775 Reg = &WorkGroupIDY;
2776 RC = &AMDGPU::SReg_32RegClass;
2780 Reg = &WorkGroupIDZ;
2781 RC = &AMDGPU::SReg_32RegClass;
2785 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2786 return LoadConstant(0);
2787 Reg = &ClusterWorkGroupIDX;
2788 RC = &AMDGPU::SReg_32RegClass;
2792 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2793 return LoadConstant(0);
2794 Reg = &ClusterWorkGroupIDY;
2795 RC = &AMDGPU::SReg_32RegClass;
2799 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2800 return LoadConstant(0);
2801 Reg = &ClusterWorkGroupIDZ;
2802 RC = &AMDGPU::SReg_32RegClass;
2807 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2808 Reg = &ClusterWorkGroupMaxIDX;
2809 RC = &AMDGPU::SReg_32RegClass;
2814 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2815 Reg = &ClusterWorkGroupMaxIDY;
2816 RC = &AMDGPU::SReg_32RegClass;
2821 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2822 Reg = &ClusterWorkGroupMaxIDZ;
2823 RC = &AMDGPU::SReg_32RegClass;
2827 Reg = &ClusterWorkGroupMaxFlatID;
2828 RC = &AMDGPU::SReg_32RegClass;
2859 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2863 "vector type argument should have been split");
2868 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2876 "unexpected vector split in ps argument type");
2890 Info->markPSInputAllocated(PSInputNum);
2892 Info->markPSInputEnabled(PSInputNum);
2908 if (Info.hasWorkItemIDX()) {
2914 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2918 if (Info.hasWorkItemIDY()) {
2919 assert(Info.hasWorkItemIDX());
2920 if (Subtarget->hasPackedTID()) {
2921 Info.setWorkItemIDY(
2924 unsigned Reg = AMDGPU::VGPR1;
2932 if (Info.hasWorkItemIDZ()) {
2933 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2934 if (Subtarget->hasPackedTID()) {
2935 Info.setWorkItemIDZ(
2938 unsigned Reg = AMDGPU::VGPR2;
2958 if (RegIdx == ArgVGPRs.
size()) {
2965 unsigned Reg = ArgVGPRs[RegIdx];
2977 unsigned NumArgRegs) {
2980 if (RegIdx == ArgSGPRs.
size())
2983 unsigned Reg = ArgSGPRs[RegIdx];
3025 const unsigned Mask = 0x3ff;
3028 if (Info.hasWorkItemIDX()) {
3030 Info.setWorkItemIDX(Arg);
3033 if (Info.hasWorkItemIDY()) {
3035 Info.setWorkItemIDY(Arg);
3038 if (Info.hasWorkItemIDZ())
3050 const unsigned Mask = 0x3ff;
3059 auto &
ArgInfo = Info.getArgInfo();
3071 if (Info.hasImplicitArgPtr())
3079 if (Info.hasWorkGroupIDX())
3082 if (Info.hasWorkGroupIDY())
3085 if (Info.hasWorkGroupIDZ())
3088 if (Info.hasLDSKernelId())
3099 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3100 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3106 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3107 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3112 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3113 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3119 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3125 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3134 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3139 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3140 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3145 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3146 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3161 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3163 bool InPreloadSequence =
true;
3165 bool AlignedForImplictArgs =
false;
3166 unsigned ImplicitArgOffset = 0;
3167 for (
auto &Arg :
F.args()) {
3168 if (!InPreloadSequence || !Arg.hasInRegAttr())
3171 unsigned ArgIdx = Arg.getArgNo();
3174 if (InIdx < Ins.
size() &&
3175 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3178 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3179 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3181 assert(ArgLocs[ArgIdx].isMemLoc());
3182 auto &ArgLoc = ArgLocs[InIdx];
3184 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3186 unsigned NumAllocSGPRs =
3187 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3190 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3191 if (!AlignedForImplictArgs) {
3193 alignTo(LastExplicitArgOffset,
3194 Subtarget->getAlignmentForImplicitArgPtr()) -
3195 LastExplicitArgOffset;
3196 AlignedForImplictArgs =
true;
3198 ArgOffset += ImplicitArgOffset;
3202 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3203 assert(InIdx >= 1 &&
"No previous SGPR");
3204 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3205 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3209 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3210 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3213 InPreloadSequence =
false;
3219 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3221 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3223 if (PreloadRegs->
size() > 1)
3224 RC = &AMDGPU::SGPR_32RegClass;
3225 for (
auto &Reg : *PreloadRegs) {
3231 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3240 if (Info.hasLDSKernelId()) {
3241 Register Reg = Info.addLDSKernelId();
3242 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3251 bool IsShader)
const {
3252 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3253 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3259 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3261 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3265 unsigned NumRequiredSystemSGPRs =
3266 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3267 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3268 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3269 Register Reg = Info.addReservedUserSGPR();
3270 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3275 if (!HasArchitectedSGPRs) {
3276 if (Info.hasWorkGroupIDX()) {
3277 Register Reg = Info.addWorkGroupIDX();
3278 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3282 if (Info.hasWorkGroupIDY()) {
3283 Register Reg = Info.addWorkGroupIDY();
3284 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3288 if (Info.hasWorkGroupIDZ()) {
3289 Register Reg = Info.addWorkGroupIDZ();
3290 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3295 if (Info.hasWorkGroupInfo()) {
3296 Register Reg = Info.addWorkGroupInfo();
3297 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3301 if (Info.hasPrivateSegmentWaveByteOffset()) {
3303 unsigned PrivateSegmentWaveByteOffsetReg;
3306 PrivateSegmentWaveByteOffsetReg =
3307 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3311 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3313 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3316 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3318 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3319 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3322 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3323 Info.getNumPreloadedSGPRs() >= 16);
3338 if (HasStackObjects)
3339 Info.setHasNonSpillStackObjects(
true);
3344 HasStackObjects =
true;
3348 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3350 if (!ST.hasFlatScratchEnabled()) {
3351 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3358 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3360 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3370 Info.setScratchRSrcReg(ReservedBufferReg);
3389 if (!MRI.
isLiveIn(AMDGPU::SGPR32)) {
3390 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3397 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3399 Info.setStackPtrOffsetReg(
Reg);
3404 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3411 if (ST.getFrameLowering()->hasFP(MF)) {
3412 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3428 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3437 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3438 RC = &AMDGPU::SGPR_64RegClass;
3439 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3440 RC = &AMDGPU::SGPR_32RegClass;
3446 Entry->addLiveIn(*
I);
3451 for (
auto *Exit : Exits)
3453 TII->get(TargetOpcode::COPY), *
I)
3468 bool IsError =
false;
3472 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3490 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3491 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3493 if (!Subtarget->hasFlatScratchEnabled())
3498 !Subtarget->hasArchitectedSGPRs())
3499 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3500 !Info->hasWorkGroupIDZ());
3503 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3521 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3522 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3525 Info->markPSInputAllocated(0);
3526 Info->markPSInputEnabled(0);
3528 if (Subtarget->isAmdPalOS()) {
3537 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3538 if ((PsInputBits & 0x7F) == 0 ||
3539 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3542 }
else if (IsKernel) {
3543 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3555 if (IsKernel && Subtarget->hasKernargPreload())
3559 }
else if (!IsGraphics) {
3564 if (!Subtarget->hasFlatScratchEnabled())
3576 Info->setNumWaveDispatchSGPRs(
3578 Info->setNumWaveDispatchVGPRs(
3580 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3581 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3586 if (IsWholeWaveFunc) {
3588 {MVT::i1, MVT::Other}, Chain);
3600 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3611 if (IsEntryFunc && VA.
isMemLoc()) {
3634 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3638 int64_t OffsetDiff =
Offset - AlignDownOffset;
3645 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3648 Register VReg = MRI.getLiveInVirtReg(Reg);
3656 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3657 Ins[i].Flags.isSExt(), &Ins[i]);
3665 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3668 if (PreloadRegs.
size() == 1) {
3669 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3674 TRI->getRegSizeInBits(*RC)));
3682 for (
auto Reg : PreloadRegs) {
3683 Register VReg = MRI.getLiveInVirtReg(Reg);
3689 PreloadRegs.size()),
3706 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3707 Ins[i].Flags.isSExt(), &Ins[i]);
3719 "hidden argument in kernel signature was not preloaded",
3725 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3726 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3746 if (!IsEntryFunc && VA.
isMemLoc()) {
3747 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3758 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3759 RC = &AMDGPU::VGPR_32RegClass;
3760 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3761 RC = &AMDGPU::SGPR_32RegClass;
3767 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3773 ReadFirstLane, Val);
3782 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3791 Info->setBytesInStackArgArea(StackArgSize);
3793 return Chains.
empty() ? Chain
3802 const Type *RetTy)
const {
3810 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3815 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3816 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3817 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3818 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3841 Info->setIfReturnsVoid(Outs.
empty());
3842 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3861 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3862 ++
I, ++RealRVLocIdx) {
3866 SDValue Arg = OutVals[RealRVLocIdx];
3889 ReadFirstLane, Arg);
3896 if (!Info->isEntryFunction()) {
3902 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3904 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3917 unsigned Opc = AMDGPUISD::ENDPGM;
3919 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3920 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3921 : AMDGPUISD::RET_GLUE;
4026 const auto [OutgoingArg, ArgRC, ArgTy] =
4031 const auto [IncomingArg, IncomingArgRC, Ty] =
4033 assert(IncomingArgRC == ArgRC);
4036 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4044 InputReg = getImplicitArgPtr(DAG,
DL);
4046 std::optional<uint32_t> Id =
4048 if (Id.has_value()) {
4059 if (OutgoingArg->isRegister()) {
4060 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4061 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4064 unsigned SpecialArgOffset =
4075 auto [OutgoingArg, ArgRC, Ty] =
4078 std::tie(OutgoingArg, ArgRC, Ty) =
4081 std::tie(OutgoingArg, ArgRC, Ty) =
4096 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4097 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4098 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4103 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4111 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4121 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4130 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4131 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4142 : IncomingArgY ? *IncomingArgY
4149 if (OutgoingArg->isRegister()) {
4151 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4177 if (Callee->isDivergent())
4184 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4188 if (!CallerPreserved)
4191 bool CCMatch = CallerCC == CalleeCC;
4204 if (Arg.hasByValAttr())
4218 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4219 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4228 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4241 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4243 if (!CCVA.isRegLoc())
4248 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4250 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4274enum ChainCallArgIdx {
4296 bool UsesDynamicVGPRs =
false;
4297 if (IsChainCallConv) {
4302 auto RequestedExecIt =
4304 return Arg.OrigArgIndex == 2;
4306 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4308 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4311 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4314 "Haven't popped all the special args");
4317 CLI.
Args[ChainCallArgIdx::Exec];
4318 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4326 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4328 ChainCallSpecialArgs.
push_back(Arg.Node);
4331 PushNodeOrTargetConstant(RequestedExecArg);
4337 if (FlagsValue.
isZero()) {
4338 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4340 "no additional args allowed if flags == 0");
4342 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4346 if (!Subtarget->isWave32()) {
4348 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4351 UsesDynamicVGPRs =
true;
4352 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4353 CLI.
Args.end(), PushNodeOrTargetConstant);
4362 bool IsSibCall =
false;
4376 "unsupported call to variadic function ");
4384 "unsupported required tail call to function ");
4389 Outs, OutVals, Ins, DAG);
4393 "site marked musttail or on llvm.amdgcn.cs.chain");
4400 if (!TailCallOpt && IsTailCall)
4424 if (!Subtarget->hasFlatScratchEnabled())
4445 auto *
TRI = Subtarget->getRegisterInfo();
4452 if (!IsSibCall || IsChainCallConv) {
4453 if (!Subtarget->hasFlatScratchEnabled()) {
4459 RegsToPass.emplace_back(IsChainCallConv
4460 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4461 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4468 const unsigned NumSpecialInputs = RegsToPass.size();
4470 MVT PtrVT = MVT::i32;
4473 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4501 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4509 int32_t
Offset = LocMemOffset;
4516 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4522 ? Flags.getNonZeroByValAlign()
4549 if (Outs[i].Flags.isByVal()) {
4551 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4554 Outs[i].Flags.getNonZeroByValAlign(),
4555 Outs[i].Flags.getNonZeroByValAlign(),
4557 nullptr, std::nullopt, DstInfo,
4563 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4569 if (!MemOpChains.
empty())
4585 unsigned ArgIdx = 0;
4586 for (
auto [Reg, Val] : RegsToPass) {
4587 if (ArgIdx++ >= NumSpecialInputs &&
4588 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4614 if (IsTailCall && !IsSibCall) {
4619 std::vector<SDValue>
Ops({Chain});
4625 Ops.push_back(Callee);
4642 Ops.push_back(Callee);
4653 if (IsChainCallConv)
4658 for (
auto &[Reg, Val] : RegsToPass)
4662 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4663 assert(Mask &&
"Missing call preserved mask for calling convention");
4673 MVT::Glue, GlueOps),
4678 Ops.push_back(InGlue);
4684 unsigned OPC = AMDGPUISD::TC_RETURN;
4687 OPC = AMDGPUISD::TC_RETURN_GFX;
4691 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4692 : AMDGPUISD::TC_RETURN_CHAIN;
4698 if (Info->isWholeWaveFunction())
4699 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4706 Chain =
Call.getValue(0);
4707 InGlue =
Call.getValue(1);
4709 uint64_t CalleePopBytes = NumBytes;
4730 EVT VT =
Op.getValueType();
4744 "Stack grows upwards for AMDGPU");
4746 Chain = BaseAddr.getValue(1);
4748 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4749 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4752 if (Alignment > StackAlign) {
4754 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4755 uint64_t StackAlignMask = ScaledAlignment - 1;
4762 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4771 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4782 if (!HasFlatScratch) {
4785 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4802 if (
Op.getValueType() != MVT::i32)
4821 assert(
Op.getValueType() == MVT::i32);
4830 Op.getOperand(0), IntrinID, GetRoundBothImm);
4864 SDValue RoundModeTimesNumBits =
4884 TableEntry, EnumOffset);
4900 static_cast<uint32_t>(ConstMode->getZExtValue()),
4912 if (UseReducedTable) {
4918 SDValue RoundModeTimesNumBits =
4938 SDValue RoundModeTimesNumBits =
4947 NewMode = TruncTable;
4956 ReadFirstLaneID, NewMode);
4969 IntrinID, RoundBothImm, NewMode);
4975 if (
Op->isDivergent() &&
4976 (!Subtarget->hasVmemPrefInsts() || !
Op.getConstantOperandVal(4)))
4986 if (Subtarget->hasSafeSmemPrefetch())
4994 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5003 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5004 EVT SrcVT = Src.getValueType();
5013 EVT DstVT =
Op.getValueType();
5022 if (
Op.getValueType() != MVT::i64)
5036 Op.getOperand(0), IntrinID, ModeHwRegImm);
5038 Op.getOperand(0), IntrinID, TrapHwRegImm);
5052 if (
Op.getOperand(1).getValueType() != MVT::i64)
5064 ReadFirstLaneID, NewModeReg);
5066 ReadFirstLaneID, NewTrapReg);
5068 unsigned ModeHwReg =
5071 unsigned TrapHwReg =
5079 IntrinID, ModeHwRegImm, NewModeReg);
5082 IntrinID, TrapHwRegImm, NewTrapReg);
5091 .
Case(
"m0", AMDGPU::M0)
5092 .
Case(
"exec", AMDGPU::EXEC)
5093 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5094 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5095 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5096 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5097 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5102 if (!Subtarget->hasFlatScrRegister() &&
5103 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5105 "\" for subtarget."));
5110 case AMDGPU::EXEC_LO:
5111 case AMDGPU::EXEC_HI:
5112 case AMDGPU::FLAT_SCR_LO:
5113 case AMDGPU::FLAT_SCR_HI:
5118 case AMDGPU::FLAT_SCR:
5137 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5146static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5168 auto Next = std::next(
I);
5179 MBB.addSuccessor(LoopBB);
5181 return std::pair(LoopBB, RemainderBB);
5188 auto I =
MI.getIterator();
5189 auto E = std::next(
I);
5211 Src->setIsKill(
false);
5221 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5230 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5254 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5255 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5277 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5284 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5288 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5298 if (UseGPRIdxMode) {
5300 SGPRIdxReg = CurrentIdxReg;
5303 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5313 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5344 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5345 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5353 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5372 InitResultReg, DstReg, PhiReg, TmpExec,
5373 Offset, UseGPRIdxMode, SGPRIdxReg);
5379 LoopBB->removeSuccessor(RemainderBB);
5381 LoopBB->addSuccessor(LandingPad);
5392static std::pair<unsigned, int>
5396 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5401 return std::pair(AMDGPU::sub0,
Offset);
5458 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5459 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5465 std::tie(SubReg,
Offset) =
5468 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5471 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5475 if (UseGPRIdxMode) {
5482 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5491 .
addReg(SrcReg, {}, SubReg)
5495 MI.eraseFromParent();
5511 UseGPRIdxMode, SGPRIdxReg);
5515 if (UseGPRIdxMode) {
5517 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5519 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5524 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5525 .
addReg(SrcReg, {}, SubReg)
5529 MI.eraseFromParent();
5546 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5554 std::tie(SubReg,
Offset) =
5556 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5558 if (Idx->
getReg() == AMDGPU::NoRegister) {
5569 MI.eraseFromParent();
5574 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5578 if (UseGPRIdxMode) {
5582 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5591 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5592 TRI.getRegSizeInBits(*VecRC), 32,
false);
5598 MI.eraseFromParent();
5612 UseGPRIdxMode, SGPRIdxReg);
5615 if (UseGPRIdxMode) {
5617 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5619 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5625 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5626 TRI.getRegSizeInBits(*VecRC), 32,
false);
5627 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5633 MI.eraseFromParent();
5649 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5650 if (ST.hasScalarAddSub64()) {
5651 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5661 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5662 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5665 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5667 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5670 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5672 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5674 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5675 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5684 MI.eraseFromParent();
5698 Register SrcCond =
MI.getOperand(3).getReg();
5706 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5708 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5710 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5712 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5715 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5717 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5720 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5722 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5725 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5727 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5749 MI.eraseFromParent();
5754 case AMDGPU::S_MIN_U32:
5755 return std::numeric_limits<uint32_t>::max();
5756 case AMDGPU::S_MIN_I32:
5757 return std::numeric_limits<int32_t>::max();
5758 case AMDGPU::S_MAX_U32:
5759 return std::numeric_limits<uint32_t>::min();
5760 case AMDGPU::S_MAX_I32:
5761 return std::numeric_limits<int32_t>::min();
5762 case AMDGPU::V_ADD_F32_e64:
5764 case AMDGPU::V_SUB_F32_e64:
5766 case AMDGPU::S_ADD_I32:
5767 case AMDGPU::S_SUB_I32:
5768 case AMDGPU::S_OR_B32:
5769 case AMDGPU::S_XOR_B32:
5770 return std::numeric_limits<uint32_t>::min();
5771 case AMDGPU::S_AND_B32:
5772 return std::numeric_limits<uint32_t>::max();
5773 case AMDGPU::V_MIN_F32_e64:
5774 case AMDGPU::V_MAX_F32_e64:
5776 case AMDGPU::V_CMP_LT_U64_e64:
5777 return std::numeric_limits<uint64_t>::max();
5778 case AMDGPU::V_CMP_LT_I64_e64:
5779 return std::numeric_limits<int64_t>::max();
5780 case AMDGPU::V_CMP_GT_U64_e64:
5781 return std::numeric_limits<uint64_t>::min();
5782 case AMDGPU::V_CMP_GT_I64_e64:
5783 return std::numeric_limits<int64_t>::min();
5784 case AMDGPU::V_MIN_F64_e64:
5785 case AMDGPU::V_MAX_F64_e64:
5786 case AMDGPU::V_MIN_NUM_F64_e64:
5787 case AMDGPU::V_MAX_NUM_F64_e64:
5788 return 0x7FF8000000000000;
5789 case AMDGPU::S_ADD_U64_PSEUDO:
5790 case AMDGPU::S_SUB_U64_PSEUDO:
5791 case AMDGPU::S_OR_B64:
5792 case AMDGPU::S_XOR_B64:
5793 return std::numeric_limits<uint64_t>::min();
5794 case AMDGPU::S_AND_B64:
5795 return std::numeric_limits<uint64_t>::max();
5796 case AMDGPU::V_ADD_F64_e64:
5797 case AMDGPU::V_ADD_F64_pseudo_e64:
5798 return 0x8000000000000000;
5805 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5806 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5807 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5808 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5809 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5810 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5811 Opc == AMDGPU::V_SUB_F32_e64;
5815 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5816 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5817 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5818 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5819 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5822static std::tuple<unsigned, unsigned>
5826 case AMDGPU::S_MIN_U32:
5827 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5829 case AMDGPU::S_MIN_I32:
5830 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5832 case AMDGPU::S_MAX_U32:
5833 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5835 case AMDGPU::S_MAX_I32:
5836 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5838 case AMDGPU::S_ADD_I32:
5839 case AMDGPU::S_SUB_I32:
5840 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5841 : AMDGPU::V_ADD_CO_U32_dpp;
5843 case AMDGPU::S_AND_B32:
5844 DPPOpc = AMDGPU::V_AND_B32_dpp;
5846 case AMDGPU::S_OR_B32:
5847 DPPOpc = AMDGPU::V_OR_B32_dpp;
5849 case AMDGPU::S_XOR_B32:
5850 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5852 case AMDGPU::V_ADD_F32_e64:
5853 case AMDGPU::V_SUB_F32_e64:
5854 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5856 case AMDGPU::V_MIN_F32_e64:
5857 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5859 case AMDGPU::V_MAX_F32_e64:
5860 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5862 case AMDGPU::V_CMP_LT_U64_e64:
5863 case AMDGPU::V_CMP_LT_I64_e64:
5864 case AMDGPU::V_CMP_GT_U64_e64:
5865 case AMDGPU::V_CMP_GT_I64_e64:
5866 case AMDGPU::S_ADD_U64_PSEUDO:
5867 case AMDGPU::S_SUB_U64_PSEUDO:
5868 case AMDGPU::S_AND_B64:
5869 case AMDGPU::S_OR_B64:
5870 case AMDGPU::S_XOR_B64:
5871 case AMDGPU::V_MIN_NUM_F64_e64:
5872 case AMDGPU::V_MIN_F64_e64:
5873 case AMDGPU::V_MAX_NUM_F64_e64:
5874 case AMDGPU::V_MAX_F64_e64:
5875 case AMDGPU::V_ADD_F64_pseudo_e64:
5876 case AMDGPU::V_ADD_F64_e64:
5877 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5882 unsigned ClampOpc =
Opc;
5883 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5884 if (
Opc == AMDGPU::S_SUB_I32)
5885 ClampOpc = AMDGPU::S_ADD_I32;
5886 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5887 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5888 else if (
Opc == AMDGPU::S_AND_B64)
5889 ClampOpc = AMDGPU::V_AND_B32_e64;
5890 else if (
Opc == AMDGPU::S_OR_B64)
5891 ClampOpc = AMDGPU::V_OR_B32_e64;
5892 else if (
Opc == AMDGPU::S_XOR_B64)
5893 ClampOpc = AMDGPU::V_XOR_B32_e64;
5895 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5897 return {DPPOpc, ClampOpc};
5900static std::pair<Register, Register>
5907 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5909 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5911 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5912 return {Op1L, Op1H};
5928 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
5929 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
5931 unsigned MIOpc =
MI.getOpcode();
5945 case AMDGPU::S_MIN_U32:
5946 case AMDGPU::S_MIN_I32:
5947 case AMDGPU::V_MIN_F32_e64:
5948 case AMDGPU::S_MAX_U32:
5949 case AMDGPU::S_MAX_I32:
5950 case AMDGPU::V_MAX_F32_e64:
5951 case AMDGPU::S_AND_B32:
5952 case AMDGPU::S_OR_B32: {
5958 case AMDGPU::V_CMP_LT_U64_e64:
5959 case AMDGPU::V_CMP_LT_I64_e64:
5960 case AMDGPU::V_CMP_GT_U64_e64:
5961 case AMDGPU::V_CMP_GT_I64_e64:
5962 case AMDGPU::V_MIN_F64_e64:
5963 case AMDGPU::V_MIN_NUM_F64_e64:
5964 case AMDGPU::V_MAX_F64_e64:
5965 case AMDGPU::V_MAX_NUM_F64_e64:
5966 case AMDGPU::S_AND_B64:
5967 case AMDGPU::S_OR_B64: {
5973 case AMDGPU::S_XOR_B32:
5974 case AMDGPU::S_XOR_B64:
5975 case AMDGPU::S_ADD_I32:
5976 case AMDGPU::S_ADD_U64_PSEUDO:
5977 case AMDGPU::V_ADD_F32_e64:
5978 case AMDGPU::V_ADD_F64_e64:
5979 case AMDGPU::V_ADD_F64_pseudo_e64:
5980 case AMDGPU::S_SUB_I32:
5981 case AMDGPU::S_SUB_U64_PSEUDO:
5982 case AMDGPU::V_SUB_F32_e64: {
5989 bool IsWave32 = ST.isWave32();
5990 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
5991 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
5992 unsigned BitCountOpc =
5993 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
5997 auto NewAccumulator =
6002 case AMDGPU::S_XOR_B32:
6003 case AMDGPU::S_XOR_B64: {
6012 .
addReg(NewAccumulator->getOperand(0).getReg())
6015 if (
Opc == AMDGPU::S_XOR_B32) {
6032 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6036 case AMDGPU::S_SUB_I32: {
6045 .
addReg(NewAccumulator->getOperand(0).getReg());
6048 case AMDGPU::S_ADD_I32: {
6051 .
addReg(NewAccumulator->getOperand(0).getReg());
6054 case AMDGPU::S_ADD_U64_PSEUDO:
6055 case AMDGPU::S_SUB_U64_PSEUDO: {
6071 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6074 .
addReg(NewAccumulator->getOperand(0).getReg())
6084 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6086 : NewAccumulator->getOperand(0).getReg();
6090 if (ST.hasScalarMulHiInsts()) {
6101 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6104 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6111 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6117 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6123 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6126 case AMDGPU::V_ADD_F32_e64:
6127 case AMDGPU::V_ADD_F64_e64:
6128 case AMDGPU::V_ADD_F64_pseudo_e64:
6129 case AMDGPU::V_SUB_F32_e64: {
6136 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6137 : AMDGPU::V_CVT_F64_I32_e64),
6139 .
addReg(NewAccumulator->getOperand(0).getReg())
6144 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6145 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6148 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6150 ? AMDGPU::V_MUL_F64_pseudo_e64
6151 : AMDGPU::V_MUL_F64_e64;
6161 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6178 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6190 bool NeedsMovDPP = !is32BitOpc;
6195 bool IsWave32 = ST.isWave32();
6196 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6197 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6198 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6224 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6228 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6229 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6238 I = ComputeLoop->begin();
6240 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6244 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6248 I = ComputeLoop->end();
6252 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6257 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6258 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6259 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6260 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6262 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6264 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6266 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6267 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6271 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6275 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6277 OpDstReg = VgprResultReg;
6278 LaneValueReg = LaneValVgpr;
6281 if (hasSrc0Modifier)
6283 OpInstr.addReg(AccumulatorReg);
6284 if (hasSrc1Modifier)
6286 OpInstr.addReg(LaneValueReg);
6293 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6294 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6308 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6312 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6316 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6317 LaneValueLoReg, LaneValueHiReg);
6319 case AMDGPU::S_OR_B64:
6320 case AMDGPU::S_AND_B64:
6321 case AMDGPU::S_XOR_B64: {
6324 .
addReg(LaneValue->getOperand(0).getReg())
6328 case AMDGPU::V_CMP_GT_I64_e64:
6329 case AMDGPU::V_CMP_GT_U64_e64:
6330 case AMDGPU::V_CMP_LT_I64_e64:
6331 case AMDGPU::V_CMP_LT_U64_e64: {
6336 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6338 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6342 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6345 .
addReg(LaneValue->getOperand(0).getReg())
6346 .
addReg(AccumulatorVReg);
6348 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6349 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6353 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6354 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6355 .
addReg(LaneValue->getOperand(0).getReg())
6359 case AMDGPU::V_MIN_F64_e64:
6360 case AMDGPU::V_MIN_NUM_F64_e64:
6361 case AMDGPU::V_MAX_F64_e64:
6362 case AMDGPU::V_MAX_NUM_F64_e64:
6363 case AMDGPU::V_ADD_F64_e64:
6364 case AMDGPU::V_ADD_F64_pseudo_e64: {
6366 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6368 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6375 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6378 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6384 .
addReg(LaneValue->getOperand(0).getReg())
6391 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6394 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6396 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6398 ReadLaneLo.addReg(Op1L);
6399 ReadLaneHi.addReg(Op1H);
6401 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6404 case AMDGPU::S_ADD_U64_PSEUDO:
6405 case AMDGPU::S_SUB_U64_PSEUDO: {
6408 .
addReg(LaneValue->getOperand(0).getReg());
6416 unsigned BITSETOpc =
6417 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6418 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6424 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6428 if (!ST.hasScalarCompareEq64()) {
6431 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6433 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6436 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6437 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6439 SetSCCInstr.
addReg(NewActiveBitsReg);
6440 if (ST.hasScalarCompareEq64())
6443 SetSCCInstr.
addReg(NewActiveBitsReg);
6444 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6449 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6466 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6470 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6471 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6474 auto IdentityCopyInstr =
6478 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6479 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6494 if (isFPOp && !NeedsMovDPP)
6497 if (isFPOp && !NeedsMovDPP)
6501 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6510 bool isAddSub =
false,
6511 bool needsCarryIn =
false,
6513 unsigned InstrOpc = ClampOpc;
6516 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6517 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6522 ClampInstr.addReg(CarryOutReg,
6528 ClampInstr.addReg(Src0);
6531 ClampInstr.addReg(Src1);
6534 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6535 ClampInstr.addImm(0);
6537 ClampInstr.addImm(0);
6538 LastBcastInstr = ClampInstr;
6543 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6544 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6545 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6547 if (isAddSubOpc || isBitWiseOpc) {
6554 auto [Src0Lo, Src0Hi] =
6556 auto [Src1Lo, Src1Hi] =
6558 Register CarryReg = BuildClampInstr(
6559 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6560 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6561 isAddSubOpc, CarryReg);
6562 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6591 SrcWithIdentityInstr =
6592 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6599 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6600 auto [SrcReg0Sub0, SrcReg0Sub1] =
6603 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6605 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6606 SrcWithIdentityInstr =
6607 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6614 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6617 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6619 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6622 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6624 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6627 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6629 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6632 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6634 if (ST.hasDPPBroadcasts()) {
6637 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6652 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6673 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6676 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6678 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6681 FinalDPPResult = RowBcast15;
6683 if (ST.hasDPPBroadcasts()) {
6686 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6702 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6706 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6712 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6720 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6725 .
addReg(ShiftedThreadID);
6730 .
addReg(PermuteByteOffset)
6740 auto [RowBcast15Lo, RowBcast15Hi] =
6744 .
addReg(PermuteByteOffset)
6749 .
addReg(PermuteByteOffset)
6752 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6756 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6758 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6760 FinalDPPResult = RowBcast31;
6762 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6763 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6773 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6776 FinalDPPResult = NegatedValVGPR;
6783 .
addImm(ST.getWavefrontSize() - 1);
6798 .
addImm(ST.getWavefrontSize() - 1);
6802 .
addImm(ST.getWavefrontSize() - 1);
6803 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6806 if (
Opc == AMDGPU::S_SUB_I32) {
6807 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6810 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6811 auto NegatedValInstr =
6819 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6825 MI.eraseFromParent();
6840 switch (
MI.getOpcode()) {
6841 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6843 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6845 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6847 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6849 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6851 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6854 ? AMDGPU::V_MIN_NUM_F64_e64
6855 : AMDGPU::V_MIN_F64_e64);
6856 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6858 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6860 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6862 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6864 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6866 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6869 ? AMDGPU::V_MAX_NUM_F64_e64
6870 : AMDGPU::V_MAX_F64_e64);
6871 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6873 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6875 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6877 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6880 ? AMDGPU::V_ADD_F64_pseudo_e64
6881 : AMDGPU::V_ADD_F64_e64);
6882 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6884 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6886 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6888 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6893 ? AMDGPU::V_ADD_F64_pseudo_e64
6894 : AMDGPU::V_ADD_F64_e64);
6895 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
6897 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
6899 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
6901 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
6903 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
6905 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
6907 case AMDGPU::S_UADDO_PSEUDO:
6908 case AMDGPU::S_USUBO_PSEUDO: {
6914 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
6916 : AMDGPU::S_SUB_U32;
6924 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
6927 MI.eraseFromParent();
6930 case AMDGPU::S_ADD_U64_PSEUDO:
6931 case AMDGPU::S_SUB_U64_PSEUDO: {
6934 case AMDGPU::V_ADD_U64_PSEUDO:
6935 case AMDGPU::V_SUB_U64_PSEUDO: {
6936 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
6942 if (ST.hasAddSubU64Insts()) {
6944 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
6945 : AMDGPU::V_SUB_U64_e64),
6950 TII->legalizeOperands(*
I);
6951 MI.eraseFromParent();
6955 if (IsAdd && ST.hasLshlAddU64Inst()) {
6961 TII->legalizeOperands(*
Add);
6962 MI.eraseFromParent();
6966 const auto *CarryRC =
TRI->getWaveMaskRegClass();
6976 : &AMDGPU::VReg_64RegClass;
6979 : &AMDGPU::VReg_64RegClass;
6982 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
6984 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
6987 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
6989 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
6992 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
6994 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
6997 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7004 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7018 TII->legalizeOperands(*LoHalf);
7019 TII->legalizeOperands(*HiHalf);
7020 MI.eraseFromParent();
7023 case AMDGPU::S_ADD_CO_PSEUDO:
7024 case AMDGPU::S_SUB_CO_PSEUDO: {
7036 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7042 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7047 if (
TRI->isVectorRegister(MRI, Src2.
getReg())) {
7048 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7053 if (ST.isWave64()) {
7054 if (ST.hasScalarCompareEq64()) {
7061 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7063 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7065 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7068 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7082 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7083 ? AMDGPU::S_ADDC_U32
7084 : AMDGPU::S_SUBB_U32;
7089 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7095 MI.eraseFromParent();
7098 case AMDGPU::SI_INIT_M0: {
7101 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7104 MI.eraseFromParent();
7107 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7110 TII->get(AMDGPU::S_CMP_EQ_U32))
7115 case AMDGPU::GET_GROUPSTATICSIZE: {
7119 .
add(
MI.getOperand(0))
7121 MI.eraseFromParent();
7124 case AMDGPU::GET_SHADERCYCLESHILO: {
7139 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7142 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7145 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7154 .
add(
MI.getOperand(0))
7159 MI.eraseFromParent();
7162 case AMDGPU::SI_INDIRECT_SRC_V1:
7163 case AMDGPU::SI_INDIRECT_SRC_V2:
7164 case AMDGPU::SI_INDIRECT_SRC_V3:
7165 case AMDGPU::SI_INDIRECT_SRC_V4:
7166 case AMDGPU::SI_INDIRECT_SRC_V5:
7167 case AMDGPU::SI_INDIRECT_SRC_V6:
7168 case AMDGPU::SI_INDIRECT_SRC_V7:
7169 case AMDGPU::SI_INDIRECT_SRC_V8:
7170 case AMDGPU::SI_INDIRECT_SRC_V9:
7171 case AMDGPU::SI_INDIRECT_SRC_V10:
7172 case AMDGPU::SI_INDIRECT_SRC_V11:
7173 case AMDGPU::SI_INDIRECT_SRC_V12:
7174 case AMDGPU::SI_INDIRECT_SRC_V16:
7175 case AMDGPU::SI_INDIRECT_SRC_V32:
7177 case AMDGPU::SI_INDIRECT_DST_V1:
7178 case AMDGPU::SI_INDIRECT_DST_V2:
7179 case AMDGPU::SI_INDIRECT_DST_V3:
7180 case AMDGPU::SI_INDIRECT_DST_V4:
7181 case AMDGPU::SI_INDIRECT_DST_V5:
7182 case AMDGPU::SI_INDIRECT_DST_V6:
7183 case AMDGPU::SI_INDIRECT_DST_V7:
7184 case AMDGPU::SI_INDIRECT_DST_V8:
7185 case AMDGPU::SI_INDIRECT_DST_V9:
7186 case AMDGPU::SI_INDIRECT_DST_V10:
7187 case AMDGPU::SI_INDIRECT_DST_V11:
7188 case AMDGPU::SI_INDIRECT_DST_V12:
7189 case AMDGPU::SI_INDIRECT_DST_V16:
7190 case AMDGPU::SI_INDIRECT_DST_V32:
7192 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7193 case AMDGPU::SI_KILL_I1_PSEUDO:
7195 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7199 case AMDGPU::SI_BR_UNDEF: {
7201 .
add(
MI.getOperand(0));
7203 MI.eraseFromParent();
7206 case AMDGPU::ADJCALLSTACKUP:
7207 case AMDGPU::ADJCALLSTACKDOWN: {
7214 case AMDGPU::SI_CALL_ISEL: {
7215 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7218 MIB =
BuildMI(*BB,
MI,
DL,
TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7224 MI.eraseFromParent();
7227 case AMDGPU::V_ADD_CO_U32_e32:
7228 case AMDGPU::V_SUB_CO_U32_e32:
7229 case AMDGPU::V_SUBREV_CO_U32_e32: {
7231 unsigned Opc =
MI.getOpcode();
7233 bool NeedClampOperand =
false;
7234 if (
TII->pseudoToMCOpcode(
Opc) == -1) {
7236 NeedClampOperand =
true;
7240 if (
TII->isVOP3(*
I)) {
7243 I.add(
MI.getOperand(1)).add(
MI.getOperand(2));
7244 if (NeedClampOperand)
7247 TII->legalizeOperands(*
I);
7249 MI.eraseFromParent();
7252 case AMDGPU::V_ADDC_U32_e32:
7253 case AMDGPU::V_SUBB_U32_e32:
7254 case AMDGPU::V_SUBBREV_U32_e32:
7257 TII->legalizeOperands(
MI);
7259 case AMDGPU::DS_GWS_INIT:
7260 case AMDGPU::DS_GWS_SEMA_BR:
7261 case AMDGPU::DS_GWS_BARRIER:
7262 case AMDGPU::DS_GWS_SEMA_V:
7263 case AMDGPU::DS_GWS_SEMA_P:
7264 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7272 case AMDGPU::S_SETREG_B32: {
7282 auto [ID,
Offset, Width] =
7288 const unsigned SetMask = WidthMask <<
Offset;
7291 unsigned SetDenormOp = 0;
7292 unsigned SetRoundOp = 0;
7300 SetRoundOp = AMDGPU::S_ROUND_MODE;
7301 SetDenormOp = AMDGPU::S_DENORM_MODE;
7303 SetRoundOp = AMDGPU::S_ROUND_MODE;
7305 SetDenormOp = AMDGPU::S_DENORM_MODE;
7308 if (SetRoundOp || SetDenormOp) {
7310 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7311 unsigned ImmVal = Def->getOperand(1).getImm();
7325 MI.eraseFromParent();
7334 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7338 case AMDGPU::S_INVERSE_BALLOT_U32:
7339 case AMDGPU::S_INVERSE_BALLOT_U64:
7342 MI.setDesc(
TII->get(AMDGPU::COPY));
7344 case AMDGPU::ENDPGM_TRAP: {
7346 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7366 MI.eraseFromParent();
7369 case AMDGPU::SIMULATED_TRAP: {
7370 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7372 TII->insertSimulatedTrap(MRI, *BB,
MI,
MI.getDebugLoc());
7373 MI.eraseFromParent();
7376 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7377 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7383 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7384 Register OriginalExec = Setup->getOperand(0).getReg();
7386 MI.getOperand(0).setReg(OriginalExec);
7389 case AMDGPU::V_DOT2_F32_F16:
7390 case AMDGPU::V_DOT2_F32_BF16: {
7431 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7435 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7464 if (!Subtarget->hasMadMacF32Insts())
7465 return Subtarget->hasFastFMAF32();
7471 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7474 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7480 return Subtarget->has16BitInsts() &&
7498 F.getDenormalFPEnv());
7503 switch (Ty.getScalarSizeInBits()) {
7521 return Subtarget->hasMadMacF32Insts() &&
7524 return Subtarget->hasMadF16() &&
7535 if (Ty.getScalarSizeInBits() == 16)
7537 if (Ty.getScalarSizeInBits() == 32)
7557 unsigned Opc =
Op.getOpcode();
7558 EVT VT =
Op.getValueType();
7570 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7571 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7584 [[maybe_unused]]
EVT VT =
Op.getValueType();
7586 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7587 VT == MVT::v16i32) &&
7588 "Unexpected ValueType.");
7597 unsigned Opc =
Op.getOpcode();
7598 EVT VT =
Op.getValueType();
7607 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7609 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7616 unsigned Opc =
Op.getOpcode();
7617 EVT VT =
Op.getValueType();
7623 : std::pair(Op0, Op0);
7632 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7634 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7640 switch (
Op.getOpcode()) {
7644 return LowerBRCOND(
Op, DAG);
7646 return LowerRETURNADDR(
Op, DAG);
7648 return LowerSPONENTRY(
Op, DAG);
7651 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7652 "Load should return a value and a chain");
7656 EVT VT =
Op.getValueType();
7658 return lowerFSQRTF32(
Op, DAG);
7660 return lowerFSQRTF64(
Op, DAG);
7665 return LowerTrig(
Op, DAG);
7667 return LowerSELECT(
Op, DAG);
7669 return LowerFDIV(
Op, DAG);
7671 return LowerFFREXP(
Op, DAG);
7673 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7675 return LowerSTORE(
Op, DAG);
7679 return LowerGlobalAddress(MFI,
Op, DAG);
7684 return LowerExternalSymbol(
Op, DAG);
7686 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7688 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7690 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7692 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7694 return LowerINTRINSIC_VOID(
Op, DAG);
7696 return lowerADDRSPACECAST(
Op, DAG);
7698 return lowerINSERT_SUBVECTOR(
Op, DAG);
7700 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7702 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7704 return lowerVECTOR_SHUFFLE(
Op, DAG);
7706 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7708 return lowerBUILD_VECTOR(
Op, DAG);
7711 return lowerFP_ROUND(
Op, DAG);
7713 return lowerTRAP(
Op, DAG);
7715 return lowerDEBUGTRAP(
Op, DAG);
7724 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7725 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7729 if (
Op.getValueType() == MVT::bf16) {
7759 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7762 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7765 return lowerFLDEXP(
Op, DAG);
7770 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7771 Op.getOperand(0).getValueType() == MVT::f32) {
7797 return lowerFCOPYSIGN(
Op, DAG);
7799 return lowerMUL(
Op, DAG);
7802 return lowerXMULO(
Op, DAG);
7805 return lowerXMUL_LOHI(
Op, DAG);
7826 return LowerINLINEASM(
Op, DAG);
7842 EVT FittingLoadVT = LoadVT;
7874SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7877 bool IsIntrinsic)
const {
7880 bool Unpacked = Subtarget->hasUnpackedD16VMem();
7881 EVT LoadVT =
M->getValueType(0);
7883 EVT EquivLoadVT = LoadVT;
7897 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
7901 M->getMemoryVT(),
M->getMemOperand());
7912 EVT LoadVT =
M->getValueType(0);
7921 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
7925 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
7926 bool IsTFE =
M->getNumValues() == 3;
7928 unsigned Opc = IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
7929 : AMDGPUISD::BUFFER_LOAD_FORMAT)
7930 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
7931 : AMDGPUISD::BUFFER_LOAD;
7934 return adjustLoadValueType(AMDGPUISD::BUFFER_LOAD_FORMAT_D16, M, DAG,
Ops);
7939 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
7943 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
7944 M->getMemOperand(), DAG);
7948 SDVTList VTList = DAG.
getVTList(CastVT, MVT::Other);
7950 M->getMemOperand(), DAG);
7958 EVT VT =
N->getValueType(0);
7959 unsigned CondCode =
N->getConstantOperandVal(3);
7970 EVT CmpVT =
LHS.getValueType();
7971 if (CmpVT == MVT::i16 && !TLI.
isTypeLegal(MVT::i16)) {
7972 unsigned PromoteOp =
7992 EVT VT =
N->getValueType(0);
7994 unsigned CondCode =
N->getConstantOperandVal(3);
8003 if (CmpVT == MVT::f16 && !TLI.
isTypeLegal(CmpVT)) {
8012 SDValue SetCC = DAG.
getNode(AMDGPUISD::SETCC, SL, CCVT, Src0, Src1,
8021 EVT VT =
N->getValueType(0);
8045 Exec = AMDGPU::EXEC_LO;
8047 Exec = AMDGPU::EXEC;
8067 EVT VT =
N->getValueType(0);
8069 unsigned IID =
N->getConstantOperandVal(0);
8070 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8071 IID == Intrinsic::amdgcn_permlanex16;
8072 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8073 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8074 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8075 IID == Intrinsic::amdgcn_permlane_up ||
8076 IID == Intrinsic::amdgcn_permlane_down ||
8077 IID == Intrinsic::amdgcn_permlane_xor;
8082 unsigned SplitSize = 32;
8083 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8084 ST->hasDPALU_DPP() &&
8092 case Intrinsic::amdgcn_permlane16:
8093 case Intrinsic::amdgcn_permlanex16:
8094 case Intrinsic::amdgcn_update_dpp:
8099 case Intrinsic::amdgcn_writelane:
8100 case Intrinsic::amdgcn_permlane_bcast:
8101 case Intrinsic::amdgcn_permlane_up:
8102 case Intrinsic::amdgcn_permlane_down:
8103 case Intrinsic::amdgcn_permlane_xor:
8106 case Intrinsic::amdgcn_readlane:
8107 case Intrinsic::amdgcn_set_inactive:
8108 case Intrinsic::amdgcn_set_inactive_chain_arg:
8109 case Intrinsic::amdgcn_mov_dpp8:
8112 case Intrinsic::amdgcn_readfirstlane:
8113 case Intrinsic::amdgcn_permlane64:
8123 if (
SDNode *GL =
N->getGluedNode()) {
8125 GL = GL->getOperand(0).getNode();
8135 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8136 IID == Intrinsic::amdgcn_mov_dpp8 ||
8137 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8138 IsPermlaneShuffle) {
8139 Src1 =
N->getOperand(2);
8140 if (IID == Intrinsic::amdgcn_writelane ||
8141 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8143 Src2 =
N->getOperand(3);
8146 if (ValSize == SplitSize) {
8156 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8161 if (IID == Intrinsic::amdgcn_writelane) {
8166 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8168 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8171 if (ValSize % SplitSize != 0)
8175 EVT VT =
N->getValueType(0);
8179 unsigned NumOperands =
N->getNumOperands();
8181 SDNode *GL =
N->getGluedNode();
8186 for (
unsigned i = 0; i != NE; ++i) {
8187 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8189 SDValue Operand =
N->getOperand(j);
8219 if (SplitSize == 32) {
8221 return unrollLaneOp(LaneOp.
getNode());
8227 unsigned SubVecNumElt =
8231 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8232 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8236 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8242 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8243 }
else if (IID == Intrinsic::amdgcn_writelane) {
8247 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8249 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8252 EltIdx += SubVecNumElt;
8266 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8269 if (IID == Intrinsic::amdgcn_writelane)
8272 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8279 EVT VT =
N->getValueType(0);
8297 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8307 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8308 {ShiftedIndex, ValueI32});
8318 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8319 {ValueI32, PoisonVal});
8320 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8321 {ShiftedIndex, PoisonVal});
8324 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8327 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8328 {WWMIndex, WWMValue});
8329 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8330 MVT::i32, {WWMIndex, Swapped});
8332 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8340 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8348 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8358 switch (
N->getOpcode()) {
8375 unsigned IID =
N->getConstantOperandVal(0);
8377 case Intrinsic::amdgcn_wave_reduce_min:
8378 case Intrinsic::amdgcn_wave_reduce_umin:
8379 case Intrinsic::amdgcn_wave_reduce_max:
8380 case Intrinsic::amdgcn_wave_reduce_umax:
8381 case Intrinsic::amdgcn_wave_reduce_add:
8382 case Intrinsic::amdgcn_wave_reduce_sub:
8383 case Intrinsic::amdgcn_wave_reduce_and:
8384 case Intrinsic::amdgcn_wave_reduce_or:
8385 case Intrinsic::amdgcn_wave_reduce_xor: {
8386 EVT VT =
N->getValueType(0);
8390 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8391 IID == Intrinsic::amdgcn_wave_reduce_max ||
8392 IID == Intrinsic::amdgcn_wave_reduce_add ||
8393 IID == Intrinsic::amdgcn_wave_reduce_sub;
8397 N->getOperand(0), ExtSrc,
N->getOperand(2));
8401 case Intrinsic::amdgcn_make_buffer_rsrc:
8402 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8404 case Intrinsic::amdgcn_cvt_pkrtz: {
8409 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8413 case Intrinsic::amdgcn_cvt_pknorm_i16:
8414 case Intrinsic::amdgcn_cvt_pknorm_u16:
8415 case Intrinsic::amdgcn_cvt_pk_i16:
8416 case Intrinsic::amdgcn_cvt_pk_u16: {
8422 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8423 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8424 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8425 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8426 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8427 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8429 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8431 EVT VT =
N->getValueType(0);
8440 case Intrinsic::amdgcn_s_buffer_load: {
8446 if (!Subtarget->hasScalarSubwordLoads())
8452 EVT VT =
Op.getValueType();
8453 assert(VT == MVT::i8 &&
"Expected 8-bit s_buffer_load intrinsics.\n");
8465 if (!
Offset->isDivergent()) {
8470 AMDGPUISD::SBUFFER_LOAD_UBYTE,
DL,
8485 LoadVal = handleByteShortBufferLoads(DAG, VT,
DL,
Ops, MMO);
8490 case Intrinsic::amdgcn_dead: {
8491 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8502 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8503 Results.push_back(Res.getOperand(
I));
8507 Results.push_back(Res.getValue(1));
8516 EVT VT =
N->getValueType(0);
8521 EVT SelectVT = NewVT;
8522 if (NewVT.
bitsLT(MVT::i32)) {
8525 SelectVT = MVT::i32;
8531 if (NewVT != SelectVT)
8537 if (
N->getValueType(0) != MVT::v2f16)
8549 if (
N->getValueType(0) != MVT::v2f16)
8561 if (
N->getValueType(0) != MVT::f16)
8576 if (U.get() !=
Value)
8579 if (U.getUser()->getOpcode() == Opcode)
8585unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8588 case Intrinsic::amdgcn_if:
8589 return AMDGPUISD::IF;
8590 case Intrinsic::amdgcn_else:
8591 return AMDGPUISD::ELSE;
8592 case Intrinsic::amdgcn_loop:
8593 return AMDGPUISD::LOOP;
8594 case Intrinsic::amdgcn_end_cf:
8614 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8637 assert(GVar->isDeclaration() &&
"AS3 GVs should be declaration here "
8638 "when object linking is enabled");
8653 SDNode *Intr = BRCOND.getOperand(1).getNode();
8670 Intr =
LHS.getNode();
8678 assert(BR &&
"brcond missing unconditional branch user");
8683 unsigned CFNode = isCFIntrinsic(Intr);
8703 Ops.push_back(Target);
8726 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8745 MVT VT =
Op.getSimpleValueType();
8748 if (
Op.getConstantOperandVal(0) != 0)
8752 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8754 if (
Info->isEntryFunction())
8771 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8785 return Op.getValueType().bitsLE(VT)
8793 EVT DstVT =
Op.getValueType();
8800 unsigned Opc =
Op.getOpcode();
8811 bool IsStrict =
Op->isStrictFPOpcode();
8812 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8813 EVT SrcVT = Src.getValueType();
8814 EVT DstVT =
Op.getValueType();
8817 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8820 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8827 if (DstVT == MVT::f16) {
8832 if (!Subtarget->has16BitInsts()) {
8837 if (
Op->getFlags().hasApproximateFuncs()) {
8848 "custom lower FP_ROUND for f16 or bf16");
8849 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8866 EVT VT =
Op.getValueType();
8868 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8869 bool IsIEEEMode =
Info->getMode().IEEE;
8878 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8885SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8887 EVT VT =
Op.getValueType();
8889 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8890 bool IsIEEEMode =
Info->getMode().IEEE;
8895 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8903 EVT VT =
Op.getValueType();
8907 EVT ExpVT =
Exp.getValueType();
8908 if (ExpVT == MVT::i16)
8929 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
8936 switch (
Op->getOpcode()) {
8968SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
8969 DAGCombinerInfo &DCI)
const {
8970 EVT OpTy =
Op.getValueType();
8971 SelectionDAG &DAG = DCI.DAG;
8980 Input = DAG.
getNode(ExtOp,
DL, ExtTy, Input);
8988 DAGCombinerInfo &DCI)
const {
8989 const unsigned Opc =
Op.getOpcode();
8998 :
Op->getOperand(0).getValueType();
8999 auto &DAG = DCI.DAG;
9002 if (DCI.isBeforeLegalizeOps() ||
9010 LHS =
Op->getOperand(1);
9011 RHS =
Op->getOperand(2);
9013 LHS =
Op->getOperand(0);
9014 RHS =
Op->getOperand(1);
9053 if (MagVT == SignVT)
9074 EVT VT =
Op.getValueType();
9080 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9107 if (
Op->isDivergent())
9120 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9122 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9125 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9127 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9133 EVT VT =
Op.getValueType();
9140 const APInt &
C = RHSC->getAPIntValue();
9142 if (
C.isPowerOf2()) {
9144 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9171 if (
Op->isDivergent()) {
9175 if (Subtarget->hasSMulHi()) {
9186 if (!Subtarget->hasTrapHandler() ||
9188 return lowerTrapEndpgm(
Op, DAG);
9190 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9191 : lowerTrapHsaQueuePtr(
Op, DAG);
9197 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9201SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9203 ImplicitParameter Param)
const {
9207 MachinePointerInfo PtrInfo =
9224 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9227 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9230 if (UserSGPR == AMDGPU::NoRegister) {
9247 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9256 if (Subtarget->hasPrivEnabledTrap2NopBug())
9257 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9261 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9269 if (!Subtarget->hasTrapHandler() ||
9273 "debugtrap handler not supported",
9281 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9291 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9292 SmallSet<Register, 8> SGPRInputRegs;
9294 unsigned NumVals = 0;
9297 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9298 NumVals =
Flags.getNumOperandRegisters();
9302 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9303 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9305 for (
unsigned J = 0; J < NumVals; ++J) {
9307 if (
const RegisterSDNode *RegNode =
9316 if (SGPRInputRegs.
empty())
9321 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9333 ReadFirstLaneID, SrcVal);
9337 if (
N->getNumOperands() > 3)
9338 Ops.push_back(
N->getOperand(3));
9344 SDNode *
Next =
nullptr;
9345 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9346 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9347 Next =
N->getOperand(
I).getNode();
9357SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9359 if (Subtarget->hasApertureRegs()) {
9361 ? AMDGPU::SRC_SHARED_BASE
9362 : AMDGPU::SRC_PRIVATE_BASE;
9363 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9364 !Subtarget->hasGloballyAddressableScratch()) &&
9365 "Cannot use src_private_base with globally addressable scratch!");
9386 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9390 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9392 if (UserSGPR == AMDGPU::NoRegister) {
9437 const AMDGPUTargetMachine &TM =
9440 unsigned DestAS, SrcAS;
9442 bool IsNonNull =
false;
9444 SrcAS = ASC->getSrcAddressSpace();
9445 Src = ASC->getOperand(0);
9446 DestAS = ASC->getDestAddressSpace();
9449 Op.getConstantOperandVal(0) ==
9450 Intrinsic::amdgcn_addrspacecast_nonnull);
9451 Src =
Op->getOperand(1);
9452 SrcAS =
Op->getConstantOperandVal(2);
9453 DestAS =
Op->getConstantOperandVal(3);
9466 Subtarget->hasGloballyAddressableScratch()) {
9471 AMDGPU::S_MOV_B32, SL, MVT::i32,
9472 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9495 Subtarget->hasGloballyAddressableScratch()) {
9504 if (Subtarget->isWave64())
9510 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9518 AMDGPU::S_MOV_B64, SL, MVT::i64,
9519 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9521 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9523 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9543 Op.getValueType() == MVT::i64) {
9544 const SIMachineFunctionInfo *
Info =
9546 if (
Info->get32BitAddressHighBits() == 0)
9555 Src.getValueType() == MVT::i64)
9583 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9588 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9590 MVT::i32, InsNumElts / 2);
9595 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9597 if (InsNumElts == 2) {
9610 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9633 if (NumElts == 4 && EltSize == 16 && KIdx) {
9644 unsigned Idx = KIdx->getZExtValue();
9645 bool InsertLo = Idx < 2;
9649 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9655 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9668 assert(VecSize <= 64 &&
"Expected target vector size to be <= 64 bits");
9703 EVT ResultVT =
Op.getValueType();
9716 if (
SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9719 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9723 if (VecSize == 128) {
9731 }
else if (VecSize == 256) {
9734 for (
unsigned P = 0;
P < 4; ++
P) {
9740 Parts[0], Parts[1]));
9742 Parts[2], Parts[3]));
9748 for (
unsigned P = 0;
P < 8; ++
P) {
9755 Parts[0], Parts[1], Parts[2], Parts[3]));
9758 Parts[4], Parts[5], Parts[6], Parts[7]));
9778 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9793 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9803 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9808 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9809 !(Mask[Elt + 1] & 1);
9815 EVT ResultVT =
Op.getValueType();
9818 const int NewSrcNumElts = 2;
9820 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9836 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9858 if (ShouldUseConsecutiveExtract &&
9861 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9862 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9874 if (Idx0 >= SrcNumElts) {
9879 if (Idx1 >= SrcNumElts) {
9884 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9885 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9893 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9894 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9899 if (SubVec0 != SubVec1) {
9900 NewMaskIdx1 += NewSrcNumElts;
9907 {NewMaskIdx0, NewMaskIdx1});
9912 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
9913 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
9914 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
9915 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
9934 EVT ResultVT =
Op.getValueType();
9950 EVT VT =
Op.getValueType();
9952 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
9953 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
9987 for (
unsigned P = 0;
P < NumParts; ++
P) {
9989 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10015 if (!Subtarget->isAmdHsaOS())
10058 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10067 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10075 EVT PtrVT =
Op.getValueType();
10077 const GlobalValue *GV = GSD->
getGlobal();
10091 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10106 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10109 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10110 if (Subtarget->has64BitLiterals()) {
10119 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10123 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10141 MachinePointerInfo PtrInfo =
10154 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10176 unsigned Offset)
const {
10178 SDValue Param = lowerKernargMemParameter(
10189 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10197 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10205 unsigned NumElts = Elts.
size();
10207 if (NumElts <= 12) {
10211 Type = MVT::v16f32;
10216 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10222 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10231 SDValue Src,
int ExtraElts) {
10232 EVT SrcVT = Src.getValueType();
10242 while (ExtraElts--)
10253 bool Unpacked,
bool IsD16,
int DMaskPop,
10254 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10258 EVT ReqRetVT = ResultTypes[0];
10260 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10261 ? (ReqRetNumElts + 1) / 2
10264 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10267 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10270 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10275 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10279 SDValue(Result, 0), ZeroIdx);
10282 SDValue(Result, 0), ZeroIdx);
10286 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10288 NumDataDwords - MaskPopDwords);
10293 EVT LegalReqRetVT = ReqRetVT;
10295 if (!
Data.getValueType().isInteger())
10297 Data.getValueType().changeTypeToInteger(),
Data);
10318 if (Result->getNumValues() == 1)
10325 SDValue *LWE,
bool &IsTexFail) {
10345 unsigned DimIdx,
unsigned EndIdx,
10346 unsigned NumGradients) {
10348 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10356 if (((
I + 1) >= EndIdx) ||
10357 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10358 I == DimIdx + NumGradients - 1))) {
10390 !
Op.getNode()->hasAnyUseOfValue(0))
10392 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10403 ResultTypes.erase(&ResultTypes[0]);
10405 bool IsD16 =
false;
10406 bool IsG16 =
false;
10407 bool IsA16 =
false;
10409 int NumVDataDwords = 0;
10410 bool AdjustRetType =
false;
10411 bool IsAtomicPacked16Bit =
false;
10414 const unsigned ArgOffset = WithChain ? 2 : 1;
10417 unsigned DMaskLanes = 0;
10419 if (BaseOpcode->
Atomic) {
10420 VData =
Op.getOperand(2);
10422 IsAtomicPacked16Bit =
10423 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10424 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10425 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10426 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10431 "unsupported image atomic data type");
10443 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10445 DMask = Is64Bit ? 0xf : 0x3;
10446 NumVDataDwords = Is64Bit ? 4 : 2;
10448 DMask = Is64Bit ? 0x3 : 0x1;
10449 NumVDataDwords = Is64Bit ? 2 : 1;
10452 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10455 if (BaseOpcode->
Store) {
10456 VData =
Op.getOperand(2);
10460 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10463 "unsupported image store data type");
10465 if (StoreScalarVT == MVT::f16) {
10466 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10470 VData = handleD16VData(VData, DAG,
true);
10473 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10474 }
else if (!BaseOpcode->
NoReturn) {
10479 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10482 "unsupported image load data type");
10484 if (LoadScalarVT == MVT::f16) {
10485 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10493 (!LoadVT.
isVector() && DMaskLanes > 1))
10499 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10500 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10501 NumVDataDwords = (DMaskLanes + 1) / 2;
10503 NumVDataDwords = DMaskLanes;
10505 AdjustRetType =
true;
10509 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10516 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10517 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10519 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10521 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10522 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10526 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10532 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10536 "Bias needs to be converted to 16 bit in A16 mode");
10541 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10545 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10546 "require 16 bit args for both gradients and addresses");
10551 if (!
ST->hasA16()) {
10552 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10553 "support 16 bit addresses\n");
10563 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10565 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10567 IntrOpcode = G16MappingInfo->
G16;
10590 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10608 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10609 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10610 const bool UseNSA =
ST->hasNSAEncoding() &&
10611 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10612 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10613 const bool UsePartialNSA =
10614 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10617 if (UsePartialNSA) {
10619 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10620 }
else if (!UseNSA) {
10630 uint64_t UnormConst =
10631 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10633 Unorm = UnormConst ? True : False;
10639 bool IsTexFail =
false;
10640 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10649 NumVDataDwords = 1;
10651 NumVDataDwords += 1;
10652 AdjustRetType =
true;
10657 if (AdjustRetType) {
10660 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10669 MVT::i32, NumVDataDwords)
10672 ResultTypes[0] = NewVT;
10673 if (ResultTypes.size() == 3) {
10677 ResultTypes.erase(&ResultTypes[1]);
10691 Ops.push_back(VData);
10692 if (UsePartialNSA) {
10694 Ops.push_back(VAddr);
10698 Ops.push_back(VAddr);
10701 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10703 Ops.push_back(Rsrc);
10708 Ops.push_back(Samp);
10713 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10714 Ops.push_back(Unorm);
10716 Ops.push_back(IsA16 &&
10717 ST->hasFeature(AMDGPU::FeatureR128A16)
10721 Ops.push_back(IsA16 ? True : False);
10723 if (!Subtarget->hasGFX90AInsts())
10724 Ops.push_back(TFE);
10728 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10731 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10732 Ops.push_back(LWE);
10734 Ops.push_back(DimInfo->
DA ? True : False);
10736 Ops.push_back(IsD16 ? True : False);
10738 Ops.push_back(
Op.getOperand(0));
10740 int NumVAddrDwords =
10746 NumVDataDwords, NumVAddrDwords);
10747 }
else if (IsGFX12Plus) {
10749 NumVDataDwords, NumVAddrDwords);
10750 }
else if (IsGFX11Plus) {
10752 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10753 : AMDGPU::MIMGEncGfx11Default,
10754 NumVDataDwords, NumVAddrDwords);
10755 }
else if (IsGFX10Plus) {
10757 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10758 : AMDGPU::MIMGEncGfx10Default,
10759 NumVDataDwords, NumVAddrDwords);
10761 if (Subtarget->hasGFX90AInsts()) {
10763 NumVDataDwords, NumVAddrDwords);
10764 if (Opcode == -1) {
10766 DAG,
Op, OrigResultTypes,
DL,
10767 "requested image instruction is not supported on this GPU");
10770 if (Opcode == -1 &&
10773 NumVDataDwords, NumVAddrDwords);
10776 NumVDataDwords, NumVAddrDwords);
10783 MachineMemOperand *MemRef = MemOp->getMemOperand();
10802 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10803 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10812 bool HasChainResult = MMO !=
nullptr;
10814 if (!HasChainResult) {
10826 if (!
Offset->isDivergent()) {
10834 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) ->
SDValue {
10836 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10839 if (HasChainResult)
10843 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10844 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10846 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10847 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10851 !Subtarget->hasScalarDwordx3Loads()) {
10855 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10860 if (HasChainResult)
10882 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10883 Subtarget->hasScalarSubwordLoads()) {
10887 if (HasChainResult)
10893 unsigned NumLoads = 1;
10899 if (NumElts == 8 || NumElts == 16) {
10900 NumLoads = NumElts / 4;
10904 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
10909 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
10911 uint64_t InstOffset =
Ops[5]->getAsZExtVal();
10913 for (
unsigned i = 0; i < NumLoads; ++i) {
10916 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
10917 LoadVT, LoadMMO, DAG));
10920 if (NumElts == 8 || NumElts == 16) {
10922 if (HasChainResult) {
10937 if (!Subtarget->hasArchitectedSGPRs())
10942 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
10949 unsigned Width)
const {
10951 using namespace AMDGPU::Hwreg;
10953 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
10993 EVT DstVT =
Op.getValueType();
10995 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
10996 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11000 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11002 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11015SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11026 EVT DstVT =
Op.getValueType();
11029 if (Src.getValueType() != MVT::i32) {
11039 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11040 return lowerFromFP8(
Op, IsBF8, DAG);
11048 EVT ResVT =
Op.getValueType();
11049 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11050 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11051 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11053 "only the v2i8 vector result is custom lowered");
11057 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11062 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32 : AMDGPUISD::CVT_PK_FP8_F32;
11070 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11082SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11096 if (
Op.getConstantOperandVal(3) != 0)
11099 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11102 if (SrcEltVT == MVT::f32)
11103 return lowerToFP8(
Op, IsBF8, DAG);
11104 if (SrcEltVT == MVT::f16 && Subtarget->hasF16FP8ConversionInsts()) {
11107 if (!
Op.getValueType().isVector())
11109 return lowerToFP8(
Op, IsBF8, DAG);
11117 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11119 EVT VT =
Op.getValueType();
11121 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11125 switch (IntrinsicID) {
11126 case Intrinsic::amdgcn_wave_reduce_min:
11127 case Intrinsic::amdgcn_wave_reduce_umin:
11128 case Intrinsic::amdgcn_wave_reduce_fmin:
11129 case Intrinsic::amdgcn_wave_reduce_max:
11130 case Intrinsic::amdgcn_wave_reduce_umax:
11131 case Intrinsic::amdgcn_wave_reduce_fmax:
11132 case Intrinsic::amdgcn_wave_reduce_add:
11133 case Intrinsic::amdgcn_wave_reduce_fadd:
11134 case Intrinsic::amdgcn_wave_reduce_sub:
11135 case Intrinsic::amdgcn_wave_reduce_fsub:
11136 case Intrinsic::amdgcn_wave_reduce_and:
11137 case Intrinsic::amdgcn_wave_reduce_or:
11138 case Intrinsic::amdgcn_wave_reduce_xor: {
11139 EVT SrcVT =
Op.getOperand(1).getValueType();
11142 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11143 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11144 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11145 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11149 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11150 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11154 Op.getOperand(0), ExtendedSrc, Strategy);
11163 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11166 return getPreloadedValue(DAG, *MFI, VT,
11169 case Intrinsic::amdgcn_dispatch_ptr:
11170 case Intrinsic::amdgcn_queue_ptr: {
11171 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11173 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11174 DL.getDebugLoc()));
11178 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11181 return getPreloadedValue(DAG, *MFI, VT, RegID);
11183 case Intrinsic::amdgcn_implicitarg_ptr: {
11185 return getImplicitArgPtr(DAG,
DL);
11186 return getPreloadedValue(DAG, *MFI, VT,
11189 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11195 return getPreloadedValue(DAG, *MFI, VT,
11198 case Intrinsic::amdgcn_dispatch_id: {
11201 case Intrinsic::amdgcn_rcp:
11202 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11203 case Intrinsic::amdgcn_rsq:
11204 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11205 case Intrinsic::amdgcn_rsq_legacy:
11209 case Intrinsic::amdgcn_rcp_legacy:
11212 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11213 case Intrinsic::amdgcn_fma_legacy:
11214 case Intrinsic::amdgcn_sudot4:
11215 case Intrinsic::amdgcn_sudot8:
11216 case Intrinsic::amdgcn_tanh:
11218 case Intrinsic::amdgcn_rsq_clamp: {
11220 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11232 case Intrinsic::r600_read_ngroups_x:
11233 if (Subtarget->isAmdHsaOS())
11236 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11239 case Intrinsic::r600_read_ngroups_y:
11240 if (Subtarget->isAmdHsaOS())
11243 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11246 case Intrinsic::r600_read_ngroups_z:
11247 if (Subtarget->isAmdHsaOS())
11250 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11253 case Intrinsic::r600_read_local_size_x:
11254 if (Subtarget->isAmdHsaOS())
11257 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11259 case Intrinsic::r600_read_local_size_y:
11260 if (Subtarget->isAmdHsaOS())
11263 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11265 case Intrinsic::r600_read_local_size_z:
11266 if (Subtarget->isAmdHsaOS())
11269 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11271 case Intrinsic::amdgcn_workgroup_id_x:
11272 return lowerWorkGroupId(DAG, *MFI, VT,
11276 case Intrinsic::amdgcn_workgroup_id_y:
11277 return lowerWorkGroupId(DAG, *MFI, VT,
11281 case Intrinsic::amdgcn_workgroup_id_z:
11282 return lowerWorkGroupId(DAG, *MFI, VT,
11286 case Intrinsic::amdgcn_cluster_id_x:
11287 return Subtarget->hasClusters()
11288 ? getPreloadedValue(DAG, *MFI, VT,
11290 : DAG.getPOISON(VT);
11291 case Intrinsic::amdgcn_cluster_id_y:
11292 return Subtarget->hasClusters()
11293 ? getPreloadedValue(DAG, *MFI, VT,
11296 case Intrinsic::amdgcn_cluster_id_z:
11297 return Subtarget->hasClusters()
11298 ? getPreloadedValue(DAG, *MFI, VT,
11301 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11302 return Subtarget->hasClusters()
11303 ? getPreloadedValue(
11307 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11308 return Subtarget->hasClusters()
11309 ? getPreloadedValue(
11313 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11314 return Subtarget->hasClusters()
11315 ? getPreloadedValue(
11319 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11320 return Subtarget->hasClusters()
11323 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11324 return Subtarget->hasClusters()
11325 ? getPreloadedValue(
11329 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11330 return Subtarget->hasClusters()
11331 ? getPreloadedValue(
11335 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11336 return Subtarget->hasClusters()
11337 ? getPreloadedValue(
11341 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11342 return Subtarget->hasClusters()
11343 ? getPreloadedValue(
11347 case Intrinsic::amdgcn_wave_id:
11348 return lowerWaveID(DAG,
Op);
11349 case Intrinsic::amdgcn_lds_kernel_id: {
11351 return getLDSKernelId(DAG,
DL);
11352 return getPreloadedValue(DAG, *MFI, VT,
11355 case Intrinsic::amdgcn_workitem_id_x:
11356 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11357 case Intrinsic::amdgcn_workitem_id_y:
11358 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11359 case Intrinsic::amdgcn_workitem_id_z:
11360 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11361 case Intrinsic::amdgcn_wavefrontsize:
11363 SDLoc(
Op), MVT::i32);
11364 case Intrinsic::amdgcn_s_buffer_load: {
11365 unsigned CPol =
Op.getConstantOperandVal(3);
11373 Op.getOperand(2),
Op.getOperand(3), DAG);
11375 case Intrinsic::amdgcn_fdiv_fast:
11376 return lowerFDIV_FAST(
Op, DAG);
11377 case Intrinsic::amdgcn_sin:
11378 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11380 case Intrinsic::amdgcn_cos:
11381 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11383 case Intrinsic::amdgcn_mul_u24:
11384 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11386 case Intrinsic::amdgcn_mul_i24:
11387 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11390 case Intrinsic::amdgcn_log_clamp: {
11396 case Intrinsic::amdgcn_fract:
11397 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11399 case Intrinsic::amdgcn_class: {
11401 EVT SrcVT = Src.getValueType();
11402 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11403 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11407 "llvm.amdgcn.class only supports f16, f32, and f64",
11408 DL.getDebugLoc()));
11411 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11413 case Intrinsic::amdgcn_div_fmas:
11414 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11415 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11417 case Intrinsic::amdgcn_div_fixup:
11418 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11419 Op.getOperand(2),
Op.getOperand(3));
11421 case Intrinsic::amdgcn_div_scale: {
11427 SDValue Denominator =
Op.getOperand(2);
11434 SDValue Src0 =
Param->isAllOnes() ? Numerator : Denominator;
11436 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11437 Denominator, Numerator);
11439 case Intrinsic::amdgcn_icmp: {
11441 if (
Op.getOperand(1).getValueType() == MVT::i1 &&
11442 Op.getConstantOperandVal(2) == 0 &&
11447 case Intrinsic::amdgcn_fcmp: {
11450 case Intrinsic::amdgcn_ballot:
11452 case Intrinsic::amdgcn_fmed3:
11453 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11454 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11455 case Intrinsic::amdgcn_fdot2:
11456 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11457 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11458 case Intrinsic::amdgcn_fmul_legacy:
11459 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11461 case Intrinsic::amdgcn_sbfe:
11462 return DAG.
getNode(AMDGPUISD::BFE_I32,
DL, VT,
Op.getOperand(1),
11463 Op.getOperand(2),
Op.getOperand(3));
11464 case Intrinsic::amdgcn_ubfe:
11465 return DAG.
getNode(AMDGPUISD::BFE_U32,
DL, VT,
Op.getOperand(1),
11466 Op.getOperand(2),
Op.getOperand(3));
11467 case Intrinsic::amdgcn_cvt_pkrtz:
11468 case Intrinsic::amdgcn_cvt_pknorm_i16:
11469 case Intrinsic::amdgcn_cvt_pknorm_u16:
11470 case Intrinsic::amdgcn_cvt_pk_i16:
11471 case Intrinsic::amdgcn_cvt_pk_u16: {
11473 EVT VT =
Op.getValueType();
11476 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11477 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11478 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11479 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11480 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11481 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11482 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11483 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11485 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11488 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11491 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11494 case Intrinsic::amdgcn_fmad_ftz:
11495 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11496 Op.getOperand(2),
Op.getOperand(3));
11498 case Intrinsic::amdgcn_if_break:
11500 Op->getOperand(1),
Op->getOperand(2)),
11503 case Intrinsic::amdgcn_groupstaticsize: {
11509 const GlobalValue *GV =
11515 case Intrinsic::amdgcn_is_shared:
11516 case Intrinsic::amdgcn_is_private: {
11523 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11527 Subtarget->hasGloballyAddressableScratch()) {
11530 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11531 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11540 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11543 case Intrinsic::amdgcn_perm:
11544 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11545 Op.getOperand(2),
Op.getOperand(3));
11546 case Intrinsic::amdgcn_reloc_constant: {
11556 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11557 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11558 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11559 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11560 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11561 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11562 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11563 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11564 if (
Op.getOperand(4).getValueType() == MVT::i32)
11570 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11571 Op.getOperand(3), IndexKeyi32);
11573 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11574 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11575 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11576 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11577 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11578 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11579 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11580 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11581 if (
Op.getOperand(4).getValueType() == MVT::i64)
11586 Op.getOperand(4).getValueType() == MVT::v2i32
11590 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11591 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11592 Op.getOperand(6)});
11594 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11595 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11596 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11597 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11598 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11599 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11600 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11603 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11608 Op.getOperand(6).getValueType().isVector()
11612 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11613 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11614 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11615 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11616 Args.push_back(
Op.getOperand(9));
11619 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11620 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11621 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11622 if (
Op.getOperand(6).getValueType() == MVT::i32)
11628 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11629 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11630 IndexKeyi32, Op.getOperand(7)});
11632 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11633 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11634 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11635 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11636 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11637 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11641 "invalid matrix and scale format combination in wmma call");
11647 case Intrinsic::amdgcn_addrspacecast_nonnull:
11648 return lowerADDRSPACECAST(
Op, DAG);
11649 case Intrinsic::amdgcn_readlane:
11650 case Intrinsic::amdgcn_readfirstlane:
11651 case Intrinsic::amdgcn_writelane:
11652 case Intrinsic::amdgcn_permlane16:
11653 case Intrinsic::amdgcn_permlanex16:
11654 case Intrinsic::amdgcn_permlane64:
11655 case Intrinsic::amdgcn_set_inactive:
11656 case Intrinsic::amdgcn_set_inactive_chain_arg:
11657 case Intrinsic::amdgcn_mov_dpp8:
11658 case Intrinsic::amdgcn_update_dpp:
11659 case Intrinsic::amdgcn_permlane_bcast:
11660 case Intrinsic::amdgcn_permlane_up:
11661 case Intrinsic::amdgcn_permlane_down:
11662 case Intrinsic::amdgcn_permlane_xor:
11664 case Intrinsic::amdgcn_dead: {
11666 for (
const EVT ValTy :
Op.getNode()->values())
11670 case Intrinsic::amdgcn_wave_shuffle:
11673 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11675 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11685 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(SOffset))
11686 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11692 unsigned NewOpcode)
const {
11699 "unsupported buffer atomic data type");
11701 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11702 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11720 M->getMemOperand());
11725 unsigned NewOpcode)
const {
11732 "unsupported buffer atomic data type");
11734 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11735 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11753 M->getMemOperand());
11758 unsigned IntrID =
Op.getConstantOperandVal(1);
11762 case Intrinsic::amdgcn_ds_ordered_add:
11763 case Intrinsic::amdgcn_ds_ordered_swap: {
11768 unsigned IndexOperand =
M->getConstantOperandVal(7);
11769 unsigned WaveRelease =
M->getConstantOperandVal(8);
11770 unsigned WaveDone =
M->getConstantOperandVal(9);
11772 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11773 IndexOperand &= ~0x3f;
11774 unsigned CountDw = 0;
11777 CountDw = (IndexOperand >> 24) & 0xf;
11778 IndexOperand &= ~(0xf << 24);
11780 if (CountDw < 1 || CountDw > 4) {
11783 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11784 DL.getDebugLoc()));
11789 if (IndexOperand) {
11792 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11795 if (WaveDone && !WaveRelease) {
11799 Fn,
"ds_ordered_count: wave_done requires wave_release",
11800 DL.getDebugLoc()));
11803 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11804 unsigned ShaderType =
11806 unsigned Offset0 = OrderedCountIndex << 2;
11807 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11810 Offset1 |= (CountDw - 1) << 6;
11813 Offset1 |= ShaderType << 2;
11815 unsigned Offset = Offset0 | (Offset1 << 8);
11822 M->getVTList(),
Ops,
M->getMemoryVT(),
11823 M->getMemOperand());
11825 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11826 unsigned CPol =
Op.getConstantOperandVal(4);
11833 return lowerSBuffer(
11834 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
11835 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
11836 Op.getOperand(4), DAG,
M->getMemOperand());
11838 case Intrinsic::amdgcn_raw_buffer_load:
11839 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11840 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11841 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11842 case Intrinsic::amdgcn_raw_buffer_load_format:
11843 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11844 const bool IsFormat =
11845 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11846 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11848 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11849 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
11863 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
11865 case Intrinsic::amdgcn_struct_buffer_load:
11866 case Intrinsic::amdgcn_struct_ptr_buffer_load:
11867 case Intrinsic::amdgcn_struct_buffer_load_format:
11868 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
11869 case Intrinsic::amdgcn_struct_atomic_buffer_load:
11870 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
11871 const bool IsFormat =
11872 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
11873 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
11875 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11876 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11891 case Intrinsic::amdgcn_raw_tbuffer_load:
11892 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
11894 EVT LoadVT =
Op.getValueType();
11895 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11896 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
11912 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11914 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
11915 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
11918 case Intrinsic::amdgcn_struct_tbuffer_load:
11919 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
11921 EVT LoadVT =
Op.getValueType();
11922 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11923 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11939 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11941 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
11942 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
11945 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
11946 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
11947 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
11948 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
11949 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
11950 return lowerStructBufferAtomicIntrin(
Op, DAG,
11951 AMDGPUISD::BUFFER_ATOMIC_FADD);
11952 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
11953 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
11954 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
11955 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
11956 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
11957 return lowerStructBufferAtomicIntrin(
Op, DAG,
11958 AMDGPUISD::BUFFER_ATOMIC_FMIN);
11959 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
11960 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
11961 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
11962 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
11963 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
11964 return lowerStructBufferAtomicIntrin(
Op, DAG,
11965 AMDGPUISD::BUFFER_ATOMIC_FMAX);
11966 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
11967 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
11968 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
11969 case Intrinsic::amdgcn_raw_buffer_atomic_add:
11970 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
11971 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
11972 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
11973 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
11974 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
11975 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
11976 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
11977 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
11978 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
11979 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
11980 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
11981 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
11982 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
11983 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
11984 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
11985 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
11986 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
11987 case Intrinsic::amdgcn_raw_buffer_atomic_and:
11988 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
11989 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
11990 case Intrinsic::amdgcn_raw_buffer_atomic_or:
11991 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
11992 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
11993 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
11994 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
11995 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
11996 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
11997 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
11998 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
11999 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12000 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12001 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12002 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12003 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12004 return lowerStructBufferAtomicIntrin(
Op, DAG,
12005 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12006 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12007 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12008 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12009 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12010 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12011 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12012 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12013 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12014 return lowerStructBufferAtomicIntrin(
Op, DAG,
12015 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12016 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12017 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12018 return lowerStructBufferAtomicIntrin(
Op, DAG,
12019 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12020 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12021 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12022 return lowerStructBufferAtomicIntrin(
Op, DAG,
12023 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12024 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12025 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12026 return lowerStructBufferAtomicIntrin(
Op, DAG,
12027 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12028 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12029 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12030 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12031 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12032 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12033 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12034 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12036 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12037 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12038 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12039 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12040 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12041 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12042 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12043 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12044 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12045 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12046 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12047 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12048 return lowerStructBufferAtomicIntrin(
Op, DAG,
12049 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12050 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12052 return lowerRawBufferAtomicIntrin(
Op, DAG,
12053 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12054 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12055 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12056 return lowerStructBufferAtomicIntrin(
Op, DAG,
12057 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12058 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12059 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12061 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12064 "unsupported buffer atomic data type");
12066 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12067 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12081 EVT VT =
Op.getValueType();
12085 Op->getVTList(),
Ops, VT,
12086 M->getMemOperand());
12088 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12089 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12091 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12094 "unsupported buffer atomic data type");
12096 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12097 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12111 EVT VT =
Op.getValueType();
12115 Op->getVTList(),
Ops, VT,
12116 M->getMemOperand());
12118 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12119 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12121 SDValue NodePtr =
M->getOperand(2);
12122 SDValue RayExtent =
M->getOperand(3);
12123 SDValue InstanceMask =
M->getOperand(4);
12124 SDValue RayOrigin =
M->getOperand(5);
12125 SDValue RayDir =
M->getOperand(6);
12127 SDValue TDescr =
M->getOperand(8);
12132 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12133 const unsigned NumVDataDwords = 10;
12134 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12136 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12137 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12138 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12142 Ops.push_back(NodePtr);
12145 {DAG.getBitcast(MVT::i32, RayExtent),
12146 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12147 Ops.push_back(RayOrigin);
12148 Ops.push_back(RayDir);
12149 Ops.push_back(Offsets);
12150 Ops.push_back(TDescr);
12151 Ops.push_back(
M->getChain());
12154 MachineMemOperand *MemRef =
M->getMemOperand();
12158 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12160 SDValue NodePtr =
M->getOperand(2);
12161 SDValue RayExtent =
M->getOperand(3);
12162 SDValue RayOrigin =
M->getOperand(4);
12163 SDValue RayDir =
M->getOperand(5);
12164 SDValue RayInvDir =
M->getOperand(6);
12165 SDValue TDescr =
M->getOperand(7);
12177 const unsigned NumVDataDwords = 4;
12178 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12179 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12180 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12183 const unsigned BaseOpcodes[2][2] = {
12184 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12185 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12186 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12190 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12191 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12192 : AMDGPU::MIMGEncGfx10NSA,
12193 NumVDataDwords, NumVAddrDwords);
12197 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12198 : AMDGPU::MIMGEncGfx10Default,
12199 NumVDataDwords, NumVAddrDwords);
12205 auto packLanes = [&DAG, &
Ops, &
DL](
SDValue Op,
bool IsAligned) {
12208 if (Lanes[0].getValueSizeInBits() == 32) {
12209 for (
unsigned I = 0;
I < 3; ++
I)
12216 Ops.push_back(Lanes[2]);
12228 if (UseNSA && IsGFX11Plus) {
12229 Ops.push_back(NodePtr);
12231 Ops.push_back(RayOrigin);
12236 for (
unsigned I = 0;
I < 3; ++
I) {
12239 {DirLanes[I], InvDirLanes[I]})));
12243 Ops.push_back(RayDir);
12244 Ops.push_back(RayInvDir);
12251 Ops.push_back(NodePtr);
12254 packLanes(RayOrigin,
true);
12255 packLanes(RayDir,
true);
12256 packLanes(RayInvDir,
false);
12261 if (NumVAddrDwords > 12) {
12269 Ops.push_back(MergedOps);
12272 Ops.push_back(TDescr);
12274 Ops.push_back(
M->getChain());
12277 MachineMemOperand *MemRef =
M->getMemOperand();
12281 case Intrinsic::amdgcn_global_atomic_fmin_num:
12282 case Intrinsic::amdgcn_global_atomic_fmax_num:
12283 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12284 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12291 unsigned Opcode = 0;
12293 case Intrinsic::amdgcn_global_atomic_fmin_num:
12294 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12298 case Intrinsic::amdgcn_global_atomic_fmax_num:
12299 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12306 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12307 Ops,
M->getMemOperand());
12309 case Intrinsic::amdgcn_s_alloc_vgpr: {
12317 ReadFirstLaneID, NumVGPRs);
12320 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12322 case Intrinsic::amdgcn_s_get_barrier_state:
12323 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12330 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12331 BarID = (BarID >> 4) & 0x3F;
12332 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12335 Ops.push_back(Chain);
12337 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12338 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12352 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12353 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12354 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12358 EVT VT =
Op->getValueType(0);
12362 case Intrinsic::amdgcn_av_load_b128: {
12366 EVT VT =
Op->getValueType(0);
12373 case Intrinsic::amdgcn_flat_load_monitor_b32:
12374 case Intrinsic::amdgcn_flat_load_monitor_b64:
12375 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12380 Op->getVTList(), {Chain, Ptr},
12383 case Intrinsic::amdgcn_global_load_monitor_b32:
12384 case Intrinsic::amdgcn_global_load_monitor_b64:
12385 case Intrinsic::amdgcn_global_load_monitor_b128: {
12390 Op->getVTList(), {Chain, Ptr},
12395 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12397 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12405SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12412 EVT VT = VTList.
VTs[0];
12415 bool IsTFE = VTList.
NumVTs == 3;
12418 unsigned NumOpDWords = NumValueDWords + 1;
12420 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12421 MachineMemOperand *OpDWordsMMO =
12423 SDValue Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12424 OpDWordsVT, OpDWordsMMO, DAG);
12429 NumValueDWords == 1
12438 if (!Subtarget->hasDwordx3LoadStores() &&
12439 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12443 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12445 WidenedMemVT, WidenedMMO);
12455 bool ImageStore)
const {
12465 if (Subtarget->hasUnpackedD16VMem()) {
12479 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12490 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12496 if ((NumElements % 2) == 1) {
12498 unsigned I = Elts.
size() / 2;
12514 if (NumElements == 3) {
12533 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12534 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12535 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12536 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12537 case Intrinsic::amdgcn_load_async_to_lds:
12538 case Intrinsic::amdgcn_global_load_async_lds:
12548 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12550 switch (IntrinsicID) {
12551 case Intrinsic::amdgcn_exp_compr: {
12572 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12576 case Intrinsic::amdgcn_struct_tbuffer_store:
12577 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12581 VData = handleD16VData(VData, DAG);
12582 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12583 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12597 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12598 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12601 M->getMemoryVT(),
M->getMemOperand());
12604 case Intrinsic::amdgcn_raw_tbuffer_store:
12605 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12609 VData = handleD16VData(VData, DAG);
12610 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12611 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12625 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12626 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12629 M->getMemoryVT(),
M->getMemOperand());
12632 case Intrinsic::amdgcn_raw_buffer_store:
12633 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12634 case Intrinsic::amdgcn_raw_buffer_store_format:
12635 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12636 const bool IsFormat =
12637 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12638 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12648 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12653 VData = handleD16VData(VData, DAG);
12663 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12664 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12678 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12679 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12684 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12687 M->getMemoryVT(),
M->getMemOperand());
12690 case Intrinsic::amdgcn_struct_buffer_store:
12691 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12692 case Intrinsic::amdgcn_struct_buffer_store_format:
12693 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12694 const bool IsFormat =
12695 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12696 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12706 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12711 VData = handleD16VData(VData, DAG);
12721 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12722 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12736 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12737 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12741 EVT VDataType = VData.getValueType().getScalarType();
12743 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12746 M->getMemoryVT(),
M->getMemOperand());
12748 case Intrinsic::amdgcn_raw_buffer_load_lds:
12749 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12750 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12751 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12752 case Intrinsic::amdgcn_struct_buffer_load_lds:
12753 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12754 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12755 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12758 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12759 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12760 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12761 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12762 unsigned OpOffset = HasVIndex ? 1 : 0;
12763 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12765 unsigned Size =
Op->getConstantOperandVal(4);
12771 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12772 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12773 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12774 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12777 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12778 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12779 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12780 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12783 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12784 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12785 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12786 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12789 if (!Subtarget->hasLDSLoadB96_B128())
12791 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12792 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12793 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12794 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12797 if (!Subtarget->hasLDSLoadB96_B128())
12799 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12800 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12801 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12802 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12810 if (HasVIndex && HasVOffset)
12814 else if (HasVIndex)
12815 Ops.push_back(
Op.getOperand(5));
12816 else if (HasVOffset)
12817 Ops.push_back(VOffset);
12819 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12820 Ops.push_back(Rsrc);
12821 Ops.push_back(
Op.getOperand(6 + OpOffset));
12822 Ops.push_back(
Op.getOperand(7 + OpOffset));
12824 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
12847 case Intrinsic::amdgcn_load_to_lds:
12848 case Intrinsic::amdgcn_load_async_to_lds:
12849 case Intrinsic::amdgcn_global_load_lds:
12850 case Intrinsic::amdgcn_global_load_async_lds: {
12851 if (!Subtarget->hasVMemToLDSLoad())
12855 unsigned Size =
Op->getConstantOperandVal(4);
12860 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
12863 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
12866 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
12869 if (!Subtarget->hasLDSLoadB96_B128())
12871 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
12874 if (!Subtarget->hasLDSLoadB96_B128())
12876 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
12892 if (
LHS->isDivergent())
12896 RHS.getOperand(0).getValueType() == MVT::i32) {
12899 VOffset =
RHS.getOperand(0);
12903 Ops.push_back(Addr);
12911 Ops.push_back(VOffset);
12914 Ops.push_back(
Op.getOperand(5));
12916 unsigned Aux =
Op.getConstantOperandVal(6);
12931 case Intrinsic::amdgcn_end_cf:
12933 Op->getOperand(2), Chain),
12935 case Intrinsic::amdgcn_s_barrier_signal_var: {
12942 if (CntC && CntC->isZero()) {
12947 std::optional<uint64_t> BarVal;
12949 BarVal =
C->getZExtValue();
12953 BarVal = *Addr + GA->getOffset();
12956 unsigned BarID = (*BarVal >> 4) & 0x3F;
12958 Ops.push_back(Chain);
12960 Op->getVTList(),
Ops);
12966 case Intrinsic::amdgcn_s_barrier_init: {
12973 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
12974 ? AMDGPU::S_BARRIER_INIT_M0
12975 : AMDGPU::S_BARRIER_SIGNAL_M0;
12986 constexpr unsigned ShAmt = 16;
12997 case Intrinsic::amdgcn_s_wakeup_barrier: {
12998 if (!Subtarget->hasSWakeupBarrier())
13002 case Intrinsic::amdgcn_s_barrier_join: {
13011 switch (IntrinsicID) {
13014 case Intrinsic::amdgcn_s_barrier_join:
13015 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13017 case Intrinsic::amdgcn_s_wakeup_barrier:
13018 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13022 unsigned BarID = (BarVal >> 4) & 0x3F;
13025 Ops.push_back(Chain);
13027 switch (IntrinsicID) {
13030 case Intrinsic::amdgcn_s_barrier_join:
13031 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13033 case Intrinsic::amdgcn_s_wakeup_barrier:
13034 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13049 case Intrinsic::amdgcn_s_prefetch_data:
13050 case Intrinsic::amdgcn_s_prefetch_inst: {
13053 return Op.getOperand(0);
13056 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13058 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13065 Op->getVTList(),
Ops,
M->getMemoryVT(),
13066 M->getMemOperand());
13068 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13069 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13070 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13078 case Intrinsic::amdgcn_av_store_b128: {
13086 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13088 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13104 return PtrVT == MVT::i64;
13118std::pair<SDValue, SDValue>
13131 bool CheckNUW = Subtarget->hasGFX1250Insts();
13148 unsigned Overflow = ImmOffset & ~MaxImm;
13149 ImmOffset -= Overflow;
13150 if ((int32_t)Overflow < 0) {
13151 Overflow += ImmOffset;
13156 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13175void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13177 Align Alignment)
const {
13179 SDLoc
DL(CombinedOffset);
13181 uint32_t
Imm =
C->getZExtValue();
13182 uint32_t SOffset, ImmOffset;
13183 if (
TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13194 bool CheckNUW = Subtarget->hasGFX1250Insts();
13197 uint32_t SOffset, ImmOffset;
13200 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13208 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13217SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13220 return MaybePointer;
13234 SDValue NumRecords =
Op->getOperand(3);
13240 if (Subtarget->has45BitNumRecordsBufferResource()) {
13243 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13262 SDValue ExtShiftedStrideVec =
13274 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13276 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13281 auto [LowHalf, HighHalf] =
13282 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13292 NumRecords, Flags);
13304 bool IsTFE)
const {
13309 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13310 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13313 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13325 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13326 : AMDGPUISD::BUFFER_LOAD_USHORT;
13328 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13342 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13346 Ops[1] = BufferStoreExt;
13347 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13348 : AMDGPUISD::BUFFER_STORE_SHORT;
13351 M->getMemOperand());
13376 DAGCombinerInfo &DCI)
const {
13377 SelectionDAG &DAG = DCI.DAG;
13392 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13399 "unexpected vector extload");
13411 "unexpected fp extload");
13429 DCI.AddToWorklist(Cvt.
getNode());
13434 DCI.AddToWorklist(Cvt.
getNode());
13445 if (Info.isEntryFunction())
13446 return Info.getUserSGPRInfo().hasFlatScratchInit();
13454 EVT MemVT =
Load->getMemoryVT();
13455 MachineMemOperand *MMO =
Load->getMemOperand();
13467 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13495 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13496 "Custom lowering for non-i32 vectors hasn't been implemented.");
13499 unsigned AS =
Load->getAddressSpace();
13500 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13507 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13511 !Subtarget->hasMultiDwordFlatScratchAddressing())
13521 Subtarget->getScalarizeGlobalBehavior() &&
Load->isSimple() &&
13524 Alignment >=
Align(4) && NumElements < 32) {
13526 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13538 if (NumElements > 4)
13541 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13551 switch (Subtarget->getMaxPrivateElementSize()) {
13557 if (NumElements > 2)
13562 if (NumElements > 4)
13565 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13574 auto Flags =
Load->getMemOperand()->getFlags();
13576 Load->getAlign(), Flags, &
Fast) &&
13585 MemVT, *
Load->getMemOperand())) {
13594 EVT VT =
Op.getValueType();
13631 EVT VT =
Op.getValueType();
13632 const SDNodeFlags
Flags =
Op->getFlags();
13634 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13640 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13643 if (CLHS->isOne()) {
13656 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13660 if (CLHS->isMinusOne()) {
13663 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13669 if (!AllowInaccurateRcp &&
13670 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13684 EVT VT =
Op.getValueType();
13685 const SDNodeFlags
Flags =
Op->getFlags();
13687 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13688 if (!AllowInaccurateDiv)
13712 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13724 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13734 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13738 return DAG.
getNode(Opcode, SL, VTList,
13747 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13757 Opcode = AMDGPUISD::FMA_W_CHAIN;
13761 return DAG.
getNode(Opcode, SL, VTList,
13767 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13768 return FastLowered;
13771 EVT VT =
Op.getValueType();
13778 if (VT == MVT::bf16) {
13801 unsigned FMADOpCode =
13805 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
13808 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13810 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
13811 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13821 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
13827 SDNodeFlags
Flags =
Op->getFlags();
13837 const APFloat K0Val(0x1p+96f);
13840 const APFloat K1Val(0x1p-32f);
13867 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
13868 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
13869 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
13874 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13875 return FastLowered;
13881 SDNodeFlags
Flags =
Op->getFlags();
13882 Flags.setNoFPExcept(
true);
13890 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
13899 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
13903 using namespace AMDGPU::Hwreg;
13904 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
13908 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
13909 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
13912 const bool HasDynamicDenormals =
13918 if (!PreservesDenormals) {
13923 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
13926 if (HasDynamicDenormals) {
13930 SavedDenormMode =
SDValue(GetReg, 0);
13936 SDNode *EnableDenorm;
13937 if (Subtarget->hasDenormModeInst()) {
13938 const SDValue EnableDenormValue =
13941 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
13945 const SDValue EnableDenormValue =
13947 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
13948 {EnableDenormValue,
BitField, Glue});
13958 ApproxRcp, One, NegDivScale0, Flags);
13961 ApproxRcp, Fma0, Flags);
13967 NumeratorScaled,
Mul, Flags);
13973 NumeratorScaled, Fma3, Flags);
13975 if (!PreservesDenormals) {
13976 SDNode *DisableDenorm;
13977 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
13981 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
13983 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
13987 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
13988 const SDValue DisableDenormValue =
13989 HasDynamicDenormals
13994 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14005 {Fma4, Fma1, Fma3, Scale},
Flags);
14007 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14011 if (
SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14012 return FastLowered;
14020 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14026 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14044 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14074 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14076 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14080 EVT VT =
Op.getValueType();
14082 if (VT == MVT::f32)
14083 return LowerFDIV32(
Op, DAG);
14085 if (VT == MVT::f64)
14086 return LowerFDIV64(
Op, DAG);
14088 if (VT == MVT::f16 || VT == MVT::bf16)
14089 return LowerFDIV16(
Op, DAG);
14098 EVT ResultExpVT =
Op->getValueType(1);
14099 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14109 if (Subtarget->hasFractBug()) {
14127 EVT VT =
Store->getMemoryVT();
14129 if (VT == MVT::i1) {
14133 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14137 Store->getValue().getValueType().getScalarType() == MVT::i32);
14139 unsigned AS =
Store->getAddressSpace();
14140 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14148 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14152 !Subtarget->hasMultiDwordFlatScratchAddressing())
14159 if (NumElements > 4)
14162 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14166 VT, *
Store->getMemOperand()))
14172 switch (Subtarget->getMaxPrivateElementSize()) {
14176 if (NumElements > 2)
14180 if (NumElements > 4 ||
14181 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14189 auto Flags =
Store->getMemOperand()->getFlags();
14208 assert(!Subtarget->has16BitInsts());
14209 SDNodeFlags
Flags =
Op->getFlags();
14223 SDNodeFlags
Flags =
Op->getFlags();
14224 MVT VT =
Op.getValueType().getSimpleVT();
14332 SDNodeFlags
Flags =
Op->getFlags();
14341 if (!
Flags.hasApproximateFuncs()) {
14373 if (!
Flags.hasApproximateFuncs()) {
14382 ScaleDownFactor, ZeroInt);
14389 if (
Flags.hasNoInfs()) {
14405 EVT VT =
Op.getValueType();
14416 if (!
V.getValueType().isVector())
14424 if (Subtarget->hasTrigReducedRange()) {
14426 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14431 switch (
Op.getOpcode()) {
14433 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14436 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14442 return UnrollIfVec(TrigVal);
14462 EVT VT =
Op.getValueType();
14470 Op->getVTList(),
Ops, VT,
14479SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14480 DAGCombinerInfo &DCI)
const {
14481 EVT VT =
N->getValueType(0);
14483 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14486 SelectionDAG &DAG = DCI.DAG;
14490 EVT SrcVT = Src.getValueType();
14496 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14499 DCI.AddToWorklist(Cvt.
getNode());
14502 if (ScalarVT != MVT::f32) {
14514 DAGCombinerInfo &DCI)
const {
14525 SelectionDAG &DAG = DCI.DAG;
14544 for (
unsigned I = 0;
I != NumElts; ++
I) {
14568 if (NewElts.
size() == 1)
14590 for (
unsigned I = 0;
I != NumElts; ++
I) {
14625SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14627 DAGCombinerInfo &DCI)
const {
14644 SelectionDAG &DAG = DCI.DAG;
14657 AM.BaseOffs =
Offset.getSExtValue();
14662 EVT VT =
N->getValueType(0);
14668 Flags.setNoUnsignedWrap(
14669 N->getFlags().hasNoUnsignedWrap() &&
14681 switch (
N->getOpcode()) {
14692 DAGCombinerInfo &DCI)
const {
14693 SelectionDAG &DAG = DCI.DAG;
14700 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14701 N->getMemoryVT(), DCI);
14705 NewOps[PtrIdx] = NewPtr;
14714 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14715 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14724SDValue SITargetLowering::splitBinaryBitConstantOp(
14728 uint32_t ValLo =
Lo_32(Val);
14729 uint32_t ValHi =
Hi_32(Val);
14736 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14750 if (V.getValueType() != MVT::i1)
14752 switch (V.getOpcode()) {
14757 case AMDGPUISD::FP_CLASS:
14769 return V.getResNo() == 1;
14771 unsigned IntrinsicID = V.getConstantOperandVal(0);
14772 switch (IntrinsicID) {
14773 case Intrinsic::amdgcn_is_shared:
14774 case Intrinsic::amdgcn_is_private:
14791 if (!(
C & 0x000000ff))
14792 ZeroByteMask |= 0x000000ff;
14793 if (!(
C & 0x0000ff00))
14794 ZeroByteMask |= 0x0000ff00;
14795 if (!(
C & 0x00ff0000))
14796 ZeroByteMask |= 0x00ff0000;
14797 if (!(
C & 0xff000000))
14798 ZeroByteMask |= 0xff000000;
14799 uint32_t NonZeroByteMask = ~ZeroByteMask;
14800 if ((NonZeroByteMask &
C) != NonZeroByteMask)
14813 assert(V.getValueSizeInBits() == 32);
14815 if (V.getNumOperands() != 2)
14824 switch (V.getOpcode()) {
14829 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14834 return (0x03020100 & ~ConstMask) | ConstMask;
14841 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
14847 return uint32_t(0x0c0c0c0c03020100ull >>
C);
14854 DAGCombinerInfo &DCI)
const {
14855 if (DCI.isBeforeLegalize())
14858 SelectionDAG &DAG = DCI.DAG;
14859 EVT VT =
N->getValueType(0);
14864 if (VT == MVT::i64 && CRHS) {
14866 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
14870 if (CRHS && VT == MVT::i32) {
14880 unsigned Shift = CShift->getZExtValue();
14882 unsigned Offset = NB + Shift;
14883 if ((
Offset & (Bits - 1)) == 0) {
14886 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
14907 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
14909 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
14922 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
14927 if (
X !=
LHS.getOperand(1))
14931 const ConstantFPSDNode *C1 =
14948 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
14954 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
14957 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
14965 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
14966 LHS.getOperand(0) ==
LHS.getOperand(1))) {
14968 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
14969 :
Mask->getZExtValue() & OrdMask;
14972 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
14990 N->isDivergent() &&
TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
14993 if (LHSMask != ~0u && RHSMask != ~0u) {
14996 if (LHSMask > RHSMask) {
15003 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15004 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15007 if (!(LHSUsedLanes & RHSUsedLanes) &&
15010 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15016 uint32_t
Mask = LHSMask & RHSMask;
15017 for (
unsigned I = 0;
I < 32;
I += 8) {
15018 uint32_t ByteSel = 0xff <<
I;
15019 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15020 Mask &= (0x0c <<
I) & 0xffffffff;
15025 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15028 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15078static const std::optional<ByteProvider<SDValue>>
15080 unsigned Depth = 0) {
15083 return std::nullopt;
15085 if (
Op.getValueSizeInBits() < 8)
15086 return std::nullopt;
15088 if (
Op.getValueType().isVector())
15091 switch (
Op->getOpcode()) {
15104 NarrowVT = VTSign->getVT();
15107 return std::nullopt;
15110 if (SrcIndex >= NarrowByteWidth)
15111 return std::nullopt;
15119 return std::nullopt;
15121 uint64_t BitShift = ShiftOp->getZExtValue();
15123 if (BitShift % 8 != 0)
15124 return std::nullopt;
15126 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15127 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15128 return std::nullopt;
15147static const std::optional<ByteProvider<SDValue>>
15149 unsigned StartingIndex = 0) {
15153 return std::nullopt;
15155 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15157 return std::nullopt;
15159 return std::nullopt;
15161 bool IsVec =
Op.getValueType().isVector();
15162 switch (
Op.getOpcode()) {
15165 return std::nullopt;
15170 return std::nullopt;
15174 return std::nullopt;
15177 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15178 return std::nullopt;
15179 if (!
LHS ||
LHS->isConstantZero())
15181 if (!
RHS ||
RHS->isConstantZero())
15183 return std::nullopt;
15188 return std::nullopt;
15192 return std::nullopt;
15194 uint32_t BitMask = BitMaskOp->getZExtValue();
15196 uint32_t IndexMask = 0xFF << (Index * 8);
15198 if ((IndexMask & BitMask) != IndexMask) {
15201 if (IndexMask & BitMask)
15202 return std::nullopt;
15211 return std::nullopt;
15215 if (!ShiftOp ||
Op.getValueType().isVector())
15216 return std::nullopt;
15218 uint64_t BitsProvided =
Op.getValueSizeInBits();
15219 if (BitsProvided % 8 != 0)
15220 return std::nullopt;
15222 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15224 return std::nullopt;
15226 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15227 uint64_t ByteShift = BitShift / 8;
15229 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15230 uint64_t BytesProvided = BitsProvided / 8;
15231 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15232 NewIndex %= BytesProvided;
15239 return std::nullopt;
15243 return std::nullopt;
15245 uint64_t BitShift = ShiftOp->getZExtValue();
15247 return std::nullopt;
15249 auto BitsProvided =
Op.getScalarValueSizeInBits();
15250 if (BitsProvided % 8 != 0)
15251 return std::nullopt;
15253 uint64_t BytesProvided = BitsProvided / 8;
15254 uint64_t ByteShift = BitShift / 8;
15255 if (Index + ByteShift < BytesProvided)
15257 Index + ByteShift);
15260 return std::nullopt;
15266 return std::nullopt;
15270 return std::nullopt;
15272 uint64_t BitShift = ShiftOp->getZExtValue();
15273 if (BitShift % 8 != 0)
15274 return std::nullopt;
15275 uint64_t ByteShift = BitShift / 8;
15281 return Index < ByteShift
15284 Depth + 1, StartingIndex);
15293 return std::nullopt;
15301 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15303 if (NarrowBitWidth % 8 != 0)
15304 return std::nullopt;
15305 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15307 if (Index >= NarrowByteWidth)
15309 ? std::optional<ByteProvider<SDValue>>(
15317 return std::nullopt;
15321 if (NarrowByteWidth >= Index) {
15326 return std::nullopt;
15333 return std::nullopt;
15339 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15340 if (NarrowBitWidth % 8 != 0)
15341 return std::nullopt;
15342 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15347 if (Index >= NarrowByteWidth) {
15349 ? std::optional<ByteProvider<SDValue>>(
15354 if (NarrowByteWidth > Index) {
15358 return std::nullopt;
15363 return std::nullopt;
15366 Depth + 1, StartingIndex);
15372 return std::nullopt;
15373 auto VecIdx = IdxOp->getZExtValue();
15374 auto ScalarSize =
Op.getScalarValueSizeInBits();
15375 if (ScalarSize < 32)
15376 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15378 StartingIndex, Index);
15381 case AMDGPUISD::PERM: {
15383 return std::nullopt;
15387 return std::nullopt;
15390 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15391 if (IdxMask > 0x07 && IdxMask != 0x0c)
15392 return std::nullopt;
15394 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15395 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15397 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15403 return std::nullopt;
15418 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15425 auto MemVT = L->getMemoryVT();
15428 return L->getMemoryVT().getSizeInBits() == 16;
15438 int Low8 = Mask & 0xff;
15439 int Hi8 = (Mask & 0xff00) >> 8;
15441 assert(Low8 < 8 && Hi8 < 8);
15443 bool IsConsecutive = (Hi8 - Low8 == 1);
15448 bool Is16Aligned = !(Low8 % 2);
15450 return IsConsecutive && Is16Aligned;
15458 int Low16 = PermMask & 0xffff;
15459 int Hi16 = (PermMask & 0xffff0000) >> 16;
15469 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15471 if (!OtherOpIs16Bit)
15479 unsigned DWordOffset) {
15484 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15489 if (Src.getValueType().isVector()) {
15490 auto ScalarTySize = Src.getScalarValueSizeInBits();
15491 auto ScalarTy = Src.getValueType().getScalarType();
15492 if (ScalarTySize == 32) {
15496 if (ScalarTySize > 32) {
15499 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15500 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15507 assert(ScalarTySize < 32);
15508 auto NumElements =
TypeSize / ScalarTySize;
15509 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15510 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15511 auto NumElementsIn32 = 32 / ScalarTySize;
15512 auto NumAvailElements = DWordOffset < Trunc32Elements
15514 : NumElements - NormalizedTrunc;
15527 auto ShiftVal = 32 * DWordOffset;
15535 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15540 for (
int i = 0; i < 4; i++) {
15542 std::optional<ByteProvider<SDValue>>
P =
15545 if (!
P ||
P->isConstantZero())
15550 if (PermNodes.
size() != 4)
15553 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15554 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15556 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15557 auto PermOp = PermNodes[i];
15560 int SrcByteAdjust = 4;
15564 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15565 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15567 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15568 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15572 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15573 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15576 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15578 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15581 SDValue Op = *PermNodes[FirstSrc.first].Src;
15583 assert(
Op.getValueSizeInBits() == 32);
15587 int Low16 = PermMask & 0xffff;
15588 int Hi16 = (PermMask & 0xffff0000) >> 16;
15590 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15591 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15594 if (WellFormedLow && WellFormedHi)
15598 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15607 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15608 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15613 assert(
Op.getValueType().isByteSized() &&
15624 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15631 DAGCombinerInfo &DCI)
const {
15632 SelectionDAG &DAG = DCI.DAG;
15636 EVT VT =
N->getValueType(0);
15637 if (VT == MVT::i1) {
15639 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15640 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15642 if (Src !=
RHS.getOperand(0))
15647 if (!CLHS || !CRHS)
15651 static const uint32_t MaxMask = 0x3ff;
15656 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15665 LHS.getOpcode() == AMDGPUISD::PERM &&
15671 Sel |=
LHS.getConstantOperandVal(2);
15673 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15680 N->isDivergent() &&
TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15684 auto usesCombinedOperand = [](SDNode *OrUse) {
15687 !OrUse->getValueType(0).isVector())
15691 for (
auto *VUser : OrUse->users()) {
15692 if (!VUser->getValueType(0).isVector())
15699 if (VUser->getOpcode() == VectorwiseOp)
15705 if (!
any_of(
N->users(), usesCombinedOperand))
15711 if (LHSMask != ~0u && RHSMask != ~0u) {
15714 if (LHSMask > RHSMask) {
15721 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15722 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15725 if (!(LHSUsedLanes & RHSUsedLanes) &&
15728 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15730 LHSMask &= ~RHSUsedLanes;
15731 RHSMask &= ~LHSUsedLanes;
15733 LHSMask |= LHSUsedLanes & 0x04040404;
15735 uint32_t Sel = LHSMask | RHSMask;
15738 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15743 if (LHSMask == ~0u || RHSMask == ~0u) {
15784 return IdentitySrc;
15790 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15805 if (SrcVT == MVT::i32) {
15810 DCI.AddToWorklist(LowOr.
getNode());
15811 DCI.AddToWorklist(HiBits.getNode());
15822 N->getOperand(0), CRHS))
15830 DAGCombinerInfo &DCI)
const {
15831 if (
SDValue RV = reassociateScalarOps(
N, DCI.DAG))
15838 SelectionDAG &DAG = DCI.DAG;
15840 EVT VT =
N->getValueType(0);
15841 if (CRHS && VT == MVT::i64) {
15843 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
15850 unsigned Opc =
LHS.getOpcode();
15880 LHS->getOperand(0), FNegLHS, FNegRHS);
15889SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
15890 DAGCombinerInfo &DCI)
const {
15891 if (!Subtarget->has16BitInsts() ||
15895 EVT VT =
N->getValueType(0);
15896 if (VT != MVT::i32)
15900 if (Src.getValueType() != MVT::i16)
15903 if (!Src->hasOneUse())
15910 std::optional<ByteProvider<SDValue>> BP0 =
15912 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
15916 std::optional<ByteProvider<SDValue>> BP1 =
15918 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
15926 SelectionDAG &DAG = DCI.DAG;
15928 uint32_t PermMask = 0x0c0c0c0c;
15931 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
15936 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
15939 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
15944SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
15945 DAGCombinerInfo &DCI)
const {
15951 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
15952 VTSign->getVT() == MVT::i8) ||
15953 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
15954 VTSign->getVT() == MVT::i16))) {
15955 assert(Subtarget->hasScalarSubwordLoads() &&
15956 "s_buffer_load_{u8, i8} are supported "
15957 "in GFX12 (or newer) architectures.");
15958 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
15959 ? AMDGPUISD::SBUFFER_LOAD_BYTE
15960 : AMDGPUISD::SBUFFER_LOAD_SHORT;
15963 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
15971 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
15972 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
15973 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
15975 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
15976 VTSign->getVT() == MVT::i8) ||
15977 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
15978 VTSign->getVT() == MVT::i16)) &&
15987 Src.getOperand(6), Src.getOperand(7)};
15990 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
15991 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
15992 ? AMDGPUISD::BUFFER_LOAD_BYTE
15993 : AMDGPUISD::BUFFER_LOAD_SHORT;
15994 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
15995 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
15996 return DCI.DAG.getMergeValues(
15997 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16003 DAGCombinerInfo &DCI)
const {
16004 SelectionDAG &DAG = DCI.DAG;
16011 if (
N->getOperand(0).isUndef())
16018 DAGCombinerInfo &DCI)
const {
16019 EVT VT =
N->getValueType(0);
16030 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16039 unsigned MaxDepth)
const {
16040 EVT VT =
Op.getValueType();
16042 "expected a floating-point value to query canonicality of");
16048 unsigned MaxDepth)
const {
16050 "QueryVT must be a floating-point scalar type");
16051 EVT VT =
Op.getValueType();
16055 unsigned Opcode =
Op.getOpcode();
16060 const auto &
F = CFP->getValueAPF();
16061 if (
F.isNaN() &&
F.isSignaling())
16063 if (!
F.isDenormal())
16095 case AMDGPUISD::FMUL_LEGACY:
16096 case AMDGPUISD::FMAD_FTZ:
16097 case AMDGPUISD::RCP:
16098 case AMDGPUISD::RSQ:
16099 case AMDGPUISD::RSQ_CLAMP:
16100 case AMDGPUISD::RCP_LEGACY:
16101 case AMDGPUISD::RCP_IFLAG:
16102 case AMDGPUISD::LOG:
16103 case AMDGPUISD::EXP:
16104 case AMDGPUISD::DIV_SCALE:
16105 case AMDGPUISD::DIV_FMAS:
16106 case AMDGPUISD::DIV_FIXUP:
16107 case AMDGPUISD::FRACT:
16108 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16109 case AMDGPUISD::CVT_F32_UBYTE0:
16110 case AMDGPUISD::CVT_F32_UBYTE1:
16111 case AMDGPUISD::CVT_F32_UBYTE2:
16112 case AMDGPUISD::CVT_F32_UBYTE3:
16113 case AMDGPUISD::FP_TO_FP16:
16114 case AMDGPUISD::SIN_HW:
16115 case AMDGPUISD::COS_HW:
16127 if (
Op.getValueType() == MVT::i32) {
16133 if (RHS->getZExtValue() == 0xffff0000) {
16144 return Op.getValueType().getScalarType() != MVT::f16;
16154 case AMDGPUISD::CLAMP:
16155 case AMDGPUISD::FMED3:
16156 case AMDGPUISD::FMAX3:
16157 case AMDGPUISD::FMIN3:
16158 case AMDGPUISD::FMAXIMUM3:
16159 case AMDGPUISD::FMINIMUM3: {
16165 if (Subtarget->supportsMinMaxDenormModes() ||
16175 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16190 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16224 if (
Op.getValueType() == MVT::i16) {
16236 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16238 switch (IntrinsicID) {
16239 case Intrinsic::amdgcn_cvt_pkrtz:
16240 case Intrinsic::amdgcn_cubeid:
16241 case Intrinsic::amdgcn_frexp_mant:
16242 case Intrinsic::amdgcn_fdot2:
16243 case Intrinsic::amdgcn_rcp:
16244 case Intrinsic::amdgcn_rsq:
16245 case Intrinsic::amdgcn_rsq_clamp:
16246 case Intrinsic::amdgcn_rcp_legacy:
16247 case Intrinsic::amdgcn_rsq_legacy:
16248 case Intrinsic::amdgcn_trig_preop:
16249 case Intrinsic::amdgcn_tanh:
16250 case Intrinsic::amdgcn_log:
16251 case Intrinsic::amdgcn_exp2:
16252 case Intrinsic::amdgcn_sqrt:
16270 unsigned MaxDepth)
const {
16273 unsigned Opcode =
MI->getOpcode();
16275 if (Opcode == AMDGPU::G_FCANONICALIZE)
16278 std::optional<FPValueAndVReg> FCR;
16281 if (FCR->Value.isSignaling())
16283 if (!FCR->Value.isDenormal())
16294 case AMDGPU::G_FADD:
16295 case AMDGPU::G_FSUB:
16296 case AMDGPU::G_FMUL:
16297 case AMDGPU::G_FCEIL:
16298 case AMDGPU::G_FFLOOR:
16299 case AMDGPU::G_FRINT:
16300 case AMDGPU::G_FNEARBYINT:
16301 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16302 case AMDGPU::G_INTRINSIC_TRUNC:
16303 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16304 case AMDGPU::G_FMA:
16305 case AMDGPU::G_FMAD:
16306 case AMDGPU::G_FSQRT:
16307 case AMDGPU::G_FDIV:
16308 case AMDGPU::G_FREM:
16309 case AMDGPU::G_FPOW:
16310 case AMDGPU::G_FPEXT:
16311 case AMDGPU::G_FLOG:
16312 case AMDGPU::G_FLOG2:
16313 case AMDGPU::G_FLOG10:
16314 case AMDGPU::G_FPTRUNC:
16315 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16316 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16317 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16318 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16319 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16321 case AMDGPU::G_FNEG:
16322 case AMDGPU::G_FABS:
16323 case AMDGPU::G_FCOPYSIGN:
16325 case AMDGPU::G_FMINNUM:
16326 case AMDGPU::G_FMAXNUM:
16327 case AMDGPU::G_FMINNUM_IEEE:
16328 case AMDGPU::G_FMAXNUM_IEEE:
16329 case AMDGPU::G_FMINIMUM:
16330 case AMDGPU::G_FMAXIMUM:
16331 case AMDGPU::G_FMINIMUMNUM:
16332 case AMDGPU::G_FMAXIMUMNUM: {
16333 if (Subtarget->supportsMinMaxDenormModes() ||
16340 case AMDGPU::G_BUILD_VECTOR:
16345 case AMDGPU::G_INTRINSIC:
16346 case AMDGPU::G_INTRINSIC_CONVERGENT:
16348 case Intrinsic::amdgcn_fmul_legacy:
16349 case Intrinsic::amdgcn_fmad_ftz:
16350 case Intrinsic::amdgcn_sqrt:
16351 case Intrinsic::amdgcn_fmed3:
16352 case Intrinsic::amdgcn_sin:
16353 case Intrinsic::amdgcn_cos:
16354 case Intrinsic::amdgcn_log:
16355 case Intrinsic::amdgcn_exp2:
16356 case Intrinsic::amdgcn_log_clamp:
16357 case Intrinsic::amdgcn_rcp:
16358 case Intrinsic::amdgcn_rcp_legacy:
16359 case Intrinsic::amdgcn_rsq:
16360 case Intrinsic::amdgcn_rsq_clamp:
16361 case Intrinsic::amdgcn_rsq_legacy:
16362 case Intrinsic::amdgcn_div_scale:
16363 case Intrinsic::amdgcn_div_fmas:
16364 case Intrinsic::amdgcn_div_fixup:
16365 case Intrinsic::amdgcn_fract:
16366 case Intrinsic::amdgcn_cvt_pkrtz:
16367 case Intrinsic::amdgcn_cubeid:
16368 case Intrinsic::amdgcn_cubema:
16369 case Intrinsic::amdgcn_cubesc:
16370 case Intrinsic::amdgcn_cubetc:
16371 case Intrinsic::amdgcn_frexp_mant:
16372 case Intrinsic::amdgcn_fdot2:
16373 case Intrinsic::amdgcn_trig_preop:
16374 case Intrinsic::amdgcn_tanh:
16393 if (
C.isDenormal()) {
16406 if (
C.isSignaling()) {
16421SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16422 DAGCombinerInfo &DCI)
const {
16423 SelectionDAG &DAG = DCI.DAG;
16425 EVT VT =
N->getValueType(0);
16434 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16449 EVT EltVT =
Lo.getValueType();
16458 for (
unsigned I = 0;
I != 2; ++
I) {
16462 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16463 }
else if (
Op.isUndef()) {
16498 return AMDGPUISD::FMAX3;
16500 return AMDGPUISD::FMAXIMUM3;
16502 return AMDGPUISD::SMAX3;
16504 return AMDGPUISD::UMAX3;
16508 return AMDGPUISD::FMIN3;
16510 return AMDGPUISD::FMINIMUM3;
16512 return AMDGPUISD::SMIN3;
16514 return AMDGPUISD::UMIN3;
16535 if (!MinK || !MaxK)
16547 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16548 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16549 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16573 bool IsKnownNoNaNs)
const {
16609 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16615 if (
Info->getMode().DX10Clamp) {
16624 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16656 case AMDGPUISD::FMIN_LEGACY:
16657 case AMDGPUISD::FMAX_LEGACY:
16658 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.
hasMin3Max3_16()) ||
16659 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16662 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16663 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16664 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16669 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.
hasMin3Max3_16());
16678 DAGCombinerInfo &DCI)
const {
16679 SelectionDAG &DAG = DCI.DAG;
16690 auto IsTreeWithCombinableChildren = [
Opc](
SDValue Op) {
16691 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16692 Op.getOperand(0).hasOneUse()) ||
16694 Op.getOperand(1).hasOneUse());
16699 bool HasCombinableTreeChild =
16700 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16701 IsTreeWithCombinableChildren(Op1));
16710 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16740 uint64_t Clamp = 0;
16748 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
16756 if (
SDValue Med3 = performIntMed3ImmCombine(
16761 if (
SDValue Med3 = performIntMed3ImmCombine(
16767 if (
SDValue Med3 = performIntMed3ImmCombine(
16772 if (
SDValue Med3 = performIntMed3ImmCombine(
16785 (
Opc == AMDGPUISD::FMIN_LEGACY &&
16786 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16787 (VT == MVT::f32 || VT == MVT::f64 ||
16788 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16789 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16790 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16791 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16793 if (
SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
16794 N->getFlags().hasNoNaNs()))
16801 const SDNodeFlags
Flags =
N->getFlags();
16803 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16807 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
16817 return (CA->isPosZero() && CB->isOne()) ||
16818 (CA->isOne() && CB->isPosZero());
16827 DAGCombinerInfo &DCI)
const {
16828 EVT VT =
N->getValueType(0);
16832 SelectionDAG &DAG = DCI.DAG;
16843 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16847 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16851 if (
Info->getMode().DX10Clamp) {
16864 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
16871 DAGCombinerInfo &DCI)
const {
16875 return DCI.DAG.getUNDEF(
N->getValueType(0));
16883 bool IsDivergentIdx,
16888 unsigned VecSize = EltSize * NumElem;
16891 if (VecSize <= 64 && EltSize < 32)
16900 if (IsDivergentIdx)
16904 unsigned NumInsts = NumElem +
16905 ((EltSize + 31) / 32) * NumElem ;
16909 if (Subtarget->useVGPRIndexMode())
16910 return NumInsts <= 16;
16914 if (Subtarget->hasMovrel())
16915 return NumInsts <= 15;
16921 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
16936SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
16937 DAGCombinerInfo &DCI)
const {
16943 EVT ResVT =
N->getValueType(0);
16967 if (!
C ||
C->getZExtValue() != 0x1f)
16983 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17011 DCI.AddToWorklist(Elt0.
getNode());
17012 DCI.AddToWorklist(Elt1.
getNode());
17043 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17044 uint64_t KImmValue = KImm->getZExtValue();
17046 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17049 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17050 uint64_t KFPImmValue =
17051 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17052 return DAG.
getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17058 if (!DCI.isBeforeLegalize())
17065 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17068 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17069 unsigned EltIdx = BitIndex / 32;
17070 unsigned LeftoverBitIdx = BitIndex % 32;
17074 DCI.AddToWorklist(Cast.
getNode());
17078 DCI.AddToWorklist(Elt.
getNode());
17081 DCI.AddToWorklist(Srl.
getNode());
17085 DCI.AddToWorklist(Trunc.
getNode());
17087 if (VecEltVT == ResVT) {
17099SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17100 DAGCombinerInfo &DCI)
const {
17111 SelectionDAG &DAG = DCI.DAG;
17131 Src.getOperand(0).getValueType() == MVT::f16) {
17132 return Src.getOperand(0);
17136 APFloat Val = CFP->getValueAPF();
17137 bool LosesInfo =
true;
17147 DAGCombinerInfo &DCI)
const {
17148 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17149 "combine only useful on gfx8");
17151 SDValue TruncSrc =
N->getOperand(0);
17152 EVT VT =
N->getValueType(0);
17153 if (VT != MVT::f16)
17156 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17160 SelectionDAG &DAG = DCI.DAG;
17191unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17193 const SDNode *N1)
const {
17198 if (((VT == MVT::f32 &&
17200 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17220 EVT VT =
N->getValueType(0);
17221 if (VT != MVT::i32 && VT != MVT::i64)
17227 unsigned Opc =
N->getOpcode();
17282 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17301 DAGCombinerInfo &DCI)
const {
17304 SelectionDAG &DAG = DCI.DAG;
17305 EVT VT =
N->getValueType(0);
17315 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17319 if (NumBits <= 32 || NumBits > 64)
17330 if (!Subtarget->hasFullRate64Ops()) {
17331 unsigned NumUsers = 0;
17332 for (SDNode *User :
LHS->
users()) {
17335 if (!
User->isAnyAdd())
17359 bool MulSignedLo =
false;
17360 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17369 if (VT != MVT::i64) {
17392 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17394 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17395 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17397 if (!MulLHSUnsigned32) {
17404 if (!MulRHSUnsigned32) {
17415 if (VT != MVT::i64)
17421SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17422 DAGCombinerInfo &DCI)
const {
17432 SelectionDAG &DAG = DCI.DAG;
17447 unsigned Opcode =
N->getOpcode();
17451 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17462static std::optional<ByteProvider<SDValue>>
17465 if (!Byte0 || Byte0->isConstantZero()) {
17466 return std::nullopt;
17469 if (Byte1 && !Byte1->isConstantZero()) {
17470 return std::nullopt;
17476 unsigned FirstCs =
First & 0x0c0c0c0c;
17477 unsigned SecondCs = Second & 0x0c0c0c0c;
17478 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17479 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17481 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17482 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17483 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17484 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17486 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17510 for (
int BPI = 0; BPI < 2; BPI++) {
17513 BPP = {Src1, Src0};
17515 unsigned ZeroMask = 0x0c0c0c0c;
17516 unsigned FMask = 0xFF << (8 * (3 - Step));
17518 unsigned FirstMask =
17519 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17520 unsigned SecondMask =
17521 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17525 int FirstGroup = -1;
17526 for (
int I = 0;
I < 2;
I++) {
17528 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17529 return IterElt.SrcOp == *BPP.first.Src &&
17530 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17534 if (Match != Srcs.
end()) {
17535 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17540 if (FirstGroup != -1) {
17542 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17543 return IterElt.SrcOp == *BPP.second.Src &&
17544 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17547 if (Match != Srcs.
end()) {
17548 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17550 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17558 unsigned ZeroMask = 0x0c0c0c0c;
17559 unsigned FMask = 0xFF << (8 * (3 - Step));
17563 ((Src0.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17567 ((Src1.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17576 if (Srcs.
size() == 1) {
17577 auto *Elt = Srcs.
begin();
17581 if (Elt->PermMask == 0x3020100)
17584 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17588 auto *FirstElt = Srcs.
begin();
17589 auto *SecondElt = std::next(FirstElt);
17596 auto FirstMask = FirstElt->PermMask;
17597 auto SecondMask = SecondElt->PermMask;
17599 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17600 unsigned FirstPlusFour = FirstMask | 0x04040404;
17603 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17615 FirstElt = std::next(SecondElt);
17616 if (FirstElt == Srcs.
end())
17619 SecondElt = std::next(FirstElt);
17622 if (SecondElt == Srcs.
end()) {
17627 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17628 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17634 return Perms.
size() == 2
17640 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17641 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17642 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17643 EntryMask += ZeroMask;
17648 auto Opcode =
Op.getOpcode();
17650 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17651 Opcode == AMDGPUISD::MUL_I24);
17654static std::optional<bool>
17665 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17668 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17670 assert(!(S0IsUnsigned && S0IsSigned));
17671 assert(!(S1IsUnsigned && S1IsSigned));
17679 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17685 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17686 return std::nullopt;
17698 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17699 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17704 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17710 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17711 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17712 return std::nullopt;
17718 DAGCombinerInfo &DCI)
const {
17719 SelectionDAG &DAG = DCI.DAG;
17720 EVT VT =
N->getValueType(0);
17726 if (Subtarget->hasMad64_32()) {
17727 if (
SDValue Folded = tryFoldToMad64_32(
N, DCI))
17732 if (
SDValue V = reassociateScalarOps(
N, DAG)) {
17736 if (VT == MVT::i64) {
17737 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17742 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17744 std::optional<bool> IsSigned;
17750 int ChainLength = 0;
17751 for (
int I = 0;
I < 4;
I++) {
17755 auto Src0 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17758 auto Src1 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17763 TempNode->getOperand(MulIdx), *Src0, *Src1,
17764 TempNode->getOperand(MulIdx)->getOperand(0),
17765 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17769 IsSigned = *IterIsSigned;
17770 if (*IterIsSigned != *IsSigned)
17773 auto AddIdx = 1 - MulIdx;
17776 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
17777 Src2s.
push_back(TempNode->getOperand(AddIdx));
17787 TempNode->getOperand(AddIdx), *Src0, *Src1,
17788 TempNode->getOperand(AddIdx)->getOperand(0),
17789 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17793 if (*IterIsSigned != *IsSigned)
17797 ChainLength =
I + 2;
17801 TempNode = TempNode->getOperand(AddIdx);
17803 ChainLength =
I + 1;
17805 if (TempNode.getOpcode() !=
ISD::ADD)
17807 LHS = TempNode->getOperand(0);
17808 RHS = TempNode->getOperand(1);
17811 if (ChainLength < 2)
17817 if (ChainLength < 4) {
17827 bool UseOriginalSrc =
false;
17828 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
17829 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
17830 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
17831 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
17832 SmallVector<unsigned, 4> SrcBytes;
17833 auto Src0Mask = Src0s.
begin()->PermMask;
17834 SrcBytes.
push_back(Src0Mask & 0xFF000000);
17835 bool UniqueEntries =
true;
17836 for (
auto I = 1;
I < 4;
I++) {
17837 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
17840 UniqueEntries =
false;
17846 if (UniqueEntries) {
17847 UseOriginalSrc =
true;
17849 auto *FirstElt = Src0s.
begin();
17853 auto *SecondElt = Src1s.
begin();
17855 SecondElt->DWordOffset);
17864 if (!UseOriginalSrc) {
17871 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
17874 : Intrinsic::amdgcn_udot4,
17884 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
17889 unsigned Opc =
LHS.getOpcode();
17901 auto Cond =
RHS.getOperand(0);
17906 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
17923 DAGCombinerInfo &DCI)
const {
17924 SelectionDAG &DAG = DCI.DAG;
17926 EVT VT =
N->getValueType(0);
17939 SDNodeFlags ShlFlags = N1->
getFlags();
17943 SDNodeFlags NewShlFlags =
17948 DCI.AddToWorklist(Inner.
getNode());
17955 if (Subtarget->hasMad64_32()) {
17956 if (
SDValue Folded = tryFoldToMad64_32(
N, DCI))
17965 if (VT == MVT::i64) {
17966 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17979 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
17980 Y->isDivergent() !=
Z->isDivergent()) {
17989 if (
Y->isDivergent())
17992 SDNodeFlags ReassocFlags =
17995 DCI.AddToWorklist(UniformInner.
getNode());
18007 DAGCombinerInfo &DCI)
const {
18008 SelectionDAG &DAG = DCI.DAG;
18009 EVT VT =
N->getValueType(0);
18011 if (VT == MVT::i64) {
18012 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18016 if (VT != MVT::i32)
18025 unsigned Opc =
RHS.getOpcode();
18032 auto Cond =
RHS.getOperand(0);
18037 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18063 ConstantSDNode *ShiftAmt =
18065 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18076 DAGCombinerInfo &DCI)
const {
18080 SelectionDAG &DAG = DCI.DAG;
18081 EVT VT =
N->getValueType(0);
18093 if (
A ==
LHS.getOperand(1)) {
18094 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18095 if (FusedOp != 0) {
18097 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18105 if (
A ==
RHS.getOperand(1)) {
18106 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18107 if (FusedOp != 0) {
18109 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18118 DAGCombinerInfo &DCI)
const {
18122 SelectionDAG &DAG = DCI.DAG;
18124 EVT VT =
N->getValueType(0);
18137 if (
A ==
LHS.getOperand(1)) {
18138 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18139 if (FusedOp != 0) {
18143 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18152 if (
A ==
RHS.getOperand(1)) {
18153 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18154 if (FusedOp != 0) {
18156 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18165 DAGCombinerInfo &DCI)
const {
18166 SelectionDAG &DAG = DCI.DAG;
18168 EVT VT =
N->getValueType(0);
18170 if (VT != MVT::f16 && VT != MVT::bf16)
18176 SDNodeFlags
Flags =
N->getFlags();
18177 SDNodeFlags RHSFlags =
RHS->getFlags();
18183 bool IsNegative =
false;
18184 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18193 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18194 }
else if (VT == MVT::f16) {
18203 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18220 DAGCombinerInfo &DCI)
const {
18221 SelectionDAG &DAG = DCI.DAG;
18222 EVT VT =
N->getValueType(0);
18226 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18227 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18242 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18247 const ConstantFPSDNode *FalseNode =
18257 if (ScalarVT == MVT::f32 &&
18263 if (TrueNodeExpVal == INT_MIN)
18266 if (FalseNodeExpVal == INT_MIN)
18286 DAGCombinerInfo &DCI)
const {
18287 SelectionDAG &DAG = DCI.DAG;
18288 EVT VT =
N->getValueType(0);
18291 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18319 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18320 FMA->getFlags().hasApproximateFuncs();
18321 if (!AllowInaccuracy) {
18324 if (Subtarget->dot2UnconditionalFlush()) {
18338 (
N->getFlags().hasAllowContract() &&
18339 FMA->getFlags().hasAllowContract())) {
18373 if (Vec1 == Vec2 || Vec3 == Vec4)
18379 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18380 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18423 EVT VT =
LHS.getValueType();
18424 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18456 if (CC ==
ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18460 if (CC ==
ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18464 if (CC ==
ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18468 if (CC ==
ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18471 const std::optional<bool> KnownEq =
18500 if (CC ==
ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18504 if (CC ==
ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18512 const std::optional<bool> KnownUge =
18537 if (CC ==
ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18551 if (CC ==
ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18554 const std::optional<bool> KnownUle =
18577 DAGCombinerInfo &DCI)
const {
18578 SelectionDAG &DAG = DCI.DAG;
18583 EVT VT =
LHS.getValueType();
18612 return LHS.getOperand(0);
18626 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18627 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18632 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18635 return LHS.getOperand(0);
18656 if (VT == MVT::i64) {
18668 const std::optional<bool> KnownEq =
18676 const std::optional<bool> KnownEq =
18687 const std::optional<bool> KnownUge =
18707 const std::optional<bool> KnownUle =
18758 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18763 {Op0Hi, Op1Hi, CarryInHi});
18773 DCI.CombineTo(
LHS.getNode(), Result);
18777 if (VT != MVT::f32 && VT != MVT::f64 &&
18778 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18793 const unsigned IsInfMask =
18795 const unsigned IsFiniteMask =
18800 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
18805 if (VT == MVT::f64) {
18816SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
18817 DAGCombinerInfo &DCI)
const {
18818 SelectionDAG &DAG = DCI.DAG;
18820 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18839 unsigned ShiftOffset = 8 *
Offset;
18841 ShiftOffset -=
C->getZExtValue();
18843 ShiftOffset +=
C->getZExtValue();
18845 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18846 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18847 MVT::f32, Shifted);
18858 DCI.AddToWorklist(
N);
18865 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
18871 DAGCombinerInfo &DCI)
const {
18880 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
18881 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
18886 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
18888 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
18892 DAGCombinerInfo &DCI)
const {
18913 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
18914 bool isInteger =
LHS.getValueType().isInteger();
18917 if (!isFloatingPoint && !isInteger)
18922 bool isNonEquality =
18924 if (!isEquality && !isNonEquality)
18941 if (isFloatingPoint) {
18943 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
18946 const std::optional<int64_t> Val =
18955 if (!(isEquality && TrueVal == ConstVal) &&
18956 !(isNonEquality && FalseVal == ConstVal))
18960 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
18961 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
18968 SelectLHS, SelectRHS);
18973 switch (
N->getOpcode()) {
18994 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19004 switch (
N->getOpcode()) {
19006 return performAddCombine(
N, DCI);
19008 return performPtrAddCombine(
N, DCI);
19010 return performSubCombine(
N, DCI);
19012 return performFAddCombine(
N, DCI);
19014 return performFSubCombine(
N, DCI);
19016 return performFDivCombine(
N, DCI);
19018 return performFMulCombine(
N, DCI);
19020 return performSetCCCombine(
N, DCI);
19022 if (
auto Res = performSelectCombine(
N, DCI))
19037 case AMDGPUISD::FMIN_LEGACY:
19038 case AMDGPUISD::FMAX_LEGACY:
19039 return performMinMaxCombine(
N, DCI);
19041 return performFMACombine(
N, DCI);
19043 return performAndCombine(
N, DCI);
19045 return performOrCombine(
N, DCI);
19048 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19049 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19055 return performXorCombine(
N, DCI);
19058 return performZeroOrAnyExtendCombine(
N, DCI);
19060 return performSignExtendInRegCombine(
N, DCI);
19061 case AMDGPUISD::FP_CLASS:
19062 return performClassCombine(
N, DCI);
19064 return performFCanonicalizeCombine(
N, DCI);
19065 case AMDGPUISD::RCP:
19066 return performRcpCombine(
N, DCI);
19068 case AMDGPUISD::FRACT:
19069 case AMDGPUISD::RSQ:
19070 case AMDGPUISD::RCP_LEGACY:
19071 case AMDGPUISD::RCP_IFLAG:
19072 case AMDGPUISD::RSQ_CLAMP: {
19081 return performUCharToFloatCombine(
N, DCI);
19083 return performFCopySignCombine(
N, DCI);
19084 case AMDGPUISD::CVT_F32_UBYTE0:
19085 case AMDGPUISD::CVT_F32_UBYTE1:
19086 case AMDGPUISD::CVT_F32_UBYTE2:
19087 case AMDGPUISD::CVT_F32_UBYTE3:
19088 return performCvtF32UByteNCombine(
N, DCI);
19089 case AMDGPUISD::FMED3:
19090 return performFMed3Combine(
N, DCI);
19091 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19092 return performCvtPkRTZCombine(
N, DCI);
19093 case AMDGPUISD::CLAMP:
19094 return performClampCombine(
N, DCI);
19097 EVT VT =
N->getValueType(0);
19100 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19103 EVT EltVT = Src.getValueType();
19104 if (EltVT != MVT::i16)
19114 return performExtractVectorEltCombine(
N, DCI);
19116 return performInsertVectorEltCombine(
N, DCI);
19118 return performFPRoundCombine(
N, DCI);
19127 return performMemSDNodeCombine(MemNode, DCI);
19158 unsigned Opcode =
Node->getMachineOpcode();
19161 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19162 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19165 SDNode *
Users[5] = {
nullptr};
19167 unsigned DmaskIdx =
19168 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19169 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19170 unsigned NewDmask = 0;
19171 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19172 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19173 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19174 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19175 unsigned TFCLane = 0;
19176 bool HasChain =
Node->getNumValues() > 1;
19178 if (OldDmask == 0) {
19186 TFCLane = OldBitsSet;
19190 for (SDUse &Use :
Node->uses()) {
19193 if (
Use.getResNo() != 0)
19196 SDNode *
User =
Use.getUser();
19199 if (!
User->isMachineOpcode() ||
19200 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19212 if (UsesTFC && Lane == TFCLane) {
19217 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19219 Dmask &= ~(1 << Comp);
19227 NewDmask |= 1 << Comp;
19232 bool NoChannels = !NewDmask;
19239 if (OldBitsSet == 1)
19245 if (NewDmask == OldDmask)
19254 unsigned NewChannels = BitsSet + UsesTFC;
19258 assert(NewOpcode != -1 &&
19259 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19260 "failed to find equivalent MIMG op");
19268 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19270 MVT ResultVT = NewChannels == 1
19273 : NewChannels == 5 ? 8
19275 SDVTList NewVTList =
19278 MachineSDNode *NewNode =
19287 if (NewChannels == 1) {
19297 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19302 if (i || !NoChannels)
19307 if (NewUser != User) {
19317 Idx = AMDGPU::sub1;
19320 Idx = AMDGPU::sub2;
19323 Idx = AMDGPU::sub3;
19326 Idx = AMDGPU::sub4;
19337 Op =
Op.getOperand(0);
19362 Node->getOperand(0), SL, VReg, SrcVal,
19368 return ToResultReg.
getNode();
19373 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19375 Ops.push_back(
Node->getOperand(i));
19381 Node->getOperand(i).getValueType(),
19382 Node->getOperand(i)),
19394 unsigned Opcode =
Node->getMachineOpcode();
19396 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19397 !
TII->isGather4(Opcode) &&
19399 return adjustWritemask(
Node, DAG);
19402 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19408 case AMDGPU::V_DIV_SCALE_F32_e64:
19409 case AMDGPU::V_DIV_SCALE_F64_e64: {
19419 (Src0 == Src1 || Src0 == Src2))
19475 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19476 unsigned InitIdx = 0;
19478 if (
TII->isImage(
MI)) {
19486 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19487 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19488 unsigned D16Val = D16 ? D16->getImm() : 0;
19490 if (!TFEVal && !LWEVal)
19501 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19503 unsigned dmask = MO_Dmask->
getImm();
19508 bool Packed = !Subtarget->hasUnpackedD16VMem();
19510 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19517 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19518 if (DstSize < InitIdx)
19522 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
19531 unsigned NewDst = 0;
19536 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19537 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19540 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19561 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
19573 if (
TII->isVOP3(
MI.getOpcode())) {
19575 TII->legalizeOperandsVOP3(MRI,
MI);
19577 if (
TII->isMAI(
MI)) {
19582 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19583 AMDGPU::OpName::scale_src0);
19584 if (Src0Idx != -1) {
19585 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19586 AMDGPU::OpName::scale_src1);
19587 if (
TII->usesConstantBus(MRI,
MI, Src0Idx) &&
19588 TII->usesConstantBus(MRI,
MI, Src1Idx))
19589 TII->legalizeOpWithMove(
MI, Src1Idx);
19596 if (
TII->isImage(
MI))
19597 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
19669std::pair<unsigned, const TargetRegisterClass *>
19676 if (Constraint.
size() == 1) {
19680 if (VT == MVT::Other)
19683 switch (Constraint[0]) {
19690 RC = &AMDGPU::SReg_32RegClass;
19693 RC = &AMDGPU::SGPR_64RegClass;
19698 return std::pair(0U,
nullptr);
19705 return std::pair(0U,
nullptr);
19707 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19708 : &AMDGPU::VGPR_32_Lo256RegClass;
19711 RC = Subtarget->has1024AddressableVGPRs()
19712 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
19715 return std::pair(0U,
nullptr);
19720 if (!Subtarget->hasMAIInsts())
19724 return std::pair(0U,
nullptr);
19726 RC = &AMDGPU::AGPR_32RegClass;
19731 return std::pair(0U,
nullptr);
19736 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
19740 RC = &AMDGPU::AV_32RegClass;
19743 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
19745 return std::pair(0U,
nullptr);
19754 return std::pair(0U, RC);
19757 if (Kind !=
'\0') {
19759 RC = &AMDGPU::VGPR_32_Lo256RegClass;
19760 }
else if (Kind ==
's') {
19761 RC = &AMDGPU::SGPR_32RegClass;
19762 }
else if (Kind ==
'a') {
19763 RC = &AMDGPU::AGPR_32RegClass;
19769 return std::pair(0U,
nullptr);
19775 return std::pair(0U,
nullptr);
19779 RC =
TRI->getVGPRClassForBitWidth(Width);
19781 RC =
TRI->getSGPRClassForBitWidth(Width);
19783 RC =
TRI->getAGPRClassForBitWidth(Width);
19785 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
19790 return std::pair(0U,
nullptr);
19792 return std::pair(Reg, RC);
19801 return std::pair(0U,
nullptr);
19802 if (RC && Idx < RC->getNumRegs())
19804 return std::pair(0U,
nullptr);
19810 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
19816 if (Constraint.
size() == 1) {
19817 switch (Constraint[0]) {
19827 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
19835 if (Constraint.
size() == 1) {
19836 switch (Constraint[0]) {
19844 }
else if (Constraint.
size() == 2) {
19845 if (Constraint ==
"VA")
19863 std::vector<SDValue> &
Ops,
19878 unsigned Size =
Op.getScalarValueSizeInBits();
19882 if (
Size == 16 && !Subtarget->has16BitInsts())
19886 Val =
C->getSExtValue();
19890 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
19894 if (
Size != 16 ||
Op.getNumOperands() != 2)
19896 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
19899 Val =
C->getSExtValue();
19903 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
19913 if (Constraint.
size() == 1) {
19914 switch (Constraint[0]) {
19929 }
else if (Constraint.
size() == 2) {
19930 if (Constraint ==
"DA") {
19931 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
19932 int64_t LoBits =
static_cast<int32_t
>(Val);
19936 if (Constraint ==
"DB") {
19944 unsigned MaxSize)
const {
19945 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
19946 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
19948 MVT VT =
Op.getSimpleValueType();
19973 switch (UnalignedClassID) {
19974 case AMDGPU::VReg_64RegClassID:
19975 return AMDGPU::VReg_64_Align2RegClassID;
19976 case AMDGPU::VReg_96RegClassID:
19977 return AMDGPU::VReg_96_Align2RegClassID;
19978 case AMDGPU::VReg_128RegClassID:
19979 return AMDGPU::VReg_128_Align2RegClassID;
19980 case AMDGPU::VReg_160RegClassID:
19981 return AMDGPU::VReg_160_Align2RegClassID;
19982 case AMDGPU::VReg_192RegClassID:
19983 return AMDGPU::VReg_192_Align2RegClassID;
19984 case AMDGPU::VReg_224RegClassID:
19985 return AMDGPU::VReg_224_Align2RegClassID;
19986 case AMDGPU::VReg_256RegClassID:
19987 return AMDGPU::VReg_256_Align2RegClassID;
19988 case AMDGPU::VReg_288RegClassID:
19989 return AMDGPU::VReg_288_Align2RegClassID;
19990 case AMDGPU::VReg_320RegClassID:
19991 return AMDGPU::VReg_320_Align2RegClassID;
19992 case AMDGPU::VReg_352RegClassID:
19993 return AMDGPU::VReg_352_Align2RegClassID;
19994 case AMDGPU::VReg_384RegClassID:
19995 return AMDGPU::VReg_384_Align2RegClassID;
19996 case AMDGPU::VReg_512RegClassID:
19997 return AMDGPU::VReg_512_Align2RegClassID;
19998 case AMDGPU::VReg_1024RegClassID:
19999 return AMDGPU::VReg_1024_Align2RegClassID;
20000 case AMDGPU::AReg_64RegClassID:
20001 return AMDGPU::AReg_64_Align2RegClassID;
20002 case AMDGPU::AReg_96RegClassID:
20003 return AMDGPU::AReg_96_Align2RegClassID;
20004 case AMDGPU::AReg_128RegClassID:
20005 return AMDGPU::AReg_128_Align2RegClassID;
20006 case AMDGPU::AReg_160RegClassID:
20007 return AMDGPU::AReg_160_Align2RegClassID;
20008 case AMDGPU::AReg_192RegClassID:
20009 return AMDGPU::AReg_192_Align2RegClassID;
20010 case AMDGPU::AReg_256RegClassID:
20011 return AMDGPU::AReg_256_Align2RegClassID;
20012 case AMDGPU::AReg_512RegClassID:
20013 return AMDGPU::AReg_512_Align2RegClassID;
20014 case AMDGPU::AReg_1024RegClassID:
20015 return AMDGPU::AReg_1024_Align2RegClassID;
20031 if (Info->isEntryFunction()) {
20038 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20040 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20041 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20042 &AMDGPU::SGPR_64RegClass);
20043 Info->setSGPRForEXECCopy(SReg);
20045 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20046 Info->getStackPtrOffsetReg()));
20047 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20048 MRI.
replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20052 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20053 MRI.
replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20055 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20058 Info->limitOccupancy(MF);
20060 if (ST.isWave32() && !MF.
empty()) {
20061 for (
auto &
MBB : MF) {
20062 for (
auto &
MI :
MBB) {
20063 TII->fixImplicitOperands(
MI);
20073 if (ST.needsAlignedVGPRs()) {
20080 if (NewClassID != -1)
20090 const APInt &DemandedElts,
20092 unsigned Depth)
const {
20094 unsigned Opc =
Op.getOpcode();
20097 unsigned IID =
Op.getConstantOperandVal(0);
20099 case Intrinsic::amdgcn_mbcnt_lo:
20100 case Intrinsic::amdgcn_mbcnt_hi: {
20105 Known.Zero.setBitsFrom(
20106 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20132 unsigned MaxValue =
20139 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20143 unsigned Src1Cst = 0;
20144 if (Src1.
isImm()) {
20145 Src1Cst = Src1.
getImm();
20146 }
else if (Src1.
isReg()) {
20150 Src1Cst = Cst->Value.getZExtValue();
20161 if (Width >= BFEWidth)
20178 unsigned Depth)
const {
20181 switch (
MI->getOpcode()) {
20182 case AMDGPU::S_BFE_I32:
20185 case AMDGPU::S_BFE_U32:
20188 case AMDGPU::S_BFE_I64:
20191 case AMDGPU::S_BFE_U64:
20194 case AMDGPU::G_INTRINSIC:
20195 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20198 case Intrinsic::amdgcn_workitem_id_x:
20201 case Intrinsic::amdgcn_workitem_id_y:
20204 case Intrinsic::amdgcn_workitem_id_z:
20207 case Intrinsic::amdgcn_mbcnt_lo:
20208 case Intrinsic::amdgcn_mbcnt_hi: {
20211 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20220 case Intrinsic::amdgcn_groupstaticsize: {
20224 Known.Zero.setHighBits(
20231 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20232 Known.Zero.setHighBits(24);
20234 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20235 Known.Zero.setHighBits(16);
20237 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20240 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20242 case AMDGPU::G_AMDGPU_SMED3:
20243 case AMDGPU::G_AMDGPU_UMED3: {
20244 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20271 unsigned Depth)
const {
20278 AttributeList Attrs =
20280 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20298 if (Header->getAlignment() != PrefAlign)
20299 return Header->getAlignment();
20300 if (needsFetchWindowAlignment(*Header))
20321 if (Header->getAlignment() != PrefAlign)
20322 return Header->getAlignment();
20324 unsigned LoopSize = 0;
20329 LoopSize +=
MBB->getAlignment().value() / 2;
20332 LoopSize +=
TII->getInstSizeInBytes(
MI);
20333 if (LoopSize > 192)
20338 if (LoopSize <= 64)
20341 if (LoopSize <= 128)
20342 return CacheLineAlign;
20348 auto I = Exit->getFirstNonDebugInstr();
20349 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20350 return CacheLineAlign;
20359 if (PreTerm == Pre->
begin() ||
20360 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20364 auto ExitHead = Exit->getFirstNonDebugInstr();
20365 if (ExitHead == Exit->end() ||
20366 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20371 return CacheLineAlign;
20379 if (needsFetchWindowAlignment(*
MBB))
20384bool SITargetLowering::needsFetchWindowAlignment(
20386 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20390 if (
MI.isMetaInstruction())
20393 return TII->getInstSizeInBytes(
MI) > 4;
20403 N =
N->getOperand(0).getNode();
20413 switch (
N->getOpcode()) {
20421 if (Reg.isPhysical() || MRI.
isLiveIn(Reg))
20422 return !
TRI->isSGPRReg(MRI, Reg);
20428 return !
TRI->isSGPRReg(MRI, Reg);
20432 unsigned AS = L->getAddressSpace();
20442 case AMDGPUISD::ATOMIC_CMP_SWAP:
20443 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20444 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20445 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20446 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20447 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20448 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20449 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20450 case AMDGPUISD::BUFFER_ATOMIC_AND:
20451 case AMDGPUISD::BUFFER_ATOMIC_OR:
20452 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20453 case AMDGPUISD::BUFFER_ATOMIC_INC:
20454 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20455 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20456 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20457 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20458 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20464 return A->readMem() &&
A->writeMem();
20485 switch (Ty.getScalarSizeInBits()) {
20497 const APInt &DemandedElts,
20500 unsigned Depth)
const {
20501 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
20505 if (Info->getMode().DX10Clamp)
20517 if (RMW->
hasMetadata(
"amdgpu.ignore.denormal.mode"))
20537 <<
"Hardware instruction generated for atomic "
20539 <<
" operation at memory scope " << MemScope;
20544 Type *EltTy = VT->getElementType();
20545 return VT->getNumElements() == 2 &&
20565 unsigned BW =
IT->getBitWidth();
20566 return BW == 32 || BW == 64;
20580 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
20581 return BW == 32 || BW == 64;
20584 if (Ty->isFloatTy() || Ty->isDoubleTy())
20588 return VT->getNumElements() == 2 &&
20589 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20599 bool HasSystemScope) {
20606 if (HasSystemScope) {
20607 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20610 if (Subtarget.hasEmulatedSystemScopeAtomics())
20612 }
else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20615 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory");
20628 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
20636 return STI.hasGloballyAddressableScratch()
20654 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
20667 bool HasSystemScope =
20701 if (!
IT ||
IT->getBitWidth() != 32)
20707 if (Subtarget->hasEmulatedSystemScopeAtomics())
20723 if (!HasSystemScope &&
20724 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
20736 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
20744 ConstVal && ConstVal->isNullValue())
20782 if (Ty->isFloatTy()) {
20787 if (Ty->isDoubleTy()) {
20808 if (Ty->isFloatTy() &&
20809 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
20822 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
20826 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
20830 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
20835 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
20840 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
20844 if (Ty->isFloatTy()) {
20847 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
20850 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
20855 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
20863 if (Subtarget->hasFlatAtomicFaddF32Inst())
20872 if (Subtarget->hasLDSFPAtomicAddF32()) {
20873 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
20875 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
20903 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
20905 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
20909 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
20911 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
20965 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
20966 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
20967 : &AMDGPU::SReg_32RegClass;
20968 if (!
TRI->isSGPRClass(RC) && !isDivergent)
20969 return TRI->getEquivalentSGPRClass(RC);
20970 if (
TRI->isSGPRClass(RC) && isDivergent) {
20971 if (Subtarget->hasGFX90AInsts())
20972 return TRI->getEquivalentAVClass(RC);
20973 return TRI->getEquivalentVGPRClass(RC);
20986 unsigned WaveSize) {
20991 if (!
IT ||
IT->getBitWidth() != WaveSize)
20996 if (!Visited.
insert(V).second)
20998 bool Result =
false;
20999 for (
const auto *U : V->users()) {
21001 if (V == U->getOperand(1)) {
21006 case Intrinsic::amdgcn_if_break:
21007 case Intrinsic::amdgcn_if:
21008 case Intrinsic::amdgcn_else:
21013 if (V == U->getOperand(0)) {
21018 case Intrinsic::amdgcn_end_cf:
21019 case Intrinsic::amdgcn_loop:
21025 Result =
hasCFUser(U, Visited, WaveSize);
21034 const Value *V)
const {
21036 if (CI->isInlineAsm()) {
21045 for (
auto &TC : TargetConstraints) {
21059 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21094 if (
I.getMetadata(
"amdgpu.noclobber"))
21096 if (
I.getMetadata(
"amdgpu.last.use"))
21160 Alignment = RMW->getAlign();
21173 bool FullFlatEmulation =
21175 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21176 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21177 RMW->getType()->isDoubleTy()));
21180 bool ReturnValueIsUsed = !AI->
use_empty();
21189 if (FullFlatEmulation) {
21200 std::prev(BB->
end())->eraseFromParent();
21201 Builder.SetInsertPoint(BB);
21203 Value *LoadedShared =
nullptr;
21204 if (FullFlatEmulation) {
21205 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21206 {Addr},
nullptr,
"is.shared");
21207 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21208 Builder.SetInsertPoint(SharedBB);
21209 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21215 LoadedShared = Clone;
21217 Builder.CreateBr(PhiBB);
21218 Builder.SetInsertPoint(CheckPrivateBB);
21221 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21222 {Addr},
nullptr,
"is.private");
21223 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21225 Builder.SetInsertPoint(PrivateBB);
21227 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21230 Value *LoadedPrivate;
21232 LoadedPrivate = Builder.CreateAlignedLoad(
21233 RMW->getType(), CastToPrivate, RMW->getAlign(),
"loaded.private");
21236 LoadedPrivate, RMW->getValOperand());
21238 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign());
21240 auto [ResultLoad, Equal] =
21246 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21249 Builder.CreateBr(PhiBB);
21251 Builder.SetInsertPoint(GlobalBB);
21255 if (FullFlatEmulation) {
21256 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21265 if (!FullFlatEmulation) {
21270 MDNode *RangeNotPrivate =
21273 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21277 Builder.CreateBr(PhiBB);
21279 Builder.SetInsertPoint(PhiBB);
21281 if (ReturnValueIsUsed) {
21284 if (FullFlatEmulation)
21285 Loaded->addIncoming(LoadedShared, SharedBB);
21286 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21287 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21288 Loaded->takeName(AI);
21291 Builder.CreateBr(ExitBB);
21295 unsigned PtrOpIdx) {
21296 Value *PtrOp =
I->getOperand(PtrOpIdx);
21303 I->setOperand(PtrOpIdx, ASCast);
21315 ConstVal && ConstVal->isNullValue()) {
21345 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21353 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21368 LoadInst *LI = Builder.CreateAlignedLoad(
static bool isMul(MachineInstr *MI)
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
iv Induction Variable Users
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
#define FP_DENORM_FLUSH_NONE
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static SDValue lowerICMPIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask=~0u, ArgDescriptor Arg=ArgDescriptor())
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static SDValue lowerFCMPIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static bool atomicIgnoresDenormalModeOrFPModeIsFTZ(const AtomicRMWInst *RMW)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void 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)
void setUsesDynamicLDS(bool DynLDS)
bool isBottomOfStack() const
uint32_t getLDSSize() const
static std::optional< uint32_t > getLDSAbsoluteAddress(const GlobalValue &GV)
bool isEntryFunction() const
unsigned getWavefrontSize() const
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
static bool EnableObjectLinking
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned AndSaveExecOpc
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
LLVM_READONLY int getExactLog2Abs() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
const Function * getParent() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
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,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
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.
Value * getPointerOperand()
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)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
std::optional< ISelOp > Src
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static bool isFPPredicate(Predicate P)
static bool isIntPredicate(Predicate P)
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Argument * getArg(unsigned i) const
const SIInstrInfo * getInstrInfo() const override
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool hasKernargSegmentPtr() const
bool hasDispatchID() const
bool hasPrivateSegmentBuffer() const
unsigned getNumFreeUserSGPRs()
bool hasImplicitBufferPtr() const
bool hasPrivateSegmentSize() const
bool hasDispatchPtr() const
bool hasFlatScratchInit() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
int64_t getOffset() const
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes 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 void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
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.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool isWholeWaveFunction() const
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
unsigned getBytesInStackArgArea() const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
void CollectTargetIntrinsicOperands(const CallInst &I, SmallVectorImpl< SDValue > &Ops, SelectionDAG &DAG) const override
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
LoadInst * lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *AI) const override
On some platforms, an AtomicRMW that never actually modifies the value (such as fetch_add of 0) can b...
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void allocateSpecialInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments at the end of allocated user arguments.
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS)
Return an AddrSpaceCastSDNode.
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 getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
OSType getOS() const
Get the parsed operating system type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM_ABI void set(Value *Val)
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
LLVM_READONLY int32_t getVOPe64(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ TowardZeroF32_TowardNegativeF64
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI 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.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred)
getICmpCondCode - Return the ISD condition code corresponding to the given LLVM IR integer condition ...
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.
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool isReleaseOrStronger(AtomicOrdering AO)
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.
LLVM_ABI ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred)
getFCmpCondCode - Return the ISD condition code corresponding to the given LLVM IR floating-point con...
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...
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::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
ArgDescriptor WorkItemIDZ
ArgDescriptor WorkItemIDY
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
ArgDescriptor WorkItemIDX
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
unsigned AtomicNoRetBaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static ArgDescriptor createStack(unsigned Offset, unsigned Mask=~0u)
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SDValue ConvergenceControlToken
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalize() const