36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
475 if (IsLoad &&
RegSize == 16 && !ST.d16PreservesUnusedBits())
491 if (!ST.hasDwordx3LoadStores())
504 if (AlignBits < MemSize) {
507 Align(AlignBits / 8)))
537 const unsigned Size = Ty.getSizeInBits();
538 if (Ty.isPointerVector())
548 unsigned EltSize = Ty.getScalarSizeInBits();
549 return EltSize != 32 && EltSize != 64;
563 const unsigned Size = Ty.getSizeInBits();
564 if (
Size != MemSizeInBits)
565 return Size <= 32 && Ty.isVector();
571 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
580 uint64_t AlignInBits,
unsigned AddrSpace,
590 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
601 if (AlignInBits < RoundedSize)
608 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
620 Query.
Types[1].getAddressSpace(), Opcode);
640 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
643 Register VectorReg =
MRI.createGenericVirtualRegister(VectorTy);
644 std::array<Register, 4> VectorElems;
645 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
646 for (
unsigned I = 0;
I < NumParts; ++
I)
648 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
649 B.buildMergeValues(MO, VectorElems);
653 Register BitcastReg =
MRI.createGenericVirtualRegister(VectorTy);
654 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
655 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
656 B.buildIntToPtr(MO, Scalar);
676 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
678 for (
unsigned I = 0;
I < NumParts; ++
I)
680 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
682 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
683 return B.buildBitcast(VectorTy, Scalar).getReg(0);
711 const LLT BufferStridedPtr =
714 const LLT CodePtr = FlatPtr;
716 const std::initializer_list<LLT> AddrSpaces64 = {
717 GlobalPtr, ConstantPtr, FlatPtr
720 const std::initializer_list<LLT> AddrSpaces32 = {
721 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
724 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
726 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
727 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
728 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
757 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
759 if (ST.hasAnyPackedU64Ops()) {
762 .clampMaxNumElementsStrict(0,
S16, 2)
768 }
else if (ST.hasScalarAddSub64()) {
771 .clampMaxNumElementsStrict(0,
S16, 2)
779 .clampMaxNumElementsStrict(0,
S16, 2)
786 if (ST.hasScalarSMulU64()) {
789 .clampMaxNumElementsStrict(0,
S16, 2)
797 .clampMaxNumElementsStrict(0,
S16, 2)
807 .minScalarOrElt(0,
S16)
812 }
else if (ST.has16BitInsts()) {
846 .widenScalarToNextMultipleOf(0, 32)
856 if (ST.hasMad64_32())
861 if (ST.hasIntClamp()) {
884 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
894 if (ST.hasVOP3PInsts()) {
896 .clampMaxNumElements(0,
S8, 2)
917 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
933 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
976 auto &FCanonicalizeActions =
978 auto &StrictFPOpActions =
985 if (ST.has16BitInsts()) {
986 if (ST.hasVOP3PInsts()) {
988 FCanonicalizeActions.legalFor({
F16,
V2F16});
989 StrictFPOpActions.legalFor({
F16,
V2F16});
991 FPOpActions.legalFor({
F16});
992 FCanonicalizeActions.legalFor({
F16});
993 StrictFPOpActions.legalFor({
F16});
996 TrigActions.customFor({
F16});
997 FDIVActions.customFor({
F16});
1000 if (ST.hasBF16PackedInsts()) {
1004 .clampMaxNumElementsStrict(0,
BF16, 2);
1007 .clampMaxNumElementsStrict(0,
BF16, 2);
1010 .clampMaxNumElementsStrict(0,
BF16, 2);
1016 if (ST.hasAnyPackedFP32Ops()) {
1017 FPOpActions.legalFor({
V2F32});
1018 FCanonicalizeActions.legalFor({
V2F32});
1019 StrictFPOpActions.legalFor({
V2F32});
1020 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1021 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1022 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1025 if (ST.hasAnyPackedFP64Ops()) {
1026 FPOpActions.legalFor({
V2F64});
1027 FCanonicalizeActions.legalFor({
V2F64});
1028 StrictFPOpActions.legalFor({
V2F64});
1029 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1030 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1031 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1034 auto &MinNumMaxNumIeee =
1037 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1039 MinNumMaxNumIeee.
legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F32, F64});
1040 MinNumMaxNum.
legalFor(ST.hasIEEEMinimumMaximumInsts(), {F32, F64})
1043 if (ST.has16BitInsts()) {
1044 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F16});
1045 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {F16})
1050 if (ST.hasVOP3PInsts()) {
1051 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1054 .clampMaxNumElements(0,
F16, 2);
1055 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1059 .clampMaxNumElements(0,
F16, 2);
1063 if (ST.hasAnyPackedFP64Ops()) {
1064 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F64})
1068 .clampMaxNumElements(0,
F64, 2);
1072 if (ST.hasBF16PackedInsts()) {
1073 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1074 .clampMaxNumElementsStrict(0,
BF16, 2);
1076 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1079 .clampMaxNumElementsStrict(0,
BF16, 2);
1087 if (!ST.has16BitInsts()) {
1088 MinNumMaxNumIeee.minScalar(0,
F32);
1089 MinNumMaxNum.minScalar(0,
F32);
1092 if (ST.hasVOP3PInsts()) {
1093 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1094 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1095 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1103 if (!ST.has16BitInsts()) {
1114 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1117 if (ST.hasAnyPackedFP32Ops())
1121 if (ST.has16BitInsts()) {
1124 .legalFor(ST.hasBF16TransInsts(), {BF16})
1134 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1156 if (ST.hasFractBug()) {
1170 .legalFor({{
F32, I32}, {
F64, I32}})
1190 if (ST.hasCvtPkF16F32Inst()) {
1192 .clampMaxNumElements(0,
F16, 2);
1205 if (ST.has16BitInsts()) {
1219 if (ST.hasBF16PackedInsts()) {
1222 .clampMaxNumElementsStrict(0,
BF16, 2);
1227 if (ST.hasAnyPackedFP32Ops())
1235 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1236 FMad.customFor({
F32,
F16});
1237 else if (ST.hasMadMacF32Insts())
1238 FMad.customFor({
F32});
1239 else if (ST.hasMadF16())
1240 FMad.customFor({
F16});
1245 if (ST.has16BitInsts()) {
1248 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1256 .clampMaxNumElements(0,
S16, 2)
1272 .legalFor({{
F32, I32}, {
F64, I32}})
1276 if (ST.has16BitInsts())
1284 .legalFor({{I32,
F32}, {I32,
F64}})
1285 .customFor({{I64,
F32}, {I64,
F64}})
1288 .widenScalarFor({{I16,
BF16}, {I32,
BF16}, {I64,
BF16}},
1290 if (ST.has16BitInsts())
1299 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1300 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1301 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1305 if (
ST.has16BitInsts())
1308 if (
ST.hasVCvtPkIU16F32())
1318 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1319 .clampScalar(0, I16, I64)
1323 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1329 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1333 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1334 .clampScalar(0, I16, I64)
1338 auto &RoundingActions = getActionDefinitionsBuilder(
1339 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1340 if (
ST.has16BitInsts())
1348 if (!
ST.has16BitInsts())
1351 getActionDefinitionsBuilder(G_PTR_ADD)
1357 getActionDefinitionsBuilder(G_PTRMASK)
1359 .scalarSameSizeAs(1, 0)
1363 getActionDefinitionsBuilder(G_ICMP)
1375 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1376 .legalForCartesianProduct(
1377 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1378 if (
ST.has16BitInsts()) {
1379 CmpBuilder.legalFor({{
S1,
S16}});
1388 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1391 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1392 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1394 if (
ST.hasSALUFloatInsts())
1395 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1398 .widenScalarToNextPow2(1)
1402 getActionDefinitionsBuilder(G_FPOW)
1404 .clampScalar(0,
F32,
F32)
1407 getActionDefinitionsBuilder(G_FPOWI)
1408 .clampScalar(0,
F32,
F32)
1412 getActionDefinitionsBuilder(G_FLOG2)
1413 .legalFor(
ST.has16BitInsts(), {F16})
1414 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1420 getActionDefinitionsBuilder(G_FEXP2)
1421 .legalFor(
ST.has16BitInsts(), {F16})
1422 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1428 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1432 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1437 getActionDefinitionsBuilder(G_CTPOP)
1439 .clampScalar(0,
S32,
S32)
1440 .widenScalarToNextPow2(1, 32)
1441 .clampScalar(1,
S32,
S64)
1443 .widenScalarToNextPow2(0, 32);
1446 if (
ST.has16BitInsts())
1447 getActionDefinitionsBuilder(G_IS_FPCLASS)
1448 .legalForCartesianProduct({
I1}, FPTypes16)
1449 .widenScalarToNextPow2(1)
1453 getActionDefinitionsBuilder(G_IS_FPCLASS)
1454 .legalForCartesianProduct({
I1}, FPTypesBase)
1455 .lowerFor({
I1,
F16})
1456 .widenScalarToNextPow2(1)
1463 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1465 .clampScalar(0,
S32,
S32)
1466 .clampScalar(1,
S32,
S64)
1467 .widenScalarToNextPow2(0, 32)
1468 .widenScalarToNextPow2(1, 32)
1472 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1475 .clampScalar(0,
S32,
S32)
1476 .clampScalar(1,
S32,
S64)
1478 .widenScalarToNextPow2(0, 32)
1479 .widenScalarToNextPow2(1, 32);
1481 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1483 .clampScalar(0,
S32,
S32)
1484 .clampScalar(1,
S32,
S64)
1486 .widenScalarToNextPow2(0, 32)
1487 .widenScalarToNextPow2(1, 32);
1489 getActionDefinitionsBuilder(G_CTLS)
1492 .clampScalar(0,
S32,
S32)
1493 .clampScalar(1,
S32,
S32);
1497 getActionDefinitionsBuilder(G_BITREVERSE)
1499 .clampScalar(0,
S32,
S64)
1501 .widenScalarToNextPow2(0);
1503 if (
ST.has16BitInsts()) {
1504 getActionDefinitionsBuilder(G_BSWAP)
1506 .clampMaxNumElementsStrict(0,
S16, 2)
1509 .widenScalarToNextPow2(0)
1510 .clampScalar(0,
S16,
S32)
1513 if (
ST.hasVOP3PInsts()) {
1514 getActionDefinitionsBuilder(G_ABS)
1516 .clampMaxNumElements(0,
S16, 2)
1518 .widenScalarToNextPow2(0)
1521 if (
ST.useMinMaxI64Insts()) {
1522 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1524 .clampMaxNumElements(0,
S16, 2)
1526 .widenScalarToNextPow2(0)
1530 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1532 .clampMaxNumElements(0,
S16, 2)
1534 .widenScalarToNextPow2(0)
1539 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1541 .widenScalarToNextPow2(0)
1548 getActionDefinitionsBuilder(G_BSWAP)
1553 .widenScalarToNextPow2(0)
1558 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1561 .widenScalarToNextPow2(0)
1566 getActionDefinitionsBuilder(G_INTTOPTR)
1568 .legalForCartesianProduct(AddrSpaces64, {
S64})
1569 .legalForCartesianProduct(AddrSpaces32, {
S32})
1582 getActionDefinitionsBuilder(G_PTRTOINT)
1584 .legalForCartesianProduct(AddrSpaces64, {
S64})
1585 .legalForCartesianProduct(AddrSpaces32, {
S32})
1598 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1602 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1603 bool IsLoad) ->
bool {
1607 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1620 !
ST.hasUsableDSOffset() && Query.
MMODescrs[0].AlignInBits == 32)
1625 unsigned NumRegs = (MemSize + 31) / 32;
1627 if (!
ST.hasDwordx3LoadStores())
1638 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1639 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1640 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1641 unsigned LocalAlign64 =
ST.hasUsableDSOffset() ? 32 : 64;
1647 for (
unsigned Op : {G_LOAD, G_STORE}) {
1648 const bool IsStore =
Op == G_STORE;
1650 auto &Actions = getActionDefinitionsBuilder(
Op);
1653 Actions.legalForTypesWithMemDesc(
1654 {{
S32, GlobalPtr,
S32, GlobalAlign32},
1657 {
S64, GlobalPtr,
S64, GlobalAlign32},
1660 {
S32, GlobalPtr,
S8, GlobalAlign8},
1661 {
S32, GlobalPtr,
S16, GlobalAlign16},
1663 {
S32, LocalPtr,
S32, 32},
1664 {
S64, LocalPtr,
S64, LocalAlign64},
1666 {
S32, LocalPtr,
S8, 8},
1667 {
S32, LocalPtr,
S16, 16},
1670 {
S32, PrivatePtr,
S32, 32},
1671 {
S32, PrivatePtr,
S8, 8},
1672 {
S32, PrivatePtr,
S16, 16},
1675 {
S32, ConstantPtr,
S32, GlobalAlign32},
1678 {
S64, ConstantPtr,
S64, GlobalAlign32}});
1680 if (IsStore ||
ST.d16PreservesUnusedBits()) {
1681 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1682 {{S16, GlobalPtr, S8, GlobalAlign8},
1683 {S16, GlobalPtr, S16, GlobalAlign16},
1684 {S16, LocalPtr, S8, 8},
1685 {S16, LocalPtr, S16, 16},
1686 {S16, PrivatePtr, S8, 8},
1687 {S16, PrivatePtr, S16, 16}});
1698 Actions.unsupportedIf(
1699 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1713 Actions.customIf(
typeIs(1, Constant32Ptr));
1739 return !Query.
Types[0].isVector() &&
1740 needToSplitMemOp(Query,
Op == G_LOAD);
1742 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1747 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1750 if (DstSize > MemSize)
1756 if (MemSize > MaxSize)
1764 return Query.
Types[0].isVector() &&
1765 needToSplitMemOp(Query,
Op == G_LOAD);
1767 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1781 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1782 if (MemSize > MaxSize) {
1786 if (MaxSize % EltSize == 0) {
1792 unsigned NumPieces = MemSize / MaxSize;
1796 if (NumPieces == 1 || NumPieces >= NumElts ||
1797 NumElts % NumPieces != 0)
1798 return std::pair(0, EltTy);
1806 return std::pair(0, EltTy);
1821 return std::pair(0, EltTy);
1826 .widenScalarToNextPow2(0)
1833 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1834 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1835 {
S32, GlobalPtr,
S16, 2 * 8},
1836 {
S32, LocalPtr,
S8, 8},
1837 {
S32, LocalPtr,
S16, 16},
1838 {
S32, PrivatePtr,
S8, 8},
1839 {
S32, PrivatePtr,
S16, 16},
1840 {
S32, ConstantPtr,
S8, 8},
1841 {
S32, ConstantPtr,
S16, 2 * 8}})
1842 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1843 {{S16, GlobalPtr, S8, GlobalAlign8},
1844 {S16, LocalPtr, S8, GlobalAlign8},
1845 {S16, PrivatePtr, S8, GlobalAlign8},
1846 {S16, ConstantPtr, S8, GlobalAlign8}})
1851 if (
ST.hasFlatAddressSpace()) {
1852 ExtLoads.legalForTypesWithMemDesc(
1853 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1855 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1856 {{S16, FlatPtr, S8, GlobalAlign8}});
1864 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1866 ExtLoads.narrowScalarIf(
1873 ExtLoads.clampScalar(0,
S32,
S32)
1874 .widenScalarToNextPow2(0)
1877 auto &Atomics = getActionDefinitionsBuilder(
1878 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1879 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1880 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1881 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1882 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1883 {
S64, GlobalPtr}, {
S64, LocalPtr},
1884 {
S32, RegionPtr}, {
S64, RegionPtr}});
1885 if (
ST.hasFlatAddressSpace()) {
1886 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1890 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1891 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1892 if (
ST.hasFlatAddressSpace()) {
1893 Atomics32.legalFor({{
S32, FlatPtr}});
1897 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1898 if (
ST.hasLDSFPAtomicAddF32()) {
1900 if (
ST.hasLdsAtomicAddF64())
1902 if (
ST.hasAtomicDsPkAdd16Insts())
1905 if (
ST.hasAtomicFaddInsts())
1907 if (
ST.hasFlatAtomicFaddF32Inst())
1910 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1914 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1917 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1918 ST.hasAtomicBufferGlobalPkAddF16Insts())
1920 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1922 if (
ST.hasAtomicFlatPkAdd16Insts())
1928 auto &AtomicFMinFMax =
1929 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1930 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1932 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1933 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1934 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1935 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1936 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1937 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1938 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1939 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1943 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1944 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1945 {
S32, FlatPtr}, {
S64, FlatPtr}})
1946 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1947 {
S32, RegionPtr}, {
S64, RegionPtr}});
1951 getActionDefinitionsBuilder(G_SELECT)
1953 LocalPtr, FlatPtr, PrivatePtr,
1957 .clampScalar(0,
S16,
S64)
1961 .clampMaxNumElements(0,
S32, 2)
1962 .clampMaxNumElements(0, LocalPtr, 2)
1963 .clampMaxNumElements(0, PrivatePtr, 2)
1965 .widenScalarToNextPow2(0)
1970 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1972 if (
ST.has16BitInsts()) {
1973 if (
ST.hasVOP3PInsts()) {
1975 .clampMaxNumElements(0,
S16, 2);
1977 Shifts.legalFor({{
S16,
S16}});
1980 Shifts.widenScalarIf(
1985 const LLT AmountTy = Query.
Types[1];
1991 Shifts.clampScalar(1,
S32,
S32);
1992 Shifts.widenScalarToNextPow2(0, 16);
1993 Shifts.clampScalar(0,
S16,
S64);
1995 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2003 Shifts.clampScalar(1,
S32,
S32);
2004 Shifts.widenScalarToNextPow2(0, 32);
2005 Shifts.clampScalar(0,
S32,
S64);
2007 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2012 Shifts.scalarize(0);
2014 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
2015 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
2016 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
2017 unsigned IdxTypeIdx = 2;
2019 getActionDefinitionsBuilder(
Op)
2021 const LLT EltTy = Query.
Types[EltTypeIdx];
2022 const LLT VecTy = Query.
Types[VecTypeIdx];
2023 const LLT IdxTy = Query.
Types[IdxTypeIdx];
2025 const bool isLegalVecType =
2035 return (EltSize == 32 || EltSize == 64) &&
2051 const LLT EltTy = Query.
Types[EltTypeIdx];
2052 const LLT VecTy = Query.
Types[VecTypeIdx];
2056 const unsigned TargetEltSize =
2057 DstEltSize % 64 == 0 ? 64 : 32;
2058 return std::pair(VecTypeIdx,
2062 .clampScalar(EltTypeIdx,
S32,
S64)
2063 .clampScalar(VecTypeIdx,
S32,
S64)
2064 .clampScalar(IdxTypeIdx,
S32,
S32)
2065 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2074 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2076 const LLT &EltTy = Query.
Types[1].getElementType();
2077 return Query.
Types[0] != EltTy;
2080 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2081 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2082 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2083 getActionDefinitionsBuilder(
Op)
2086 const LLT BigTy = Query.
Types[BigTyIdx];
2092 const LLT LitTy = Query.
Types[LitTyIdx];
2097 .widenScalarToNextPow2(BigTyIdx, 32)
2105 const LLT BigTy = Query.
Types[BigTyIdx];
2106 const LLT LitTy = Query.
Types[LitTyIdx];
2114 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2124 if (
ST.hasScalarPackInsts()) {
2127 .minScalarOrElt(0,
S16)
2130 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2134 BuildVector.customFor({
V2S16,
S16});
2135 BuildVector.minScalarOrElt(0,
S32);
2137 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2145 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2147 .clampMaxNumElements(0,
S32, 32)
2148 .clampMaxNumElements(1,
S16, 2)
2149 .clampMaxNumElements(0,
S16, 64);
2151 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2154 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2155 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2156 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2158 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2159 const LLT Ty = Query.
Types[TypeIdx];
2171 getActionDefinitionsBuilder(
Op)
2175 const LLT BigTy = Query.
Types[BigTyIdx];
2181 .widenScalarToNextPow2(LitTyIdx, 16)
2190 .clampScalar(LitTyIdx,
S32,
S512)
2191 .widenScalarToNextPow2(LitTyIdx, 32)
2195 return notValidElt(Query, LitTyIdx);
2200 return notValidElt(Query, BigTyIdx);
2205 if (
Op == G_MERGE_VALUES) {
2206 Builder.widenScalarIf(
2209 const LLT Ty = Query.
Types[LitTyIdx];
2215 Builder.widenScalarIf(
2217 const LLT Ty = Query.
Types[BigTyIdx];
2223 const LLT &Ty = Query.
Types[BigTyIdx];
2225 if (NewSizeInBits >= 256) {
2227 if (RoundedTo < NewSizeInBits)
2228 NewSizeInBits = RoundedTo;
2230 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2239 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2240 .legalFor({{
S32}, {
S64}})
2241 .clampScalar(0,
S32,
S64);
2243 if (
ST.hasVOP3PInsts()) {
2244 SextInReg.lowerFor({{
V2S16}})
2248 .clampMaxNumElementsStrict(0,
S16, 2);
2249 }
else if (
ST.has16BitInsts()) {
2250 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2254 SextInReg.lowerFor({{
S32}, {
S64}});
2259 .clampScalar(0,
S32,
S64)
2262 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2266 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2267 FSHRActionDefs.legalFor({{
S32,
S32}})
2268 .clampMaxNumElementsStrict(0,
S16, 2);
2269 if (
ST.hasVOP3PInsts())
2271 FSHRActionDefs.scalarize(0).lower();
2273 if (
ST.hasVOP3PInsts()) {
2274 getActionDefinitionsBuilder(G_FSHL)
2276 .clampMaxNumElementsStrict(0,
S16, 2)
2280 getActionDefinitionsBuilder(G_FSHL)
2285 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2288 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2290 getActionDefinitionsBuilder(G_FENCE)
2293 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2298 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2300 .clampScalar(1,
S32,
S32)
2301 .clampScalar(0,
S32,
S64)
2302 .widenScalarToNextPow2(0)
2305 getActionDefinitionsBuilder(
2309 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2315 if (
ST.hasIEEEMinimumMaximumInsts()) {
2316 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2317 .legalFor(FPTypesPK16)
2318 .clampMaxNumElements(0,
F16, 2)
2320 }
else if (
ST.hasVOP3PInsts()) {
2321 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2323 .clampMaxNumElementsStrict(0,
F16, 2)
2327 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2329 .clampScalar(0,
F32,
F64)
2333 getActionDefinitionsBuilder(
2334 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2337 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2339 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2340 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2341 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2344 getActionDefinitionsBuilder(G_PREFETCH)
2345 .customFor({Constant32Ptr})
2348 getActionDefinitionsBuilder(
2349 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2350 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2351 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2352 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2357 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2358 G_INTRINSIC_CONVERGENT,
2359 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2371 switch (
MI.getOpcode()) {
2372 case TargetOpcode::G_ADDRSPACE_CAST:
2374 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2376 case TargetOpcode::G_FCEIL:
2378 case TargetOpcode::G_FREM:
2380 case TargetOpcode::G_INTRINSIC_TRUNC:
2382 case TargetOpcode::G_SITOFP:
2384 case TargetOpcode::G_UITOFP:
2386 case TargetOpcode::G_FPTOSI:
2388 case TargetOpcode::G_FPTOUI:
2390 case TargetOpcode::G_FMINNUM:
2391 case TargetOpcode::G_FMAXNUM:
2392 case TargetOpcode::G_FMINIMUMNUM:
2393 case TargetOpcode::G_FMAXIMUMNUM:
2395 case TargetOpcode::G_EXTRACT:
2397 case TargetOpcode::G_INSERT:
2399 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2401 case TargetOpcode::G_INSERT_VECTOR_ELT:
2403 case TargetOpcode::G_FSIN:
2404 case TargetOpcode::G_FCOS:
2406 case TargetOpcode::G_GLOBAL_VALUE:
2408 case TargetOpcode::G_LOAD:
2409 case TargetOpcode::G_SEXTLOAD:
2410 case TargetOpcode::G_ZEXTLOAD:
2411 case TargetOpcode::G_PREFETCH:
2413 case TargetOpcode::G_STORE:
2415 case TargetOpcode::G_FMAD:
2417 case TargetOpcode::G_FDIV:
2419 case TargetOpcode::G_FFREXP:
2421 case TargetOpcode::G_FSQRT:
2423 case TargetOpcode::G_UDIV:
2424 case TargetOpcode::G_UREM:
2425 case TargetOpcode::G_UDIVREM:
2427 case TargetOpcode::G_SDIV:
2428 case TargetOpcode::G_SREM:
2429 case TargetOpcode::G_SDIVREM:
2431 case TargetOpcode::G_ATOMIC_CMPXCHG:
2433 case TargetOpcode::G_FLOG2:
2435 case TargetOpcode::G_FLOG:
2436 case TargetOpcode::G_FLOG10:
2438 case TargetOpcode::G_FEXP2:
2440 case TargetOpcode::G_FEXP:
2441 case TargetOpcode::G_FEXP10:
2443 case TargetOpcode::G_FPOW:
2445 case TargetOpcode::G_FFLOOR:
2447 case TargetOpcode::G_BUILD_VECTOR:
2448 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2450 case TargetOpcode::G_MUL:
2452 case TargetOpcode::G_CTLZ:
2453 case TargetOpcode::G_CTTZ:
2455 case TargetOpcode::G_CTLS:
2457 case TargetOpcode::G_CTLZ_ZERO_POISON:
2459 case TargetOpcode::G_STACKSAVE:
2461 case TargetOpcode::G_GET_FPENV:
2463 case TargetOpcode::G_SET_FPENV:
2465 case TargetOpcode::G_TRAP:
2467 case TargetOpcode::G_DEBUGTRAP:
2479 unsigned BaseAS = AS;
2484 Register Aperture = getBaseSegmentAperture(BaseAS,
MRI,
B);
2488 auto Tag =
B.buildConstant(
S32, SANum);
2489 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2495Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2505 if (ST.hasApertureRegs()) {
2509 const unsigned ApertureRegNo =
2510 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2511 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2512 !ST.hasGloballyAddressableScratch()) &&
2513 "Cannot use src_private_base with globally addressable scratch!");
2514 Register Dst =
MRI.createGenericVirtualRegister(I64);
2515 MRI.setRegClass(Dst, &AMDGPU::SReg_64RegClass);
2516 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2517 return B.buildUnmerge(I32, Dst).getReg(1);
2532 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2548 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2551 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2565 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2573 B.buildObjectPtrOffset(
2576 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2584 switch (Def->getOpcode()) {
2585 case AMDGPU::G_FRAME_INDEX:
2586 case AMDGPU::G_GLOBAL_VALUE:
2587 case AMDGPU::G_BLOCK_ADDR:
2589 case AMDGPU::G_CONSTANT: {
2590 const ConstantInt *CI = Def->getOperand(1).getCImm();
2605 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2611 LLT DstTy =
MRI.getType(Dst);
2612 LLT SrcTy =
MRI.getType(Src);
2614 unsigned SrcAS = SrcTy.getAddressSpace();
2628 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2635 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2637 ST.hasGloballyAddressableScratch()) {
2640 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2642 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2643 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2645 MRI.setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2646 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2647 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2650 return B.buildExtract(Dst, Src, 0).getReg(0);
2654 castFlatToLocalOrPrivate(Dst);
2655 MI.eraseFromParent();
2661 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2662 auto FlatNull =
B.buildConstant(SrcTy, 0);
2665 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2669 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2671 MI.eraseFromParent();
2678 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2681 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2684 ST.hasGloballyAddressableScratch()) {
2688 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2689 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2693 if (ST.isWave64()) {
2694 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2700 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2701 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2703 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2707 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2708 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2710 MRI.setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2711 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2720 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2724 castLocalOrPrivateToFlat(Dst);
2725 MI.eraseFromParent();
2729 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2736 SegmentNull.getReg(0));
2738 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2740 MI.eraseFromParent();
2745 SrcTy.getSizeInBits() == 64) {
2747 B.buildExtract(Dst, Src, 0);
2748 MI.eraseFromParent();
2755 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2756 auto PtrLo =
B.buildPtrToInt(I32, Src);
2757 if (AddrHiVal == 0) {
2758 auto Zext =
B.buildZExt(I64, PtrLo);
2759 B.buildIntToPtr(Dst, Zext);
2761 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2762 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2765 MI.eraseFromParent();
2772 MI.eraseFromParent();
2780 LLT Ty =
MRI.getType(Src);
2781 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2786 auto C1 =
B.buildFConstant(Ty, C1Val);
2787 auto CopySign =
B.buildFCopysign(Ty,
C1, Src);
2790 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2791 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2793 auto C2 =
B.buildFConstant(Ty, C2Val);
2794 auto Fabs =
B.buildFAbs(Ty, Src);
2797 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2798 MI.eraseFromParent();
2815 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2817 const auto Zero =
B.buildFConstant(
F64, 0.0);
2818 const auto One =
B.buildFConstant(
F64, 1.0);
2821 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2822 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2825 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2826 MI.eraseFromParent();
2834 Register Src0Reg =
MI.getOperand(1).getReg();
2835 Register Src1Reg =
MI.getOperand(2).getReg();
2836 auto Flags =
MI.getFlags();
2837 LLT Ty =
MRI.getType(DstReg);
2839 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2840 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2841 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2842 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2843 MI.eraseFromParent();
2849 const unsigned FractBits = 52;
2850 const unsigned ExpBits = 11;
2853 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2854 auto Const1 =
B.buildConstant(I32, ExpBits);
2856 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2858 .addUse(Const0.getReg(0))
2859 .addUse(Const1.getReg(0));
2861 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2874 auto SrcInt =
B.buildBitcast(I64, Src);
2877 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2884 const unsigned FractBits = 52;
2887 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2888 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2890 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2892 const auto Zero32 =
B.buildConstant(I32, 0);
2895 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2897 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2898 auto Not =
B.buildNot(I64, Shr);
2899 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2900 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2905 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2906 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2907 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2908 MI.eraseFromParent();
2924 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2925 auto ThirtyTwo =
B.buildConstant(I32, 32);
2927 if (
MRI.getType(Dst) ==
F64) {
2928 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2929 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2931 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2932 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2935 B.buildFAdd(Dst, LdExp, CvtLo);
2936 MI.eraseFromParent();
2942 auto One =
B.buildConstant(I32, 1);
2946 auto ThirtyOne =
B.buildConstant(I32, 31);
2947 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2948 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2949 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2950 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2951 .addUse(Unmerge.getReg(1));
2952 auto LS2 =
B.buildSub(I32, LS, One);
2953 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2955 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2956 auto Norm =
B.buildShl(I64, Src, ShAmt);
2957 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2958 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2959 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2960 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2961 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2962 B.buildFLdexp(Dst, FVal, Scale);
2963 MI.eraseFromParent();
2980 const LLT SrcLT =
MRI.getType(Src);
2983 unsigned Flags =
MI.getFlags();
2994 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
3002 auto SrcInt =
B.buildBitcast(I32, Src);
3003 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
3004 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
3008 K0 =
B.buildFConstant(
3010 K1 =
B.buildFConstant(
3013 K0 =
B.buildFConstant(
3015 K1 =
B.buildFConstant(
3019 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
3020 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
3021 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
3023 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
3024 :
B.buildFPTOUI(I32, FloorMul);
3025 auto Lo =
B.buildFPTOUI(I32, Fma);
3029 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
3031 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
3034 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3035 MI.eraseFromParent();
3058 uint64_t
Offset =
MI.getOperand(2).getImm();
3066 const LLT DstTy =
MRI.getType(DstReg);
3067 unsigned StartIdx =
Offset / 32;
3071 if (DstCount == 1) {
3073 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3076 MRI.replaceRegWith(DstReg, Unmerge.getReg(StartIdx));
3081 for (
unsigned I = 0;
I < DstCount; ++
I)
3082 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3083 B.buildMergeLikeInstr(DstReg, MergeVec);
3086 MI.eraseFromParent();
3096 Register InsertSrc =
MI.getOperand(2).getReg();
3097 uint64_t
Offset =
MI.getOperand(3).getImm();
3099 unsigned DstSize =
MRI.getType(DstReg).getSizeInBits();
3100 const LLT InsertTy =
MRI.getType(InsertSrc);
3105 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3109 unsigned DstCount = DstSize / 32;
3110 unsigned InsertCount = InsertSize / 32;
3111 unsigned StartIdx =
Offset / 32;
3113 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3116 for (
unsigned I = 0;
I < StartIdx; ++
I)
3119 if (InsertCount == 1) {
3123 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3126 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3127 for (
unsigned I = 0;
I < InsertCount; ++
I)
3131 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3134 B.buildMergeLikeInstr(DstReg, MergeVec);
3136 MI.eraseFromParent();
3150 LLT VecTy =
MRI.getType(Vec);
3163 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3164 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3165 B.buildIntToPtr(Dst, IntElt);
3167 MI.eraseFromParent();
3174 std::optional<ValueAndVReg> MaybeIdxVal =
3178 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3181 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3182 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3187 MI.eraseFromParent();
3202 LLT VecTy =
MRI.getType(Vec);
3216 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3217 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3218 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3220 B.buildIntToPtr(Dst, IntVecDest);
3221 MI.eraseFromParent();
3228 std::optional<ValueAndVReg> MaybeIdxVal =
3233 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3236 if (IdxVal < NumElts) {
3238 for (
unsigned i = 0; i < NumElts; ++i)
3239 SrcRegs.
push_back(
MRI.createGenericVirtualRegister(EltTy));
3240 B.buildUnmerge(SrcRegs, Vec);
3242 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3243 B.buildMergeLikeInstr(Dst, SrcRegs);
3248 MI.eraseFromParent();
3258 LLT Ty =
MRI.getType(DstReg);
3259 unsigned Flags =
MI.getFlags();
3263 if (ST.hasTrigReducedRange()) {
3264 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3265 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3266 .addUse(MulVal.getReg(0))
3270 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3273 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3277 MI.eraseFromParent();
3285 unsigned GAFlags)
const {
3316 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass, PCRegTy});
3318 if (ST.has64BitLiterals()) {
3322 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3326 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3337 B.buildExtract(DstReg, PCReg, 0);
3339 B.buildCopy(DstReg, PCReg);
3349 if (RequiresHighHalf && ST.has64BitLiterals()) {
3351 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass, PtrTy});
3352 B.buildInstr(AMDGPU::S_MOV_B64)
3355 B.buildCopy(DstReg, Addr);
3360 Register AddrLo =
MRI.createVirtualRegister({&AMDGPU::SReg_32RegClass, I32});
3363 B.buildInstr(AMDGPU::S_MOV_B32)
3368 if (RequiresHighHalf) {
3370 "Must provide a 64-bit pointer type!");
3373 MRI.createVirtualRegister({&AMDGPU::SReg_32RegClass, I32});
3375 B.buildInstr(AMDGPU::S_MOV_B32)
3380 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass,
LLT::integer(64)});
3382 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3383 B.buildCast(DstReg, AddrDst);
3385 B.buildCast(DstReg, AddrLo);
3393 LLT Ty =
MRI.getType(DstReg);
3394 unsigned AS = Ty.getAddressSpace();
3405 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3407 B.buildUndef(DstReg);
3408 MI.eraseFromParent();
3412 B.buildConstant(DstReg,
3414 MI.eraseFromParent();
3420 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3423 Fn,
"local memory global used by non-kernel function",
3432 B.buildUndef(DstReg);
3433 MI.eraseFromParent();
3457 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3458 B.buildIntToPtr(DstReg, Sz);
3459 MI.eraseFromParent();
3465 MI.eraseFromParent();
3469 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3471 MI.eraseFromParent();
3479 MI.eraseFromParent();
3485 MI.eraseFromParent();
3490 Register GOTAddr =
MRI.createGenericVirtualRegister(PtrTy);
3501 if (Ty.getSizeInBits() == 32) {
3503 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3504 B.buildExtract(DstReg,
Load, 0);
3506 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3508 MI.eraseFromParent();
3525 unsigned PtrIdx =
MI.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3526 Register PtrReg =
MI.getOperand(PtrIdx).getReg();
3527 LLT PtrTy =
MRI.getType(PtrReg);
3532 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3534 MI.getOperand(PtrIdx).setReg(Cast.getReg(0));
3539 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3543 LLT ValTy =
MRI.getType(ValReg);
3557 const uint64_t AlignInBits = 8 * MemAlign.
value();
3565 if (WideMemSize == ValSize) {
3571 MI.setMemRefs(MF, {WideMMO});
3577 if (ValSize > WideMemSize)
3584 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3585 B.buildTrunc(ValReg, WideLoad).getReg(0);
3592 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3593 B.buildExtract(ValReg, WideLoad, 0);
3597 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3598 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3602 MI.eraseFromParent();
3615 Register DataReg =
MI.getOperand(0).getReg();
3616 LLT DataTy =
MRI.getType(DataReg);
3630 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
3660 "this should not have been custom lowered");
3662 LLT ValTy =
MRI.getType(CmpVal);
3665 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3667 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3671 .setMemRefs(
MI.memoperands());
3673 MI.eraseFromParent();
3681 switch (
DefMI->getOpcode()) {
3682 case TargetOpcode::G_INTRINSIC: {
3684 case Intrinsic::amdgcn_frexp_mant:
3685 case Intrinsic::amdgcn_log:
3686 case Intrinsic::amdgcn_log_clamp:
3687 case Intrinsic::amdgcn_exp2:
3688 case Intrinsic::amdgcn_sqrt:
3696 case TargetOpcode::G_FSQRT:
3698 case TargetOpcode::G_FFREXP: {
3699 if (
DefMI->getOperand(0).getReg() == Src)
3703 case TargetOpcode::G_FPEXT: {
3704 return MRI.getType(
DefMI->getOperand(1).getReg()) ==
F16;
3724std::pair<Register, Register>
3726 unsigned Flags)
const {
3730 auto SmallestNormal =
B.buildFConstant(
3732 auto IsLtSmallestNormal =
3735 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3736 auto One =
B.buildFConstant(
F32, 1.0);
3738 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3739 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3741 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3754 LLT Ty =
B.getMRI()->getType(Dst);
3755 unsigned Flags =
MI.getFlags();
3759 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3760 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3761 .addUse(Ext.getReg(0))
3763 B.buildFPTrunc(Dst,
Log2, Flags);
3764 MI.eraseFromParent();
3772 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3775 MI.eraseFromParent();
3779 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3780 .addUse(ScaledInput)
3783 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3784 auto Zero =
B.buildFConstant(Ty, 0.0);
3786 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3787 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3789 MI.eraseFromParent();
3795 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3796 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3801 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3802 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3807 unsigned Flags =
MI.getFlags();
3808 const LLT Ty =
MRI.getType(
X);
3817 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3819 B.buildFPTrunc(Dst, LogVal, Flags);
3824 MI.eraseFromParent();
3833 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3836 if (ST.hasFastFMAF32()) {
3838 const float c_log10 = 0x1.344134p-2f;
3839 const float cc_log10 = 0x1.09f79ep-26f;
3842 const float c_log = 0x1.62e42ep-1f;
3843 const float cc_log = 0x1.efa39ep-25f;
3845 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3846 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3850 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3851 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3852 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3853 auto FMA1 =
B.buildFMA(Ty,
Y,
CC, FMA0, NewFlags);
3854 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3857 const float ch_log10 = 0x1.344000p-2f;
3858 const float ct_log10 = 0x1.3509f6p-18f;
3861 const float ch_log = 0x1.62e000p-1f;
3862 const float ct_log = 0x1.0bfbe8p-15f;
3864 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3865 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3868 auto YInt =
B.buildBitcast(I32,
Y);
3869 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3870 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3871 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3875 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3878 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3880 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3883 const bool IsFiniteOnly =
3886 if (!IsFiniteOnly) {
3889 auto Fabs =
B.buildFAbs(Ty,
Y);
3892 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3896 auto Zero =
B.buildFConstant(Ty, 0.0);
3898 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3899 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3900 B.buildFSub(Dst, R, Shift, Flags);
3902 B.buildCopy(Dst, R);
3905 MI.eraseFromParent();
3911 unsigned Flags)
const {
3912 const double Log2BaseInverted =
3915 LLT Ty =
B.getMRI()->getType(Dst);
3920 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3921 .addUse(ScaledInput)
3923 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3924 auto Zero =
B.buildFConstant(Ty, 0.0);
3926 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3927 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3929 if (ST.hasFastFMAF32())
3930 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3932 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3933 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3940 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3941 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3944 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3945 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3956 unsigned Flags =
MI.getFlags();
3957 LLT Ty =
B.getMRI()->getType(Dst);
3964 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3965 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3966 .addUse(Ext.getReg(0))
3968 B.buildFPTrunc(Dst,
Log2, Flags);
3969 MI.eraseFromParent();
3979 MI.eraseFromParent();
3987 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3989 RangeCheckConst, Flags);
3991 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3992 auto Zero =
B.buildFConstant(Ty, 0.0);
3993 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3994 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3996 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3997 .addUse(AddInput.getReg(0))
4000 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
4001 auto One =
B.buildFConstant(Ty, 1.0);
4002 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
4003 B.buildFMul(Dst, Exp2, ResultScale, Flags);
4004 MI.eraseFromParent();
4009 const SrcOp &Src,
unsigned Flags) {
4010 LLT Ty = Dst.getLLTTy(*
B.getMRI());
4013 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
4014 .addUse(Src.getReg())
4017 return B.buildFExp2(Dst, Src, Flags);
4023 bool IsExp10)
const {
4024 LLT Ty =
B.getMRI()->getType(
X);
4028 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
4029 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4036 LLT Ty =
B.getMRI()->getType(Dst);
4042 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4045 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4046 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4047 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4050 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4052 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4053 .addUse(ExpInput.getReg(0))
4056 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4057 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4058 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4064 unsigned Flags)
const {
4065 LLT Ty =
B.getMRI()->getType(Dst);
4069 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4070 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4072 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4073 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4074 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4075 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4076 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4086 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4090 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4091 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4092 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4094 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4095 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4097 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4098 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4099 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4100 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4102 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4103 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4104 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4106 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4124 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4126 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4128 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4130 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4131 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4132 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4133 T =
B.buildFMA(
F64,
F,
C1, Mul2, Flags).getReg(0);
4135 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4136 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4137 auto Mul =
B.buildFMul(
F64,
X,
C1, Flags).getReg(0);
4138 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4140 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4141 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4142 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4143 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4144 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4146 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4147 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4148 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4149 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4152 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4153 auto Mul =
B.buildFMul(
F64,
X,
C1, Flags).getReg(0);
4154 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4156 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4157 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4158 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4159 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4160 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4164 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4165 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4167 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4169 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4171 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4173 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4175 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4176 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4177 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4178 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4180 auto One =
B.buildFConstant(
F64, 1.0);
4181 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4182 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4185 auto DnInt =
B.buildFPTOSI(I32, Dn);
4186 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4193 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4200 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4202 MI.eraseFromParent();
4210 const unsigned Flags =
MI.getFlags();
4213 LLT Ty =
MRI.getType(Dst);
4218 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4226 MI.eraseFromParent();
4237 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4240 B.buildFPTrunc(Dst, Lowered, Flags);
4241 MI.eraseFromParent();
4252 MI.eraseFromParent();
4280 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4283 if (ST.hasFastFMAF32()) {
4285 const float cc_exp = 0x1.4ae0bep-26f;
4286 const float c_exp10 = 0x1.a934f0p+1f;
4287 const float cc_exp10 = 0x1.2f346ep-24f;
4289 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4290 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4291 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4292 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4294 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4295 PL =
B.buildFMA(Ty,
X,
CC, FMA0, Flags).getReg(0);
4297 const float ch_exp = 0x1.714000p+0f;
4298 const float cl_exp = 0x1.47652ap-12f;
4300 const float ch_exp10 = 0x1.a92000p+1f;
4301 const float cl_exp10 = 0x1.4f0978p-11f;
4304 auto XInt =
B.buildBitcast(I32,
X);
4305 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4306 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4307 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4309 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4310 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4312 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4313 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4316 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4317 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4320 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4323 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4324 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4326 auto IntE =
B.buildFPTOSI(I32, E);
4328 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4329 .addUse(
A.getReg(0))
4331 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4333 auto UnderflowCheckConst =
4334 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4335 auto Zero =
B.buildFConstant(Ty, 0.0);
4339 R =
B.buildSelect(Ty, Underflow, Zero, R);
4342 auto OverflowCheckConst =
4343 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4348 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4351 B.buildCopy(Dst, R);
4352 MI.eraseFromParent();
4363 unsigned Flags =
MI.getFlags();
4372 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4374 .setMIFlags(CoreFlags);
4375 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4377 .addUse(Log.getReg(0))
4378 .setMIFlags(CoreFlags);
4380 MI.eraseFromParent();
4384 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4385 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4386 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4388 .addUse(Log.getReg(0))
4389 .setMIFlags(CoreFlags);
4394 .signBitIsZeroOrNaN()) {
4395 B.buildFExp2(Dst,
Mul, CoreFlags);
4396 MI.eraseFromParent();
4402 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4404 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4405 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4406 auto YIsOdd =
B.buildAnd(
4410 auto Neg =
B.buildFCopysign(
F32, R,
X);
4412 B.buildSelect(Dst, YIsOdd, Neg, R);
4413 MI.eraseFromParent();
4416 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4423 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4425 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4427 B.buildSelect(Dst, NegNonInt, NaN, R);
4429 MI.eraseFromParent();
4437 ModSrc = SrcFNeg->getOperand(1).getReg();
4439 ModSrc = SrcFAbs->getOperand(1).getReg();
4441 ModSrc = SrcFAbs->getOperand(1).getReg();
4451 Register OrigSrc =
MI.getOperand(1).getReg();
4452 unsigned Flags =
MI.getFlags();
4454 "this should not have been custom lowered");
4464 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4483 if (MFI->
getMode().
IEEE && !ST.hasIEEEMinimumMaximumInsts())
4484 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4486 B.buildFMinNum(Min, Fract, Const, Flags);
4491 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4494 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4495 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4497 MI.eraseFromParent();
4509 MRI.getType(Dst).getNumElements() == 2 &&
4510 MRI.getType(Dst).getScalarSizeInBits() == 16);
4515 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4517 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4518 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4521 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4522 B.buildBitcast(Dst,
Merge);
4524 MI.eraseFromParent();
4541 bool UsePartialMad64_32,
4542 bool SeparateOddAlignedProducts)
const {
4557 auto getZero32 = [&]() ->
Register {
4559 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4562 auto getZero64 = [&]() ->
Register {
4564 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4569 for (
unsigned i = 0; i < Src0.size(); ++i) {
4580 if (CarryIn.empty())
4583 bool HaveCarryOut =
true;
4585 if (CarryIn.size() == 1) {
4587 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4591 CarryAccum = getZero32();
4593 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4594 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4596 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4601 LocalAccum = getZero32();
4602 HaveCarryOut =
false;
4607 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4608 LocalAccum =
Add.getReg(0);
4622 auto buildMadChain =
4625 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4626 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4633 if (LocalAccum.size() == 1 &&
4634 (!UsePartialMad64_32 || !CarryIn.empty())) {
4637 unsigned j1 = DstIndex - j0;
4638 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4642 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4644 LocalAccum[0] =
Mul.getReg(0);
4646 if (CarryIn.empty()) {
4647 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4650 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4656 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4660 if (j0 <= DstIndex) {
4661 bool HaveSmallAccum =
false;
4664 if (LocalAccum[0]) {
4665 if (LocalAccum.size() == 1) {
4666 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4667 HaveSmallAccum =
true;
4668 }
else if (LocalAccum[1]) {
4669 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4670 HaveSmallAccum =
false;
4672 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4673 HaveSmallAccum =
true;
4676 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4678 HaveSmallAccum =
true;
4682 unsigned j1 = DstIndex - j0;
4683 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4687 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4688 {Src0[j0], Src1[j1], Tmp});
4689 Tmp = Mad.getReg(0);
4690 if (!HaveSmallAccum)
4691 CarryOut.push_back(Mad.getReg(1));
4692 HaveSmallAccum =
false;
4695 }
while (j0 <= DstIndex);
4697 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4698 LocalAccum[0] = Unmerge.getReg(0);
4699 if (LocalAccum.size() > 1)
4700 LocalAccum[1] = Unmerge.getReg(1);
4707 LocalAccum[0] = getZero32();
4711 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4712 "Uninitialized accumulator part");
4738 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4739 Carry OddCarryIn = std::move(OddCarry);
4740 Carry EvenCarryIn = std::move(EvenCarry);
4745 if (2 * i < Accum.
size()) {
4746 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4747 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4752 if (!SeparateOddAlignedProducts) {
4753 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4754 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4756 bool IsHighest = 2 * i >= Accum.
size();
4759 .take_front(IsHighest ? 1 : 2);
4760 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4766 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4768 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4770 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4773 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4776 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4777 Lo->getOperand(1).getReg());
4778 Accum[2 * i] =
Hi.getReg(0);
4779 SeparateOddCarry =
Hi.getReg(1);
4786 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4787 EvenCarryIn.push_back(CarryOut);
4789 if (2 * i < Accum.
size()) {
4790 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4791 OddCarry.push_back(CarryOut);
4803 assert(ST.hasMad64_32());
4804 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4813 LLT Ty =
MRI.getType(DstReg);
4816 unsigned Size = Ty.getSizeInBits();
4817 if (ST.useVMulU64Inst() &&
Size == 64)
4820 unsigned NumParts =
Size / 32;
4832 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4836 for (
unsigned i = 0; i < NumParts; ++i) {
4837 Src0Parts.
push_back(
MRI.createGenericVirtualRegister(I32));
4838 Src1Parts.
push_back(
MRI.createGenericVirtualRegister(I32));
4840 B.buildUnmerge(Src0Parts, Src0);
4841 B.buildUnmerge(Src1Parts, Src1);
4844 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4845 SeparateOddAlignedProducts);
4847 B.buildMergeLikeInstr(DstReg, AccumRegs);
4848 MI.eraseFromParent();
4860 LLT DstTy =
MRI.getType(Dst);
4861 LLT SrcTy =
MRI.getType(Src);
4863 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4864 ? AMDGPU::G_AMDGPU_FFBH_U32
4865 : AMDGPU::G_AMDGPU_FFBL_B32;
4866 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4869 MI.eraseFromParent();
4878 LLT SrcTy =
MRI.getType(Src);
4879 TypeSize NumBits = SrcTy.getSizeInBits();
4884 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4885 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4886 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4887 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4888 B.buildTrunc(Dst, Ctlz);
4889 MI.eraseFromParent();
4898 LLT SrcTy =
MRI.getType(Src);
4900 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4901 unsigned BitWidth = SrcTy.getSizeInBits();
4903 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4904 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4905 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4906 MI.eraseFromParent();
4912 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4915 return ConstVal == -1;
4922 Register CondDef =
MI.getOperand(0).getReg();
4923 if (!
MRI.hasOneNonDBGUse(CondDef))
4931 if (!
MRI.hasOneNonDBGUse(NegatedCond))
4937 UseMI = &*
MRI.use_instr_nodbg_begin(NegatedCond);
4941 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4950 UncondBrTarget = &*NextMBB;
4952 if (
Next->getOpcode() != AMDGPU::G_BR)
4971 *ArgRC,
B.getDebugLoc(), ArgTy);
4975 const unsigned Mask = Arg->
getMask();
4983 auto ShiftAmt =
B.buildConstant(I32, Shift);
4984 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4987 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4989 B.buildCopy(DstReg, LiveIn);
4999 if (!ST.hasClusters()) {
5002 MI.eraseFromParent();
5014 Register ClusterIdXYZ =
MRI.createGenericVirtualRegister(I32);
5015 Register ClusterMaxIdXYZ =
MRI.createGenericVirtualRegister(I32);
5016 Register ClusterWorkGroupIdXYZ =
MRI.createGenericVirtualRegister(I32);
5022 auto One =
B.buildConstant(I32, 1);
5023 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
5024 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
5025 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
5032 B.buildCopy(DstReg, GlobalIdXYZ);
5033 MI.eraseFromParent();
5037 B.buildCopy(DstReg, ClusterIdXYZ);
5038 MI.eraseFromParent();
5043 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5044 Register ClusterId =
MRI.createGenericVirtualRegister(I32);
5045 MRI.setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5046 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5048 .addImm(ClusterIdField);
5049 auto Zero =
B.buildConstant(I32, 0);
5052 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5053 MI.eraseFromParent();
5095 auto LoadConstant = [&](
unsigned N) {
5096 B.buildConstant(DstReg,
N);
5100 if (ST.hasArchitectedSGPRs() &&
5108 Arg = &WorkGroupIDX;
5109 ArgRC = &AMDGPU::SReg_32RegClass;
5113 Arg = &WorkGroupIDY;
5114 ArgRC = &AMDGPU::SReg_32RegClass;
5118 Arg = &WorkGroupIDZ;
5119 ArgRC = &AMDGPU::SReg_32RegClass;
5123 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5124 return LoadConstant(0);
5125 Arg = &ClusterWorkGroupIDX;
5126 ArgRC = &AMDGPU::SReg_32RegClass;
5130 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5131 return LoadConstant(0);
5132 Arg = &ClusterWorkGroupIDY;
5133 ArgRC = &AMDGPU::SReg_32RegClass;
5137 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5138 return LoadConstant(0);
5139 Arg = &ClusterWorkGroupIDZ;
5140 ArgRC = &AMDGPU::SReg_32RegClass;
5145 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5146 Arg = &ClusterWorkGroupMaxIDX;
5147 ArgRC = &AMDGPU::SReg_32RegClass;
5152 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5153 Arg = &ClusterWorkGroupMaxIDY;
5154 ArgRC = &AMDGPU::SReg_32RegClass;
5159 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5160 Arg = &ClusterWorkGroupMaxIDZ;
5161 ArgRC = &AMDGPU::SReg_32RegClass;
5165 Arg = &ClusterWorkGroupMaxFlatID;
5166 ArgRC = &AMDGPU::SReg_32RegClass;
5181 return LoadConstant(0);
5186 B.buildUndef(DstReg);
5190 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5202 MI.eraseFromParent();
5208 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5209 MI.eraseFromParent();
5216 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5230 B.buildUndef(DstReg);
5231 MI.eraseFromParent();
5235 if (Arg->isMasked()) {
5249 MI.eraseFromParent();
5264 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5273 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5281 Align Alignment)
const {
5285 "unexpected kernarg parameter type");
5292 MI.eraseFromParent();
5300 LLT DstTy =
MRI.getType(Dst);
5324 auto FloatY =
B.buildUITOFP(
F32,
Y);
5325 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5327 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5328 auto Z =
B.buildFPTOUI(I32, ScaledY);
5331 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5332 auto NegYZ =
B.buildMul(I32, NegY, Z);
5333 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5336 auto Q =
B.buildUMulH(I32,
X, Z);
5337 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5340 auto One =
B.buildConstant(I32, 1);
5343 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5344 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5349 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5352 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5371 auto Unmerge =
B.buildUnmerge(I32, Val);
5373 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5374 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5376 auto Mad =
B.buildFMAD(
5380 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5381 auto Mul1 =
B.buildFMul(
5385 auto Mul2 =
B.buildFMul(
5387 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5390 auto Mad2 =
B.buildFMAD(
5394 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5395 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5397 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5412 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5414 auto Zero64 =
B.buildConstant(I64, 0);
5415 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5417 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5418 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5420 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5421 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5422 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5424 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5425 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5426 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5428 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5429 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5430 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5431 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5432 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5434 auto Zero32 =
B.buildConstant(I32, 0);
5435 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5436 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5437 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5439 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5440 Register NumerLo = UnmergeNumer.getReg(0);
5441 Register NumerHi = UnmergeNumer.getReg(1);
5443 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5444 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5445 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5446 Register Mul3_Lo = UnmergeMul3.getReg(0);
5447 Register Mul3_Hi = UnmergeMul3.getReg(1);
5448 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5449 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5450 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5451 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5453 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5454 Register DenomLo = UnmergeDenom.getReg(0);
5455 Register DenomHi = UnmergeDenom.getReg(1);
5458 auto C1 =
B.buildSExt(I32, CmpHi);
5461 auto C2 =
B.buildSExt(I32, CmpLo);
5464 auto C3 =
B.buildSelect(I32, CmpEq, C2,
C1);
5471 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5472 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5473 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5474 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5476 auto One64 =
B.buildConstant(I64, 1);
5477 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5483 auto C6 =
B.buildSelect(
5487 auto Add4 =
B.buildAdd(I64, Add3, One64);
5488 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5490 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5491 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5492 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5498 auto Sel1 =
B.buildSelect(
5505 auto Sel2 =
B.buildSelect(
5516 switch (
MI.getOpcode()) {
5519 case AMDGPU::G_UDIV: {
5520 DstDivReg =
MI.getOperand(0).getReg();
5523 case AMDGPU::G_UREM: {
5524 DstRemReg =
MI.getOperand(0).getReg();
5527 case AMDGPU::G_UDIVREM: {
5528 DstDivReg =
MI.getOperand(0).getReg();
5529 DstRemReg =
MI.getOperand(1).getReg();
5536 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5537 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5538 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5539 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
5548 MI.eraseFromParent();
5558 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
5559 if (Ty != I32 && Ty != I64)
5562 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5563 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5564 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5566 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5567 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5568 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5570 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5571 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5573 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5574 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5576 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5577 switch (
MI.getOpcode()) {
5580 case AMDGPU::G_SDIV: {
5581 DstDivReg =
MI.getOperand(0).getReg();
5582 TmpDivReg =
MRI.createGenericVirtualRegister(Ty);
5585 case AMDGPU::G_SREM: {
5586 DstRemReg =
MI.getOperand(0).getReg();
5587 TmpRemReg =
MRI.createGenericVirtualRegister(Ty);
5590 case AMDGPU::G_SDIVREM: {
5591 DstDivReg =
MI.getOperand(0).getReg();
5592 DstRemReg =
MI.getOperand(1).getReg();
5593 TmpDivReg =
MRI.createGenericVirtualRegister(Ty);
5594 TmpRemReg =
MRI.createGenericVirtualRegister(Ty);
5605 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5606 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5607 B.buildSub(DstDivReg, SignXor, Sign);
5611 auto Sign = LHSign.getReg(0);
5612 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5613 B.buildSub(DstRemReg, SignXor, Sign);
5616 MI.eraseFromParent();
5626 uint16_t Flags =
MI.getFlags();
5627 LLT ResTy =
MRI.getType(Res);
5632 if (!AllowInaccurateRcp && ResTy !=
F16)
5643 if (CLHS->isOne()) {
5644 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5648 MI.eraseFromParent();
5653 if (CLHS->isMinusOne()) {
5654 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5655 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5656 .addUse(FNeg.getReg(0))
5659 MI.eraseFromParent();
5666 if (!AllowInaccurateRcp &&
5671 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5674 B.buildFMul(Res, LHS, RCP, Flags);
5676 MI.eraseFromParent();
5686 uint16_t Flags =
MI.getFlags();
5687 LLT ResTy =
MRI.getType(Res);
5691 if (!AllowInaccurateRcp)
5699 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5701 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5702 auto One =
B.buildFConstant(ResTy, 1.0);
5704 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5708 R =
B.buildFNeg(ResTy, R);
5710 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5711 R =
B.buildFMA(ResTy, Tmp0, R, R);
5713 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5714 R =
B.buildFMA(ResTy, Tmp1, R, R);
5717 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5718 B.buildCopy(Res, R);
5719 MI.eraseFromParent();
5723 auto Ret =
B.buildFMul(ResTy,
X, R);
5724 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5726 B.buildFMA(Res, Tmp2, R, Ret);
5727 MI.eraseFromParent();
5741 uint16_t Flags =
MI.getFlags();
5758 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5759 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5760 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5761 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5762 .addUse(RHSExt.getReg(0))
5764 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5766 if (ST.hasMadMacF32Insts()) {
5767 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5768 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5769 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5771 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5772 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5773 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5775 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5776 auto TmpInt =
B.buildBitcast(I32, Tmp);
5777 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5778 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5779 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5780 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5781 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5782 .addUse(RDst.getReg(0))
5787 MI.eraseFromParent();
5800 unsigned SPDenormMode =
5803 if (ST.hasDenormModeInst()) {
5805 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5807 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5808 B.buildInstr(AMDGPU::S_DENORM_MODE)
5809 .addImm(NewDenormModeValue);
5812 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5813 .addImm(SPDenormMode)
5830 uint16_t Flags =
MI.getFlags();
5834 auto One =
B.buildFConstant(
F32, 1.0f);
5836 auto DenominatorScaled =
5837 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5842 auto NumeratorScaled =
5843 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5849 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5850 .addUse(DenominatorScaled.getReg(0))
5852 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5855 const bool HasDynamicDenormals =
5860 if (!PreservesDenormals) {
5861 if (HasDynamicDenormals) {
5862 SavedSPDenormMode =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5863 B.buildInstr(AMDGPU::S_GETREG_B32)
5864 .addDef(SavedSPDenormMode)
5870 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5871 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5872 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5873 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5874 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5875 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5877 if (!PreservesDenormals) {
5878 if (HasDynamicDenormals) {
5879 assert(SavedSPDenormMode);
5880 B.buildInstr(AMDGPU::S_SETREG_B32)
5881 .addReg(SavedSPDenormMode)
5887 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5888 .addUse(Fma4.getReg(0))
5889 .addUse(Fma1.getReg(0))
5890 .addUse(Fma3.getReg(0))
5891 .addUse(NumeratorScaled.getReg(1))
5894 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5895 .addUse(Fmas.getReg(0))
5900 MI.eraseFromParent();
5914 uint16_t Flags =
MI.getFlags();
5918 auto One =
B.buildFConstant(
F64, 1.0);
5920 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5926 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5928 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5929 .addUse(DivScale0.getReg(0))
5932 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5933 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5934 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5936 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5942 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5943 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5944 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5947 if (!ST.hasUsableDivScaleConditionOutput()) {
5954 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5955 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5956 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5957 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5960 Scale1Unmerge.getReg(1));
5962 Scale0Unmerge.getReg(1));
5963 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5965 Scale = DivScale1.getReg(1);
5968 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5969 .addUse(Fma4.getReg(0))
5970 .addUse(Fma3.getReg(0))
5971 .addUse(
Mul.getReg(0))
5975 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5976 .addUse(Fmas.getReg(0))
5981 MI.eraseFromParent();
5991 uint16_t Flags =
MI.getFlags();
5993 LLT Ty =
MRI.getType(Res0);
5996 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5999 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
6003 if (ST.hasFractBug()) {
6004 auto Fabs =
B.buildFAbs(Ty, Val);
6008 auto Zero =
B.buildConstant(InstrExpTy, 0);
6009 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
6010 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
6013 B.buildCopy(Res0, Mant);
6014 B.buildSExtOrTrunc(Res1, Exp);
6016 MI.eraseFromParent();
6026 uint16_t Flags =
MI.getFlags();
6030 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
6032 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
6033 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
6034 auto C2 =
B.buildFConstant(
F32, 1.0f);
6037 auto Sel =
B.buildSelect(
F32, CmpRes,
C1, C2, Flags);
6039 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6041 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6042 .addUse(Mul0.getReg(0))
6045 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6047 B.buildFMul(Res, Sel, Mul1, Flags);
6049 MI.eraseFromParent();
6058 unsigned Flags =
MI.getFlags();
6059 assert(!ST.has16BitInsts());
6060 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6061 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6062 .addUse(Ext.getReg(0))
6064 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6065 MI.eraseFromParent();
6075 const unsigned Flags =
MI.getFlags();
6083 MI.eraseFromParent();
6087 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6089 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6090 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6091 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6096 .addUse(SqrtX.getReg(0))
6099 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6100 auto NegOne =
B.buildConstant(I32, -1);
6101 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6103 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6104 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6106 auto PosOne =
B.buildConstant(I32, 1);
6107 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6109 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6110 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6112 auto Zero =
B.buildFConstant(
F32, 0.0f);
6116 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6120 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6123 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6124 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6126 auto Half =
B.buildFConstant(
F32, 0.5f);
6127 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6128 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6129 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6130 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6131 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6132 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6133 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6134 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6137 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6139 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6141 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6144 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6146 MI.eraseFromParent();
6177 assert(
MRI.getType(Dst) ==
F64 &&
"only expect to lower f64 sqrt");
6180 unsigned Flags =
MI.getFlags();
6185 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6187 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6191 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6192 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6193 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6196 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6198 auto Half =
B.buildFConstant(
F64, 0.5);
6199 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6200 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6202 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6203 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6205 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6206 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6208 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6209 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6211 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6213 Register SqrtRet = SqrtS2.getReg(0);
6215 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6216 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6217 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6220 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6221 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6222 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6227 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6230 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6236 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6238 MI.eraseFromParent();
6245 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
6269 auto Flags =
MI.getFlags();
6271 LLT Ty =
MRI.getType(Dst);
6281 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6291 auto ClampMax = UseIEEE && !ST.hasIEEEMinimumMaximumInsts()
6292 ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags)
6293 :
B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6297 if (UseIEEE && !ST.hasIEEEMinimumMaximumInsts())
6298 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6300 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6301 MI.eraseFromParent();
6313 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6314 IID == Intrinsic::amdgcn_permlanex16;
6315 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6316 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6317 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6318 IID == Intrinsic::amdgcn_permlane_up ||
6319 IID == Intrinsic::amdgcn_permlane_down ||
6320 IID == Intrinsic::amdgcn_permlane_xor;
6324 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6326 case Intrinsic::amdgcn_readfirstlane:
6327 case Intrinsic::amdgcn_permlane64:
6328 return LaneOp.getReg(0);
6329 case Intrinsic::amdgcn_readlane:
6330 case Intrinsic::amdgcn_set_inactive:
6331 case Intrinsic::amdgcn_set_inactive_chain_arg:
6332 return LaneOp.addUse(Src1).getReg(0);
6333 case Intrinsic::amdgcn_writelane:
6334 case Intrinsic::amdgcn_permlane_bcast:
6335 case Intrinsic::amdgcn_permlane_up:
6336 case Intrinsic::amdgcn_permlane_down:
6337 case Intrinsic::amdgcn_permlane_xor:
6338 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6339 case Intrinsic::amdgcn_permlane16:
6340 case Intrinsic::amdgcn_permlanex16: {
6342 int64_t Src4 =
MI.getOperand(6).getImm();
6343 int64_t Src5 =
MI.getOperand(7).getImm();
6344 return LaneOp.addUse(Src1)
6351 case Intrinsic::amdgcn_mov_dpp8:
6352 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6353 case Intrinsic::amdgcn_update_dpp:
6354 return LaneOp.addUse(Src1)
6355 .addImm(
MI.getOperand(4).getImm())
6356 .addImm(
MI.getOperand(5).getImm())
6357 .addImm(
MI.getOperand(6).getImm())
6358 .addImm(
MI.getOperand(7).getImm())
6368 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6369 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6370 IsPermlaneShuffle) {
6371 Src1 =
MI.getOperand(3).getReg();
6372 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6373 IsPermlaneShuffle) {
6374 Src2 =
MI.getOperand(4).getReg();
6378 LLT Ty =
MRI.getType(DstReg);
6379 unsigned Size = Ty.getSizeInBits();
6381 unsigned SplitSize = 32;
6382 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6383 ST.hasDPALU_DPP() &&
6387 if (
Size == SplitSize) {
6394 bool IsFloat = Ty.getScalarType().isFloat();
6398 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6399 if (Src1 &&
MRI.getType(Src1).getScalarType().isFloat())
6400 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6401 if (Src2 &&
MRI.getType(Src2).getScalarType().isFloat())
6402 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6406 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6408 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6409 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6411 if (IID == Intrinsic::amdgcn_writelane)
6412 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6414 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6416 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6418 B.buildTrunc(DstReg, LaneOpDst);
6419 MI.eraseFromParent();
6423 if (
Size % SplitSize != 0)
6427 bool NeedsBitcast =
false;
6428 if (IntTy.isVector()) {
6431 if (EltSize == SplitSize) {
6432 PartialResTy = EltTy;
6433 }
else if (EltSize == 16 || EltSize == 32) {
6434 unsigned NElem = SplitSize / EltSize;
6437 NeedsBitcast =
true;
6442 unsigned NumParts =
Size / SplitSize;
6446 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6447 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6449 if (IID == Intrinsic::amdgcn_writelane)
6450 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6452 for (
unsigned i = 0; i < NumParts; ++i) {
6453 Src0 = Src0Parts.
getReg(i);
6455 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6456 Src1 = Src1Parts.
getReg(i);
6458 if (IID == Intrinsic::amdgcn_writelane)
6459 Src2 = Src2Parts.
getReg(i);
6461 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6464 if (NeedsBitcast || IsFloat)
6467 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6469 B.buildMergeLikeInstr(DstReg, PartialRes);
6471 MI.eraseFromParent();
6479 ST.getTargetLowering()->getImplicitParameterOffset(
6481 LLT DstTy =
MRI.getType(DstReg);
6484 Register KernargPtrReg =
MRI.createGenericVirtualRegister(DstTy);
6489 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6490 B.buildConstant(IdxTy,
Offset).getReg(0));
6501 Register Pointer =
MI.getOperand(2).getReg();
6503 Register NumRecords =
MI.getOperand(4).getReg();
6509 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6511 auto ExtStride =
B.buildAnyExt(I32, Stride);
6513 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6514 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6516 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6518 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6522 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6523 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6524 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6525 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6529 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6530 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6531 auto ExtShiftedStride =
6532 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6533 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6534 auto ExtShiftedFlags =
6535 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6536 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6538 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6539 B.buildMergeValues(Result, {LowHalf, HighHalf});
6541 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6542 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6543 auto LowHalf = Unmerge.getReg(0);
6544 auto HighHalf = Unmerge.getReg(1);
6546 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6547 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6548 auto ShiftConst =
B.buildConstant(I32, 16);
6549 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6550 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6551 Register NewHighHalfReg = NewHighHalf.getReg(0);
6552 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6555 MI.eraseFromParent();
6572 MI.eraseFromParent();
6579 unsigned AddrSpace)
const {
6581 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6585 ST.hasGloballyAddressableScratch()) {
6587 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6588 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6590 MRI.setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6592 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6594 B.buildConstant(I32, 1u << 26));
6599 MI.eraseFromParent();
6609std::pair<Register, unsigned>
6621 bool CheckNUW = ST.hasGFX1250Insts();
6623 MRI, OrigOffset,
nullptr, CheckNUW);
6626 if (
MRI.getType(BaseReg).isPointer())
6627 BaseReg =
B.buildPtrToInt(
MRI.getType(OrigOffset), BaseReg).getReg(0);
6637 unsigned Overflow = ImmOffset & ~MaxImm;
6638 ImmOffset -= Overflow;
6639 if ((int32_t)Overflow < 0) {
6640 Overflow += ImmOffset;
6644 if (Overflow != 0) {
6646 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6648 auto OverflowVal =
B.buildConstant(I32, Overflow);
6649 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6654 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6656 return std::pair(BaseReg, ImmOffset);
6663 bool ImageStore)
const {
6666 LLT StoreVT =
MRI.getType(Reg);
6671 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6673 if (ST.hasUnpackedD16VMem()) {
6674 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6677 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6678 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6686 if (ImageStore && ST.hasImageStoreD16Bug()) {
6689 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6691 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6698 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6699 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6701 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6709 auto Unmerge =
B.buildUnmerge(I32, Reg);
6710 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6712 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6722 Reg =
B.buildPadVectorWithUndefElements(
6731 bool IsFormat)
const {
6733 LLT Ty =
MRI->getType(VData);
6741 VData =
B.buildBitcast(Ty, VData).getReg(0);
6743 if (Ty.isFloat(16)) {
6745 VData =
B.buildBitcast(Ty, VData).getReg(0);
6752 if (Ty.isVector()) {
6753 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6765 bool IsFormat)
const {
6770 LLT Ty =
MRI.getType(VData);
6772 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6779 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6780 const Function &Fn =
B.getMF().getFunction();
6782 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6783 MI.eraseFromParent();
6795 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6798 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6802 VIndex =
MI.getOperand(3).getReg();
6805 VIndex =
B.buildConstant(I32, 0).getReg(0);
6808 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6809 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6813 Format =
MI.getOperand(5 + OpOffset).getImm();
6817 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6823 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6824 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6825 }
else if (IsFormat) {
6826 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6827 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6831 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6834 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6837 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6842 auto MIB =
B.buildInstr(
Opc)
6853 MIB.addImm(AuxiliaryData)
6854 .addImm(HasVIndex ? -1 : 0)
6855 .addMemOperand(MMO);
6857 MI.eraseFromParent();
6863 unsigned ImmOffset,
unsigned Format,
6866 auto MIB =
B.buildInstr(
Opc)
6877 MIB.addImm(AuxiliaryData)
6878 .addImm(HasVIndex ? -1 : 0)
6879 .addMemOperand(MMO);
6885 Register SOffset,
unsigned ImmOffset,
6886 unsigned Format,
unsigned AuxiliaryData,
6890 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6892 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6895 B.buildUnmerge(Unmerge, LoadDstReg);
6901 bool IsTyped)
const {
6915 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6916 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6918 StatusDst =
MI.getOperand(1).getReg();
6923 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6926 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6929 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6932 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6935 VIndex =
B.buildConstant(I32, 0).getReg(0);
6938 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6939 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6943 Format =
MI.getOperand(5 + OpOffset).getImm();
6947 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6950 LLT Ty =
MRI.getType(Dst);
6957 Dst =
MI.getOperand(0).getReg();
6958 B.setInsertPt(
B.getMBB(),
MI);
6965 Dst =
MI.getOperand(0).getReg();
6966 B.setInsertPt(
B.getMBB(),
MI);
6970 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6971 const bool Unpacked = ST.hasUnpackedD16VMem();
6973 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6974 const Function &Fn =
B.getMF().getFunction();
6976 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6979 B.buildUndef(StatusDst);
6980 MI.eraseFromParent();
6984 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6985 const Function &Fn =
B.getMF().getFunction();
6987 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6990 B.buildUndef(StatusDst);
6991 MI.eraseFromParent();
7003 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
7004 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
7005 }
else if (IsFormat) {
7007 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
7008 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
7010 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
7011 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
7016 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
7017 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7020 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7021 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7024 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7025 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7030 if (IsTFE && IsD16 && Ty.isVector()) {
7032 const unsigned NumElts = Ty.getNumElements();
7033 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7036 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7037 ValueDWords.
push_back(
MRI.createGenericVirtualRegister(I32));
7039 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7044 R =
B.buildTrunc(EltTy, R).getReg(0);
7045 B.buildMergeLikeInstr(Dst, ValueDWords);
7054 if (PackedTy == Ty) {
7055 B.buildBitcast(Dst, Merged);
7057 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7058 B.buildDeleteTrailingVectorElements(Dst, Packed);
7062 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7064 EltTy.
isFloat() ?
MRI.createGenericVirtualRegister(Ty.changeElementType(
7068 Register ExtDst =
MRI.createGenericVirtualRegister(I32);
7070 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7072 B.buildTrunc(DstInt, ExtDst);
7073 }
else if (NumValueDWords == 1) {
7075 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7079 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7080 ValueDWords.
push_back(
MRI.createGenericVirtualRegister(I32));
7082 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7083 IsTyped, HasVIndex,
B);
7084 B.buildMergeLikeInstr(DstInt, ValueDWords);
7087 B.buildBitcast(Dst, DstInt);
7089 (IsD16 && !Ty.isVector())) {
7090 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7092 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7093 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7094 B.buildTrunc(Dst, LoadDstReg);
7095 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7097 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7099 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7100 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7102 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7104 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7105 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7106 B.buildMergeLikeInstr(Dst, Repack);
7109 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7112 MI.eraseFromParent();
7118 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7119 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7120 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7121 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7122 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7123 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7124 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7125 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7126 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7127 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7128 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7129 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7130 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7131 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7132 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7133 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7135 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7136 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7137 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7138 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7139 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7140 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7141 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7142 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7143 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7144 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7145 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7146 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7147 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7148 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7150 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7151 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7152 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7153 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7154 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7155 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7156 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7157 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7158 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7159 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7160 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7162 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7163 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7164 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7165 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7166 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7167 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7168 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7169 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7170 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7172 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7173 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7174 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7175 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7176 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7177 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7178 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7179 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7180 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7181 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7182 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7183 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7185 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7186 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7187 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7188 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7189 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7190 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7191 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7192 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7193 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7194 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7195 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7196 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7197 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7198 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7199 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7200 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7201 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7202 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7203 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7204 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7205 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7206 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7207 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7216 const bool IsCmpSwap =
7217 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7218 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7219 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7220 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7231 CmpVal =
MI.getOperand(3).getReg();
7236 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7237 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7240 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7243 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7249 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7250 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7251 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7270 .addImm(AuxiliaryData)
7271 .addImm(HasVIndex ? -1 : 0)
7272 .addMemOperand(MMO);
7274 MI.eraseFromParent();
7284 bool IsA16,
bool IsG16) {
7298 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7303 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7307 "Bias needs to be converted to 16 bit in A16 mode");
7309 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7313 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7317 if (((
I + 1) >= EndIdx) ||
7324 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7326 B.buildBuildVector(V2EltTy,
7327 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7332 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7343 int DimIdx,
int NumVAddrs) {
7345 for (
int I = 0;
I != NumVAddrs; ++
I) {
7347 if (
SrcOp.isReg()) {
7350 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7351 if (
B.getMRI()->getType(
Reg) != I32)
7352 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7357 int NumAddrRegs = AddrRegs.
size();
7358 if (NumAddrRegs != 1) {
7359 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7362 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7365 for (
int I = 1;
I != NumVAddrs; ++
I) {
7368 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7390 const unsigned NumDefs =
MI.getNumExplicitDefs();
7391 const unsigned ArgOffset = NumDefs + 1;
7392 bool IsTFE = NumDefs == 2;
7410 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7411 Ty =
MRI->getType(VData);
7414 const bool IsAtomicPacked16Bit =
7415 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7416 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7423 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7424 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7425 const bool DataTyIs16 =
7426 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7428 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7429 const bool IsA16 = AddrTyIs16;
7430 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7433 if (!BaseOpcode->
Atomic) {
7434 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7437 }
else if (DMask != 0) {
7439 }
else if (!IsTFE && !BaseOpcode->
Store) {
7441 B.buildUndef(
MI.getOperand(0));
7442 MI.eraseFromParent();
7450 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7451 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7452 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7453 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7454 unsigned NewOpcode = LoadOpcode;
7455 if (BaseOpcode->
Store)
7456 NewOpcode = StoreOpcode;
7458 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7461 MI.setDesc(
B.getTII().get(NewOpcode));
7465 if (IsTFE && DMask == 0) {
7468 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7471 if (BaseOpcode->
Atomic) {
7473 LLT Ty =
MRI->getType(VData0);
7476 if (Ty.isVector() && !IsAtomicPacked16Bit)
7483 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7484 MI.getOperand(2).setReg(
Concat.getReg(0));
7485 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7489 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7492 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7498 if (IsA16 && !ST.hasA16()) {
7503 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7504 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7506 if (IsA16 || IsG16) {
7514 const bool UseNSA = ST.hasNSAEncoding() &&
7515 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7516 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7517 const bool UsePartialNSA =
7518 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7520 if (UsePartialNSA) {
7524 auto Concat =
B.buildConcatVectors(
7525 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7526 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7527 PackedRegs.
resize(NSAMaxSize);
7528 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7530 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7531 PackedRegs[0] =
Concat.getReg(0);
7535 const unsigned NumPacked = PackedRegs.
size();
7538 if (!
SrcOp.isReg()) {
7548 SrcOp.setReg(AMDGPU::NoRegister);
7565 const bool UseNSA = ST.hasNSAEncoding() &&
7566 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7567 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7568 const bool UsePartialNSA =
7569 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7571 if (UsePartialNSA) {
7573 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7575 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7590 if (!Ty.isVector() || !IsD16)
7594 if (RepackedReg != VData) {
7595 MI.getOperand(1).setReg(RepackedReg);
7603 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7606 if (NumElts < DMaskLanes)
7609 if (NumElts > 4 || DMaskLanes > 4)
7620 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7621 const LLT AdjustedTy =
7637 if (IsD16 && ST.hasUnpackedD16VMem()) {
7644 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7645 unsigned RoundedSize = 32 * RoundedElts;
7649 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7654 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7660 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7664 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7665 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7667 Register NewResultReg =
MRI->createGenericVirtualRegister(LoadResultTy);
7669 MI.getOperand(0).setReg(NewResultReg);
7677 Dst1Reg =
MI.getOperand(1).getReg();
7678 if (
MRI->getType(Dst1Reg) != I32)
7682 MI.removeOperand(1);
7685 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7686 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7687 B.buildBitcast(DstReg, Unmerge.getReg(0));
7688 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7697 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7699 if (ResultNumRegs == 1) {
7701 ResultRegs[0] = NewResultReg;
7704 for (
int I = 0;
I != NumDataRegs; ++
I)
7705 ResultRegs[
I] =
MRI->createGenericVirtualRegister(RegTy);
7706 B.buildUnmerge(ResultRegs, NewResultReg);
7711 ResultRegs.
resize(NumDataRegs);
7716 if (IsD16 && !Ty.isVector()) {
7717 B.buildTrunc(DstReg, ResultRegs[0]);
7722 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7723 !ST.hasUnpackedD16VMem()) {
7724 B.buildBitcast(DstReg, ResultRegs[0]);
7736 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7738 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7739 }
else if (ST.hasUnpackedD16VMem()) {
7741 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7745 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7749 for (
int I = 0;
I != NumElts; ++
I)
7754 LLT ResTy =
MRI->getType(ResultRegs[0]);
7756 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7757 B.buildBuildVector(DstReg, ResultRegs);
7761 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7762 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7767 if (Ty == V3I16 || Ty == V3F16) {
7769 if (ResultRegs.
size() == 1) {
7770 NewResultReg = ResultRegs[0];
7771 }
else if (ResultRegs.
size() == 2) {
7773 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7779 LLT DstTy =
MRI->getType(DstReg);
7780 LLT NewResTy =
MRI->getType(NewResultReg);
7784 :
MRI->createGenericVirtualRegister(
7788 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7790 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7792 if (ResizeDst != DstReg)
7793 B.buildBitcast(DstReg, ResizeDst);
7797 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7798 B.buildConcatVectors(DstReg, ResultRegs);
7807 Register OrigDst =
MI.getOperand(0).getReg();
7809 LLT Ty =
B.getMRI()->getType(OrigDst);
7810 unsigned Size = Ty.getSizeInBits();
7812 bool HasMMO = !
MI.memoperands_empty();
7817 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7818 if (
Size % 32 != 0 && !IsSubwordLoad) {
7821 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7822 B.buildUndef(OrigDst);
7823 MI.eraseFromParent();
7828 if (IsSubwordLoad) {
7830 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7831 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7834 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7836 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7845 B.setInsertPt(
B.getMBB(),
MI);
7850 B.setInsertPt(
B.getMBB(),
MI);
7853 MI.setDesc(
B.getTII().get(
Opc));
7854 MI.removeOperand(1);
7860 const unsigned MemSize = (
Size + 7) / 8;
7861 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7868 MI.addMemOperand(MF, MMO);
7870 if (Dst != OrigDst) {
7871 MI.getOperand(0).setReg(Dst);
7872 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7873 B.buildTrunc(OrigDst, Dst);
7895 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7896 MI.removeOperand(0);
7907 if (!ST.hasTrapHandler() ||
7926 MI.eraseFromParent();
7938 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7947 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7949 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7953 MI.eraseFromParent();
7962 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7969 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7971 Register KernargPtrReg =
MRI.createGenericVirtualRegister(
7987 Register LoadAddr =
MRI.createGenericVirtualRegister(
7989 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7992 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7993 B.buildCopy(SGPR01, Temp);
7994 B.buildInstr(AMDGPU::S_TRAP)
7997 MI.eraseFromParent();
8008 B.buildCopy(SGPR01, LiveIn);
8009 B.buildInstr(AMDGPU::S_TRAP)
8013 MI.eraseFromParent();
8024 if (ST.hasPrivEnabledTrap2NopBug()) {
8036 ST.getInstrInfo()->insertSimulatedTrap(
MRI,
MBB,
MI,
MI.getDebugLoc());
8039 MI.eraseFromParent();
8043 B.buildInstr(AMDGPU::S_TRAP)
8045 MI.eraseFromParent();
8054 if (!ST.hasTrapHandler() ||
8058 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8061 B.buildInstr(AMDGPU::S_TRAP)
8065 MI.eraseFromParent();
8079 Register NodePtr =
MI.getOperand(2).getReg();
8080 Register RayExtent =
MI.getOperand(3).getReg();
8081 Register RayOrigin =
MI.getOperand(4).getReg();
8083 Register RayInvDir =
MI.getOperand(6).getReg();
8086 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8091 const bool IsA16 =
MRI.getType(RayDir).getElementType().getSizeInBits() == 16;
8092 const bool Is64 =
MRI.getType(NodePtr).getSizeInBits() == 64;
8093 const unsigned NumVDataDwords = 4;
8094 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8095 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8097 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8099 const unsigned BaseOpcodes[2][2] = {
8100 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8101 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8102 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8106 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8107 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8108 : AMDGPU::MIMGEncGfx10NSA,
8109 NumVDataDwords, NumVAddrDwords);
8113 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8114 : AMDGPU::MIMGEncGfx10Default,
8115 NumVDataDwords, NumVAddrDwords);
8120 if (UseNSA && IsGFX11Plus) {
8121 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8122 auto SrcInt =
B.buildBitcast(V3I32, Src);
8123 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8124 auto Merged =
B.buildMergeLikeInstr(
8125 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8126 Ops.push_back(Merged.getReg(0));
8129 Ops.push_back(NodePtr);
8130 Ops.push_back(RayExtent);
8131 packLanes(RayOrigin);
8134 auto UnmergeRayDir =
8135 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8136 auto UnmergeRayInvDir =
8137 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8138 auto MergedDir =
B.buildMergeLikeInstr(
8141 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8142 UnmergeRayDir.getReg(0)}))
8145 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8146 UnmergeRayDir.getReg(1)}))
8149 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8150 UnmergeRayDir.getReg(2)}))
8152 Ops.push_back(MergedDir.getReg(0));
8155 packLanes(RayInvDir);
8159 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8160 Ops.push_back(Unmerge.getReg(0));
8161 Ops.push_back(Unmerge.getReg(1));
8163 Ops.push_back(NodePtr);
8165 Ops.push_back(RayExtent);
8167 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8168 auto SrcInt =
B.buildBitcast(V3I32, Src);
8169 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8170 Ops.push_back(Unmerge.getReg(0));
8171 Ops.push_back(Unmerge.getReg(1));
8172 Ops.push_back(Unmerge.getReg(2));
8175 packLanes(RayOrigin);
8177 auto UnmergeRayDir =
8178 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8179 auto UnmergeRayInvDir =
8180 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8181 Register R1 =
MRI.createGenericVirtualRegister(I32);
8183 Register R3 =
MRI.createGenericVirtualRegister(I32);
8184 B.buildMergeLikeInstr(R1,
8185 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8186 B.buildMergeLikeInstr(
8187 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8188 B.buildMergeLikeInstr(
8189 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8195 packLanes(RayInvDir);
8204 Ops.push_back(MergedOps);
8207 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8216 .addImm(IsA16 ? 1 : 0)
8219 MI.eraseFromParent();
8229 Register DstOrigin =
MI.getOperand(1).getReg();
8231 Register NodePtr =
MI.getOperand(4).getReg();
8232 Register RayExtent =
MI.getOperand(5).getReg();
8233 Register InstanceMask =
MI.getOperand(6).getReg();
8234 Register RayOrigin =
MI.getOperand(7).getReg();
8236 Register Offsets =
MI.getOperand(9).getReg();
8237 Register TDescr =
MI.getOperand(10).getReg();
8240 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8241 const unsigned NumVDataDwords = 10;
8242 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8244 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8245 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8246 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8249 auto RayExtentInstanceMaskVec =
8250 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8251 B.buildAnyExt(I32, InstanceMask)});
8253 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8254 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8260 .addUse(RayExtentInstanceMaskVec.getReg(0))
8267 MI.eraseFromParent();
8276 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8277 MI.eraseFromParent();
8284 if (!ST.hasArchitectedSGPRs())
8288 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8289 auto LSB =
B.buildConstant(I32, 25);
8290 auto Width =
B.buildConstant(I32, 5);
8291 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8292 MI.eraseFromParent();
8300 unsigned Width)
const {
8304 {&AMDGPU::SReg_32RegClass,
MRI.getType(DstReg)});
8305 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8308 B.buildCopy(DstReg, Result);
8309 MI.eraseFromParent();
8325 if (
MRI.getType(Src) != I64)
8329 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8333 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8336 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8337 MI.eraseFromParent();
8347 if (
MRI.getType(Src) != I64)
8350 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8354 .addReg(Unmerge.getReg(0));
8358 .addReg(Unmerge.getReg(1));
8359 MI.eraseFromParent();
8371 case Intrinsic::sponentry:
8376 Register TmpReg =
MRI.createGenericVirtualRegister(I32);
8377 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8380 B.buildIntToPtr(DstReg, TmpReg);
8381 MI.eraseFromParent();
8383 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8385 B.buildFrameIndex(
MI.getOperand(0), FI);
8386 MI.eraseFromParent();
8389 case Intrinsic::amdgcn_if:
8390 case Intrinsic::amdgcn_else: {
8393 bool Negated =
false;
8403 MRI.createVirtualRegister({WaveMaskRC,
MRI.getType(Def)});
8405 MRI.createVirtualRegister({WaveMaskRC,
MRI.getType(
Use)});
8410 std::swap(CondBrTarget, UncondBrTarget);
8412 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8413 B.buildCopy(NewUse,
Use);
8414 if (IntrID == Intrinsic::amdgcn_if) {
8415 B.buildInstr(AMDGPU::SI_IF)
8418 .addMBB(UncondBrTarget)
8421 B.buildInstr(AMDGPU::SI_ELSE)
8424 .addMBB(UncondBrTarget)
8434 B.buildBr(*CondBrTarget);
8437 MI.eraseFromParent();
8438 BrCond->eraseFromParent();
8442 MRI.replaceRegWith(Def, NewDef);
8449 case Intrinsic::amdgcn_loop: {
8452 bool Negated =
false;
8461 {
TRI->getWaveMaskRegClass(),
MRI.getType(Reg)});
8464 std::swap(CondBrTarget, UncondBrTarget);
8466 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8467 B.buildCopy(NewReg, Reg);
8468 B.buildInstr(AMDGPU::SI_LOOP)
8470 .addMBB(UncondBrTarget)
8476 B.buildBr(*CondBrTarget);
8478 MI.eraseFromParent();
8479 BrCond->eraseFromParent();
8485 case Intrinsic::amdgcn_wave_reduce_min:
8486 case Intrinsic::amdgcn_wave_reduce_umin:
8487 case Intrinsic::amdgcn_wave_reduce_fmin:
8488 case Intrinsic::amdgcn_wave_reduce_max:
8489 case Intrinsic::amdgcn_wave_reduce_umax:
8490 case Intrinsic::amdgcn_wave_reduce_fmax:
8491 case Intrinsic::amdgcn_wave_reduce_add:
8492 case Intrinsic::amdgcn_wave_reduce_fadd:
8493 case Intrinsic::amdgcn_wave_reduce_sub:
8494 case Intrinsic::amdgcn_wave_reduce_fsub:
8495 case Intrinsic::amdgcn_wave_reduce_and:
8496 case Intrinsic::amdgcn_wave_reduce_or:
8497 case Intrinsic::amdgcn_wave_reduce_xor: {
8499 if (
MRI.getType(SrcReg).getSizeInBits() != 16)
8502 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8503 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8504 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8505 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8506 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8507 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8508 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8509 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8510 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8517 .addUse(Ext.getReg(0))
8518 .addImm(
MI.getOperand(3).getImm());
8520 B.buildFPTrunc(DstReg, NewDst);
8522 B.buildTrunc(DstReg, NewDst);
8523 MI.eraseFromParent();
8526 case Intrinsic::amdgcn_make_buffer_rsrc:
8528 case Intrinsic::amdgcn_kernarg_segment_ptr:
8531 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8532 MI.eraseFromParent();
8538 case Intrinsic::amdgcn_implicitarg_ptr:
8540 case Intrinsic::amdgcn_workitem_id_x:
8543 case Intrinsic::amdgcn_workitem_id_y:
8546 case Intrinsic::amdgcn_workitem_id_z:
8549 case Intrinsic::amdgcn_workgroup_id_x:
8554 case Intrinsic::amdgcn_workgroup_id_y:
8559 case Intrinsic::amdgcn_workgroup_id_z:
8564 case Intrinsic::amdgcn_cluster_id_x:
8565 return ST.hasClusters() &&
8568 case Intrinsic::amdgcn_cluster_id_y:
8569 return ST.hasClusters() &&
8572 case Intrinsic::amdgcn_cluster_id_z:
8573 return ST.hasClusters() &&
8576 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8577 return ST.hasClusters() &&
8580 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8581 return ST.hasClusters() &&
8584 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8585 return ST.hasClusters() &&
8588 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8589 return ST.hasClusters() &&
8591 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8592 return ST.hasClusters() &&
8595 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8596 return ST.hasClusters() &&
8599 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8600 return ST.hasClusters() &&
8603 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8604 return ST.hasClusters() &&
8608 case Intrinsic::amdgcn_wave_id:
8610 case Intrinsic::amdgcn_lds_kernel_id:
8613 case Intrinsic::amdgcn_dispatch_ptr:
8616 case Intrinsic::amdgcn_queue_ptr:
8619 case Intrinsic::amdgcn_implicit_buffer_ptr: {
8620 const Function &Fn =
B.getMF().getFunction();
8625 ST.hasArchitectedFlatScratch()
8626 ?
"intrinsic not supported on subtarget"
8627 : !ST.isMesa3DOS() ?
"intrinsic not supported for OS"
8628 :
"intrinsic not supported for calling convention";
8631 B.buildUndef(
MI.getOperand(0).getReg());
8632 MI.eraseFromParent();
8638 case Intrinsic::amdgcn_dispatch_id:
8641 case Intrinsic::r600_read_ngroups_x:
8645 case Intrinsic::r600_read_ngroups_y:
8648 case Intrinsic::r600_read_ngroups_z:
8651 case Intrinsic::r600_read_local_size_x:
8654 case Intrinsic::r600_read_local_size_y:
8658 case Intrinsic::r600_read_local_size_z:
8661 case Intrinsic::amdgcn_fdiv_fast:
8663 case Intrinsic::amdgcn_is_shared:
8665 case Intrinsic::amdgcn_is_private:
8667 case Intrinsic::amdgcn_wavefrontsize: {
8668 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8669 MI.eraseFromParent();
8672 case Intrinsic::amdgcn_s_buffer_load:
8673 case Intrinsic::amdgcn_ptr_s_buffer_load:
8675 case Intrinsic::amdgcn_raw_buffer_store:
8676 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8677 case Intrinsic::amdgcn_struct_buffer_store:
8678 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8680 case Intrinsic::amdgcn_raw_buffer_store_format:
8681 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8682 case Intrinsic::amdgcn_struct_buffer_store_format:
8683 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8685 case Intrinsic::amdgcn_raw_tbuffer_store:
8686 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8687 case Intrinsic::amdgcn_struct_tbuffer_store:
8688 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8690 case Intrinsic::amdgcn_raw_buffer_load:
8691 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8692 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8693 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8694 case Intrinsic::amdgcn_struct_buffer_load:
8695 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8696 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8697 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8699 case Intrinsic::amdgcn_raw_buffer_load_format:
8700 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8701 case Intrinsic::amdgcn_struct_buffer_load_format:
8702 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8704 case Intrinsic::amdgcn_raw_tbuffer_load:
8705 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8706 case Intrinsic::amdgcn_struct_tbuffer_load:
8707 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8709 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8710 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8711 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8712 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8713 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8714 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8715 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8716 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8717 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8718 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8719 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8720 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8721 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8722 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8723 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8724 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8725 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8726 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8727 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8728 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8729 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8730 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8731 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8732 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8733 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8734 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8735 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8736 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8737 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8738 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8739 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8740 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8741 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8742 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8743 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8744 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8745 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8746 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8747 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8748 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8749 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8750 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8751 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8752 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8753 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8754 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8755 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8756 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8757 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8758 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8759 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8760 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8761 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8762 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8763 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8764 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8765 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8766 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8767 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8768 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8769 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8770 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8771 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8772 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8773 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8774 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8775 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8776 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8777 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8778 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8779 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8780 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8782 case Intrinsic::amdgcn_rsq_clamp:
8784 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8786 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8787 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8789 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8790 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8791 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8792 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8793 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8794 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8795 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8796 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8799 LLT IndexArgTy =
MRI.getType(Index);
8800 if (IndexArgTy != I64) {
8801 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8802 :
B.buildAnyExt(I64, Index);
8803 MI.getOperand(5).setReg(NewIndex.getReg(0));
8807 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8808 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8809 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8810 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8811 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8812 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8813 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8814 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8817 if (
MRI.getType(Index) != I32)
8818 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8821 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8822 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8823 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8824 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8825 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8826 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8827 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8828 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8829 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8831 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8834 LLT IndexArgTy =
MRI.getType(Index);
8835 if (IndexArgTy != IdxTy) {
8836 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8837 :
B.buildAnyExt(IdxTy, Index);
8838 MI.getOperand(7).setReg(NewIndex.getReg(0));
8843 case Intrinsic::amdgcn_fmed3: {
8849 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8850 MI.removeOperand(1);
8854 case Intrinsic::amdgcn_readlane:
8855 case Intrinsic::amdgcn_writelane:
8856 case Intrinsic::amdgcn_readfirstlane:
8857 case Intrinsic::amdgcn_permlane16:
8858 case Intrinsic::amdgcn_permlanex16:
8859 case Intrinsic::amdgcn_permlane64:
8860 case Intrinsic::amdgcn_set_inactive:
8861 case Intrinsic::amdgcn_set_inactive_chain_arg:
8862 case Intrinsic::amdgcn_mov_dpp8:
8863 case Intrinsic::amdgcn_update_dpp:
8864 case Intrinsic::amdgcn_permlane_bcast:
8865 case Intrinsic::amdgcn_permlane_up:
8866 case Intrinsic::amdgcn_permlane_down:
8867 case Intrinsic::amdgcn_permlane_xor:
8869 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8871 case Intrinsic::amdgcn_dead: {
8875 MI.eraseFromParent();
8878 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8879 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8880 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8881 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8882 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8883 MI.eraseFromParent();
8885 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8886 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8887 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8888 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8889 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8890 MI.eraseFromParent();
8892 case Intrinsic::amdgcn_av_load_b128:
8893 case Intrinsic::amdgcn_av_store_b128: {
8894 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8895 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8896 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8898 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8899 **
MI.memoperands_begin());
8900 MI.eraseFromParent();
8903 case Intrinsic::amdgcn_flat_load_monitor_b32:
8904 case Intrinsic::amdgcn_flat_load_monitor_b64:
8905 case Intrinsic::amdgcn_flat_load_monitor_b128:
8906 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8907 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8908 .add(
MI.getOperand(0))
8909 .add(
MI.getOperand(2))
8910 .addMemOperand(*
MI.memoperands_begin());
8911 MI.eraseFromParent();
8913 case Intrinsic::amdgcn_global_load_monitor_b32:
8914 case Intrinsic::amdgcn_global_load_monitor_b64:
8915 case Intrinsic::amdgcn_global_load_monitor_b128:
8916 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8917 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8918 .add(
MI.getOperand(0))
8919 .add(
MI.getOperand(2))
8920 .addMemOperand(*
MI.memoperands_begin());
8921 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
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 unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static void buildTFEBufferLoad(unsigned Opc, ArrayRef< Register > ValueDsts, Register StatusDst, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
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.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeTrapHsa(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Lightweight error class with error context and mandatory checking.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasImplicitBufferPtr() const
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() 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.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
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.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
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.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
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.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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...
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
GCNUserSGPRUsageInfo & getUserSGPRInfo()
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ 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.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
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 has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
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...
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
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
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
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
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.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.