37#include "llvm/IR/IntrinsicsAMDGPU.h"
38#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];
376 if (Ty.isPointerOrPointerVector())
377 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
381 (ST.useRealTrue16Insts() && Ty ==
S16) ||
396 const LLT Ty = Query.Types[TypeIdx];
397 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
398 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
406 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
416 bool IsLoad,
bool IsAtomic) {
420 return ST.hasFlatScratchEnabled() ? 128 : 32;
422 return ST.useDS128() ? 128 : 64;
433 return IsLoad ? 512 : 128;
438 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
447 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
449 unsigned RegSize = Ty.getSizeInBits();
452 unsigned AS = Query.
Types[1].getAddressSpace();
459 if (Ty.isVector() && MemSize !=
RegSize)
466 if (IsLoad && MemSize <
Size)
467 MemSize = std::max(MemSize,
Align);
487 if (!ST.hasDwordx3LoadStores())
500 if (AlignBits < MemSize) {
503 Align(AlignBits / 8)))
533 const unsigned Size = Ty.getSizeInBits();
534 if (Ty.isPointerVector())
544 unsigned EltSize = Ty.getScalarSizeInBits();
545 return EltSize != 32 && EltSize != 64;
559 const unsigned Size = Ty.getSizeInBits();
560 if (
Size != MemSizeInBits)
561 return Size <= 32 && Ty.isVector();
567 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
576 uint64_t AlignInBits,
unsigned AddrSpace,
586 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
597 if (AlignInBits < RoundedSize)
604 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
616 Query.
Types[1].getAddressSpace(), Opcode);
636 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
640 std::array<Register, 4> VectorElems;
641 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
642 for (
unsigned I = 0;
I < NumParts; ++
I)
644 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
645 B.buildMergeValues(MO, VectorElems);
650 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
651 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
652 B.buildIntToPtr(MO, Scalar);
672 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
674 for (
unsigned I = 0;
I < NumParts; ++
I)
676 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
678 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
679 return B.buildBitcast(VectorTy, Scalar).getReg(0);
698 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
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 = {
730 const std::initializer_list<LLT> FPTypes16 = {
734 const std::initializer_list<LLT> FPTypesPK16 = {
738 const std::initializer_list<LLT> FPTypesPK16_64 = {
S32,
S64,
S16,
V2S16,
741 const LLT MinScalarFPTy = ST.has16BitInsts() ?
S16 :
S32;
764 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
766 if (ST.hasPackedU64Ops()) {
769 .clampMaxNumElementsStrict(0,
S16, 2)
775 }
else if (ST.hasScalarAddSub64()) {
778 .clampMaxNumElementsStrict(0,
S16, 2)
786 .clampMaxNumElementsStrict(0,
S16, 2)
793 if (ST.hasScalarSMulU64()) {
796 .clampMaxNumElementsStrict(0,
S16, 2)
804 .clampMaxNumElementsStrict(0,
S16, 2)
814 .minScalarOrElt(0,
S16)
819 }
else if (ST.has16BitInsts()) {
853 .widenScalarToNextMultipleOf(0, 32)
863 if (ST.hasMad64_32())
868 if (ST.hasIntClamp()) {
891 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
901 if (ST.hasVOP3PInsts()) {
903 .clampMaxNumElements(0,
S8, 2)
924 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
940 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
947 .clampScalar(0,
S16,
S64);
982 { G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE,
983 G_STRICT_FADD, G_STRICT_FMUL, G_STRICT_FMA})
990 if (ST.has16BitInsts()) {
991 if (ST.hasVOP3PInsts())
994 FPOpActions.legalFor({
S16});
996 TrigActions.customFor({
S16});
997 FDIVActions.customFor({
S16});
1000 if (ST.hasPackedFP32Ops()) {
1001 FPOpActions.legalFor({
V2S32});
1002 FPOpActions.clampMaxNumElementsStrict(0,
S32, 2);
1005 if (ST.hasPackedFP64Ops()) {
1006 FPOpActions.legalFor({
V2S64});
1007 FPOpActions.clampMaxNumElementsStrict(0,
S64, 2);
1010 if (ST.hasPackedFP64Ops()) {
1011 FPOpActions.legalFor({
V2S64});
1012 FPOpActions.clampMaxNumElementsStrict(0,
S64, 2);
1015 auto &MinNumMaxNumIeee =
1018 if (ST.hasVOP3PInsts()) {
1019 MinNumMaxNumIeee.legalFor(FPTypesPK16)
1021 .clampMaxNumElements(0,
S16, 2)
1022 .clampScalar(0,
S16,
S64)
1024 }
else if (ST.has16BitInsts()) {
1025 MinNumMaxNumIeee.legalFor(FPTypes16).clampScalar(0,
S16,
S64).scalarize(0);
1027 MinNumMaxNumIeee.legalFor(FPTypesBase)
1028 .clampScalar(0,
S32,
S64)
1033 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1035 if (ST.hasPackedFP64Ops()) {
1036 MinNumMaxNum.customFor(FPTypesPK16_64)
1038 .clampMaxNumElements(0,
S16, 2)
1039 .clampMaxNumElements(0,
S64, 2)
1040 .clampScalar(0,
S16,
S64)
1042 }
else if (ST.hasVOP3PInsts()) {
1043 MinNumMaxNum.customFor(FPTypesPK16)
1045 .clampMaxNumElements(0,
S16, 2)
1046 .clampScalar(0,
S16,
S64)
1048 }
else if (ST.has16BitInsts()) {
1049 MinNumMaxNum.customFor(FPTypes16)
1050 .clampScalar(0,
S16,
S64)
1053 MinNumMaxNum.customFor(FPTypesBase)
1054 .clampScalar(0,
S32,
S64)
1058 if (ST.hasVOP3PInsts())
1075 .
legalFor(ST.hasPackedFP32Ops(), {V2S32})
1077 if (ST.hasPackedFP32Ops())
1081 if (ST.has16BitInsts()) {
1115 if (ST.hasFractBug()) {
1149 if (ST.hasCvtPkF16F32Inst()) {
1151 .clampMaxNumElements(0,
S16, 2);
1155 FPTruncActions.scalarize(0).lower();
1164 if (ST.has16BitInsts()) {
1178 if (ST.hasPackedFP32Ops())
1188 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1189 FMad.customFor({
S32,
S16});
1190 else if (ST.hasMadMacF32Insts())
1191 FMad.customFor({
S32});
1192 else if (ST.hasMadF16())
1193 FMad.customFor({
S16});
1198 if (ST.has16BitInsts()) {
1201 FRem.minScalar(0,
S32)
1210 .clampMaxNumElements(0,
S16, 2)
1230 if (ST.has16BitInsts())
1242 if (ST.has16BitInsts())
1255 .legalFor(ST.has16BitInsts(), {{S16, S16}})
1256 .legalFor(ST.hasVCvtPkIU16F32(), {{V2S16, V2S32}})
1260 if (
ST.has16BitInsts())
1263 if (
ST.hasVCvtPkIU16F32())
1273 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1274 .clampScalar(0,
S16,
S64)
1278 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1284 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1288 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1289 .clampScalar(0,
S16,
S64)
1293 if (
ST.has16BitInsts()) {
1294 getActionDefinitionsBuilder(
1295 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1297 .clampScalar(0,
S16,
S64)
1300 getActionDefinitionsBuilder(
1301 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1303 .clampScalar(0,
S32,
S64)
1306 getActionDefinitionsBuilder(
1307 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1310 .clampScalar(0,
S32,
S64)
1314 getActionDefinitionsBuilder(G_PTR_ADD)
1320 getActionDefinitionsBuilder(G_PTRMASK)
1322 .scalarSameSizeAs(1, 0)
1326 getActionDefinitionsBuilder(G_ICMP)
1338 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1339 .legalForCartesianProduct(
1340 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1341 if (
ST.has16BitInsts()) {
1342 CmpBuilder.legalFor({{
S1,
S16}});
1353 {
S1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1355 if (
ST.hasSALUFloatInsts())
1364 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1365 if (
ST.has16BitInsts())
1366 ExpOps.customFor({{
S32}, {
S16}});
1368 ExpOps.customFor({
S32});
1369 ExpOps.clampScalar(0, MinScalarFPTy,
S32)
1372 getActionDefinitionsBuilder(G_FPOWI)
1373 .clampScalar(0, MinScalarFPTy,
S32)
1376 getActionDefinitionsBuilder(G_FLOG2)
1377 .legalFor(
ST.has16BitInsts(), {S16})
1382 getActionDefinitionsBuilder(G_FEXP2)
1383 .legalFor(
ST.has16BitInsts(), {S16})
1389 getActionDefinitionsBuilder({G_FLOG, G_FLOG10, G_FEXP, G_FEXP10});
1391 LogOps.clampScalar(0, MinScalarFPTy,
S32)
1395 getActionDefinitionsBuilder(G_CTPOP)
1397 .clampScalar(0,
S32,
S32)
1398 .widenScalarToNextPow2(1, 32)
1399 .clampScalar(1,
S32,
S64)
1401 .widenScalarToNextPow2(0, 32);
1404 if (
ST.has16BitInsts())
1405 getActionDefinitionsBuilder(G_IS_FPCLASS)
1406 .legalForCartesianProduct({
S1}, FPTypes16)
1407 .widenScalarToNextPow2(1)
1411 getActionDefinitionsBuilder(G_IS_FPCLASS)
1412 .legalForCartesianProduct({
S1}, FPTypesBase)
1413 .lowerFor({
S1,
S16})
1414 .widenScalarToNextPow2(1)
1421 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1423 .clampScalar(0,
S32,
S32)
1424 .clampScalar(1,
S32,
S64)
1425 .widenScalarToNextPow2(0, 32)
1426 .widenScalarToNextPow2(1, 32)
1430 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1433 .clampScalar(0,
S32,
S32)
1434 .clampScalar(1,
S32,
S64)
1436 .widenScalarToNextPow2(0, 32)
1437 .widenScalarToNextPow2(1, 32);
1439 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1441 .clampScalar(0,
S32,
S32)
1442 .clampScalar(1,
S32,
S64)
1444 .widenScalarToNextPow2(0, 32)
1445 .widenScalarToNextPow2(1, 32);
1447 getActionDefinitionsBuilder(G_CTLS)
1450 .clampScalar(0,
S32,
S32)
1451 .clampScalar(1,
S32,
S32);
1455 getActionDefinitionsBuilder(G_BITREVERSE)
1457 .clampScalar(0,
S32,
S64)
1459 .widenScalarToNextPow2(0);
1461 if (
ST.has16BitInsts()) {
1462 getActionDefinitionsBuilder(G_BSWAP)
1464 .clampMaxNumElementsStrict(0,
S16, 2)
1467 .widenScalarToNextPow2(0)
1468 .clampScalar(0,
S16,
S32)
1471 if (
ST.hasVOP3PInsts()) {
1472 getActionDefinitionsBuilder(G_ABS)
1474 .clampMaxNumElements(0,
S16, 2)
1476 .widenScalarToNextPow2(0)
1479 if (
ST.hasMinMaxI64Insts()) {
1480 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1482 .clampMaxNumElements(0,
S16, 2)
1484 .widenScalarToNextPow2(0)
1488 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1490 .clampMaxNumElements(0,
S16, 2)
1492 .widenScalarToNextPow2(0)
1497 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1499 .widenScalarToNextPow2(0)
1506 getActionDefinitionsBuilder(G_BSWAP)
1511 .widenScalarToNextPow2(0)
1516 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1519 .widenScalarToNextPow2(0)
1524 getActionDefinitionsBuilder(G_INTTOPTR)
1526 .legalForCartesianProduct(AddrSpaces64, {
S64})
1527 .legalForCartesianProduct(AddrSpaces32, {
S32})
1540 getActionDefinitionsBuilder(G_PTRTOINT)
1542 .legalForCartesianProduct(AddrSpaces64, {
S64})
1543 .legalForCartesianProduct(AddrSpaces32, {
S32})
1556 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1560 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1561 bool IsLoad) ->
bool {
1565 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1579 unsigned NumRegs = (MemSize + 31) / 32;
1581 if (!
ST.hasDwordx3LoadStores())
1592 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1593 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1594 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1600 for (
unsigned Op : {G_LOAD, G_STORE}) {
1601 const bool IsStore =
Op == G_STORE;
1603 auto &Actions = getActionDefinitionsBuilder(
Op);
1606 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1609 {
S64, GlobalPtr,
S64, GlobalAlign32},
1612 {
S32, GlobalPtr,
S8, GlobalAlign8},
1613 {
S32, GlobalPtr,
S16, GlobalAlign16},
1615 {
S32, LocalPtr,
S32, 32},
1616 {
S64, LocalPtr,
S64, 32},
1618 {
S32, LocalPtr,
S8, 8},
1619 {
S32, LocalPtr,
S16, 16},
1622 {
S32, PrivatePtr,
S32, 32},
1623 {
S32, PrivatePtr,
S8, 8},
1624 {
S32, PrivatePtr,
S16, 16},
1627 {
S32, ConstantPtr,
S32, GlobalAlign32},
1630 {
S64, ConstantPtr,
S64, GlobalAlign32},
1631 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1633 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1634 {{S16, GlobalPtr, S8, GlobalAlign8},
1635 {S16, GlobalPtr, S16, GlobalAlign16},
1636 {S16, LocalPtr, S8, 8},
1637 {S16, LocalPtr, S16, 16},
1638 {S16, PrivatePtr, S8, 8},
1639 {S16, PrivatePtr, S16, 16}});
1649 Actions.unsupportedIf(
1650 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1664 Actions.customIf(
typeIs(1, Constant32Ptr));
1690 return !Query.
Types[0].isVector() &&
1691 needToSplitMemOp(Query,
Op == G_LOAD);
1693 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1698 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1701 if (DstSize > MemSize)
1707 if (MemSize > MaxSize)
1715 return Query.
Types[0].isVector() &&
1716 needToSplitMemOp(Query,
Op == G_LOAD);
1718 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1732 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1733 if (MemSize > MaxSize) {
1737 if (MaxSize % EltSize == 0) {
1743 unsigned NumPieces = MemSize / MaxSize;
1747 if (NumPieces == 1 || NumPieces >= NumElts ||
1748 NumElts % NumPieces != 0)
1749 return std::pair(0, EltTy);
1757 return std::pair(0, EltTy);
1772 return std::pair(0, EltTy);
1777 .widenScalarToNextPow2(0)
1784 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1785 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1786 {
S32, GlobalPtr,
S16, 2 * 8},
1787 {
S32, LocalPtr,
S8, 8},
1788 {
S32, LocalPtr,
S16, 16},
1789 {
S32, PrivatePtr,
S8, 8},
1790 {
S32, PrivatePtr,
S16, 16},
1791 {
S32, ConstantPtr,
S8, 8},
1792 {
S32, ConstantPtr,
S16, 2 * 8}})
1793 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1794 {{S16, GlobalPtr, S8, GlobalAlign8},
1795 {S16, LocalPtr, S8, GlobalAlign8},
1796 {S16, PrivatePtr, S8, GlobalAlign8},
1797 {S16, ConstantPtr, S8, GlobalAlign8}})
1802 if (
ST.hasFlatAddressSpace()) {
1803 ExtLoads.legalForTypesWithMemDesc(
1804 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1806 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1807 {{S16, FlatPtr, S8, GlobalAlign8}});
1815 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1817 ExtLoads.narrowScalarIf(
1824 ExtLoads.clampScalar(0,
S32,
S32)
1825 .widenScalarToNextPow2(0)
1828 auto &Atomics = getActionDefinitionsBuilder(
1829 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1830 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1831 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1832 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1833 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1834 {
S64, GlobalPtr}, {
S64, LocalPtr},
1835 {
S32, RegionPtr}, {
S64, RegionPtr}});
1836 if (
ST.hasFlatAddressSpace()) {
1837 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1841 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1842 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1843 if (
ST.hasFlatAddressSpace()) {
1844 Atomics32.legalFor({{
S32, FlatPtr}});
1848 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1849 if (
ST.hasLDSFPAtomicAddF32()) {
1850 Atomic.legalFor({{
S32, LocalPtr}, {
S32, RegionPtr}});
1851 if (
ST.hasLdsAtomicAddF64())
1852 Atomic.legalFor({{
S64, LocalPtr}});
1853 if (
ST.hasAtomicDsPkAdd16Insts())
1854 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1856 if (
ST.hasAtomicFaddInsts())
1857 Atomic.legalFor({{
S32, GlobalPtr}});
1858 if (
ST.hasFlatAtomicFaddF32Inst())
1859 Atomic.legalFor({{
S32, FlatPtr}});
1861 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1872 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1873 ST.hasAtomicBufferGlobalPkAddF16Insts())
1874 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1875 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1876 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1877 if (
ST.hasAtomicFlatPkAdd16Insts())
1878 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1883 auto &AtomicFMinFMax =
1884 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1885 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1887 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1888 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1889 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1890 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1891 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1892 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1893 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1894 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1898 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1899 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1900 {
S32, FlatPtr}, {
S64, FlatPtr}})
1901 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1902 {
S32, RegionPtr}, {
S64, RegionPtr}});
1906 getActionDefinitionsBuilder(G_SELECT)
1908 LocalPtr, FlatPtr, PrivatePtr,
1912 .clampScalar(0,
S16,
S64)
1916 .clampMaxNumElements(0,
S32, 2)
1917 .clampMaxNumElements(0, LocalPtr, 2)
1918 .clampMaxNumElements(0, PrivatePtr, 2)
1920 .widenScalarToNextPow2(0)
1925 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1927 if (
ST.has16BitInsts()) {
1928 if (
ST.hasVOP3PInsts()) {
1930 .clampMaxNumElements(0,
S16, 2);
1932 Shifts.legalFor({{
S16,
S16}});
1935 Shifts.widenScalarIf(
1940 const LLT AmountTy = Query.
Types[1];
1946 Shifts.clampScalar(1,
S32,
S32);
1947 Shifts.widenScalarToNextPow2(0, 16);
1948 Shifts.clampScalar(0,
S16,
S64);
1950 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1958 Shifts.clampScalar(1,
S32,
S32);
1959 Shifts.widenScalarToNextPow2(0, 32);
1960 Shifts.clampScalar(0,
S32,
S64);
1962 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1967 Shifts.scalarize(0);
1969 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1970 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1971 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1972 unsigned IdxTypeIdx = 2;
1974 getActionDefinitionsBuilder(
Op)
1976 const LLT EltTy = Query.
Types[EltTypeIdx];
1977 const LLT VecTy = Query.
Types[VecTypeIdx];
1978 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1980 const bool isLegalVecType =
1990 return (EltSize == 32 || EltSize == 64) &&
2006 const LLT EltTy = Query.
Types[EltTypeIdx];
2007 const LLT VecTy = Query.
Types[VecTypeIdx];
2011 const unsigned TargetEltSize =
2012 DstEltSize % 64 == 0 ? 64 : 32;
2013 return std::pair(VecTypeIdx,
2017 .clampScalar(EltTypeIdx,
S32,
S64)
2018 .clampScalar(VecTypeIdx,
S32,
S64)
2019 .clampScalar(IdxTypeIdx,
S32,
S32)
2020 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2029 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2031 const LLT &EltTy = Query.
Types[1].getElementType();
2032 return Query.
Types[0] != EltTy;
2035 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2036 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2037 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2038 getActionDefinitionsBuilder(
Op)
2041 const LLT BigTy = Query.
Types[BigTyIdx];
2047 const LLT LitTy = Query.
Types[LitTyIdx];
2052 .widenScalarToNextPow2(BigTyIdx, 32)
2060 const LLT BigTy = Query.
Types[BigTyIdx];
2061 const LLT LitTy = Query.
Types[LitTyIdx];
2069 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2079 if (
ST.hasScalarPackInsts()) {
2082 .minScalarOrElt(0,
S16)
2085 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2089 BuildVector.customFor({
V2S16,
S16});
2090 BuildVector.minScalarOrElt(0,
S32);
2092 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2100 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2102 .clampMaxNumElements(0,
S32, 32)
2103 .clampMaxNumElements(1,
S16, 2)
2104 .clampMaxNumElements(0,
S16, 64);
2106 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2109 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2110 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2111 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2113 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2114 const LLT Ty = Query.
Types[TypeIdx];
2126 getActionDefinitionsBuilder(
Op)
2130 const LLT BigTy = Query.
Types[BigTyIdx];
2136 .widenScalarToNextPow2(LitTyIdx, 16)
2145 .clampScalar(LitTyIdx,
S32,
S512)
2146 .widenScalarToNextPow2(LitTyIdx, 32)
2150 return notValidElt(Query, LitTyIdx);
2155 return notValidElt(Query, BigTyIdx);
2160 if (
Op == G_MERGE_VALUES) {
2161 Builder.widenScalarIf(
2164 const LLT Ty = Query.
Types[LitTyIdx];
2170 Builder.widenScalarIf(
2172 const LLT Ty = Query.
Types[BigTyIdx];
2178 const LLT &Ty = Query.
Types[BigTyIdx];
2180 if (NewSizeInBits >= 256) {
2182 if (RoundedTo < NewSizeInBits)
2183 NewSizeInBits = RoundedTo;
2185 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2194 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2195 .legalFor({{
S32}, {
S64}})
2196 .clampScalar(0,
S32,
S64);
2198 if (
ST.hasVOP3PInsts()) {
2199 SextInReg.lowerFor({{
V2S16}})
2203 .clampMaxNumElementsStrict(0,
S16, 2);
2204 }
else if (
ST.has16BitInsts()) {
2205 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2209 SextInReg.lowerFor({{
S32}, {
S64}});
2214 .clampScalar(0,
S32,
S64)
2217 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2221 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2222 FSHRActionDefs.legalFor({{
S32,
S32}})
2223 .clampMaxNumElementsStrict(0,
S16, 2);
2224 if (
ST.hasVOP3PInsts())
2226 FSHRActionDefs.scalarize(0).lower();
2228 if (
ST.hasVOP3PInsts()) {
2229 getActionDefinitionsBuilder(G_FSHL)
2231 .clampMaxNumElementsStrict(0,
S16, 2)
2235 getActionDefinitionsBuilder(G_FSHL)
2240 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2243 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2245 getActionDefinitionsBuilder(G_FENCE)
2248 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2253 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2255 .clampScalar(1,
S32,
S32)
2256 .clampScalar(0,
S32,
S64)
2257 .widenScalarToNextPow2(0)
2260 getActionDefinitionsBuilder(
2264 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2265 G_READ_REGISTER, G_WRITE_REGISTER,
2270 if (
ST.hasIEEEMinimumMaximumInsts()) {
2271 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2272 .legalFor(FPTypesPK16)
2273 .clampMaxNumElements(0,
S16, 2)
2275 }
else if (
ST.hasVOP3PInsts()) {
2276 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2278 .clampMaxNumElementsStrict(0,
S16, 2)
2282 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2284 .clampScalar(0,
S32,
S64)
2288 getActionDefinitionsBuilder(
2289 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2292 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2294 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2295 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2296 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2299 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2301 getActionDefinitionsBuilder(
2302 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2303 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2304 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2305 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2310 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2311 G_INTRINSIC_CONVERGENT,
2312 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2324 switch (
MI.getOpcode()) {
2325 case TargetOpcode::G_ADDRSPACE_CAST:
2327 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2329 case TargetOpcode::G_FCEIL:
2331 case TargetOpcode::G_FREM:
2333 case TargetOpcode::G_INTRINSIC_TRUNC:
2335 case TargetOpcode::G_SITOFP:
2337 case TargetOpcode::G_UITOFP:
2339 case TargetOpcode::G_FPTOSI:
2341 case TargetOpcode::G_FPTOUI:
2343 case TargetOpcode::G_FMINNUM:
2344 case TargetOpcode::G_FMAXNUM:
2345 case TargetOpcode::G_FMINIMUMNUM:
2346 case TargetOpcode::G_FMAXIMUMNUM:
2348 case TargetOpcode::G_EXTRACT:
2350 case TargetOpcode::G_INSERT:
2352 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2354 case TargetOpcode::G_INSERT_VECTOR_ELT:
2356 case TargetOpcode::G_FSIN:
2357 case TargetOpcode::G_FCOS:
2359 case TargetOpcode::G_GLOBAL_VALUE:
2361 case TargetOpcode::G_LOAD:
2362 case TargetOpcode::G_SEXTLOAD:
2363 case TargetOpcode::G_ZEXTLOAD:
2365 case TargetOpcode::G_STORE:
2367 case TargetOpcode::G_FMAD:
2369 case TargetOpcode::G_FDIV:
2371 case TargetOpcode::G_FFREXP:
2373 case TargetOpcode::G_FSQRT:
2375 case TargetOpcode::G_UDIV:
2376 case TargetOpcode::G_UREM:
2377 case TargetOpcode::G_UDIVREM:
2379 case TargetOpcode::G_SDIV:
2380 case TargetOpcode::G_SREM:
2381 case TargetOpcode::G_SDIVREM:
2383 case TargetOpcode::G_ATOMIC_CMPXCHG:
2385 case TargetOpcode::G_FLOG2:
2387 case TargetOpcode::G_FLOG:
2388 case TargetOpcode::G_FLOG10:
2390 case TargetOpcode::G_FEXP2:
2392 case TargetOpcode::G_FEXP:
2393 case TargetOpcode::G_FEXP10:
2395 case TargetOpcode::G_FPOW:
2397 case TargetOpcode::G_FFLOOR:
2399 case TargetOpcode::G_BUILD_VECTOR:
2400 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2402 case TargetOpcode::G_MUL:
2404 case TargetOpcode::G_CTLZ:
2405 case TargetOpcode::G_CTTZ:
2407 case TargetOpcode::G_CTLS:
2409 case TargetOpcode::G_CTLZ_ZERO_POISON:
2411 case TargetOpcode::G_STACKSAVE:
2413 case TargetOpcode::G_GET_FPENV:
2415 case TargetOpcode::G_SET_FPENV:
2417 case TargetOpcode::G_TRAP:
2419 case TargetOpcode::G_DEBUGTRAP:
2439 if (ST.hasApertureRegs()) {
2444 ? AMDGPU::SRC_SHARED_BASE
2445 : AMDGPU::SRC_PRIVATE_BASE;
2446 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2447 !ST.hasGloballyAddressableScratch()) &&
2448 "Cannot use src_private_base with globally addressable scratch!");
2451 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2452 return B.buildUnmerge(I32, Dst).getReg(1);
2467 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2483 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2486 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2508 B.buildObjectPtrOffset(
2511 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2519 switch (Def->getOpcode()) {
2520 case AMDGPU::G_FRAME_INDEX:
2521 case AMDGPU::G_GLOBAL_VALUE:
2522 case AMDGPU::G_BLOCK_ADDR:
2524 case AMDGPU::G_CONSTANT: {
2525 const ConstantInt *CI = Def->getOperand(1).getCImm();
2542 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2544 Intrinsic::amdgcn_addrspacecast_nonnull));
2550 :
MI.getOperand(1).getReg();
2554 unsigned SrcAS = SrcTy.getAddressSpace();
2564 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2571 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2573 ST.hasGloballyAddressableScratch()) {
2576 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2578 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2579 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2581 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2582 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2583 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2587 return B.buildExtract(Dst, Src, 0).getReg(0);
2593 castFlatToLocalOrPrivate(Dst);
2594 MI.eraseFromParent();
2600 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2601 auto FlatNull =
B.buildConstant(SrcTy, 0);
2604 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2608 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2610 MI.eraseFromParent();
2617 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2620 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2623 ST.hasGloballyAddressableScratch()) {
2627 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2628 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2632 if (ST.isWave64()) {
2633 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2639 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2640 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2642 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2646 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2647 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2649 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2650 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2659 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2665 castLocalOrPrivateToFlat(Dst);
2666 MI.eraseFromParent();
2670 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2677 SegmentNull.getReg(0));
2679 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2681 MI.eraseFromParent();
2686 SrcTy.getSizeInBits() == 64) {
2688 B.buildExtract(Dst, Src, 0);
2689 MI.eraseFromParent();
2696 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2697 auto PtrLo =
B.buildPtrToInt(I32, Src);
2698 if (AddrHiVal == 0) {
2699 auto Zext =
B.buildZExt(I64, PtrLo);
2700 B.buildIntToPtr(Dst, Zext);
2702 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2703 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2706 MI.eraseFromParent();
2713 MI.eraseFromParent();
2722 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2727 auto C1 =
B.buildFConstant(Ty, C1Val);
2728 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2731 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2732 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2734 auto C2 =
B.buildFConstant(Ty, C2Val);
2735 auto Fabs =
B.buildFAbs(Ty, Src);
2738 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2739 MI.eraseFromParent();
2756 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2758 const auto Zero =
B.buildFConstant(
F64, 0.0);
2759 const auto One =
B.buildFConstant(
F64, 1.0);
2762 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2763 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2766 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2767 MI.eraseFromParent();
2775 Register Src0Reg =
MI.getOperand(1).getReg();
2776 Register Src1Reg =
MI.getOperand(2).getReg();
2777 auto Flags =
MI.getFlags();
2780 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2781 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2782 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2783 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2784 MI.eraseFromParent();
2790 const unsigned FractBits = 52;
2791 const unsigned ExpBits = 11;
2794 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2795 auto Const1 =
B.buildConstant(I32, ExpBits);
2797 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2799 .addUse(Const0.getReg(0))
2800 .addUse(Const1.getReg(0));
2802 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2815 auto SrcInt =
B.buildBitcast(I64, Src);
2818 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2825 const unsigned FractBits = 52;
2828 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2829 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2831 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2833 const auto Zero32 =
B.buildConstant(I32, 0);
2836 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2838 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2839 auto Not =
B.buildNot(I64, Shr);
2840 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2841 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2846 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2847 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2848 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2849 MI.eraseFromParent();
2865 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2866 auto ThirtyTwo =
B.buildConstant(I32, 32);
2869 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2870 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2872 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2873 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2876 B.buildFAdd(Dst, LdExp, CvtLo);
2877 MI.eraseFromParent();
2883 auto One =
B.buildConstant(I32, 1);
2887 auto ThirtyOne =
B.buildConstant(I32, 31);
2888 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2889 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2890 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2891 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2892 .addUse(Unmerge.getReg(1));
2893 auto LS2 =
B.buildSub(I32, LS, One);
2894 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2896 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2897 auto Norm =
B.buildShl(I64, Src, ShAmt);
2898 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2899 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2900 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2901 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2902 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2903 B.buildFLdexp(Dst, FVal, Scale);
2904 MI.eraseFromParent();
2924 unsigned Flags =
MI.getFlags();
2935 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2943 auto SrcInt =
B.buildBitcast(I32, Src);
2944 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2945 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2949 K0 =
B.buildFConstant(
2951 K1 =
B.buildFConstant(
2954 K0 =
B.buildFConstant(
2956 K1 =
B.buildFConstant(
2960 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2961 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2962 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2964 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2965 :
B.buildFPTOUI(I32, FloorMul);
2966 auto Lo =
B.buildFPTOUI(I32, Fma);
2970 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2972 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2975 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2976 MI.eraseFromParent();
3008 unsigned StartIdx =
Offset / 32;
3012 if (DstCount == 1) {
3014 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3019 for (
unsigned I = 0;
I < DstCount; ++
I)
3020 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3021 B.buildMergeLikeInstr(DstReg, MergeVec);
3024 MI.eraseFromParent();
3034 Register InsertSrc =
MI.getOperand(2).getReg();
3043 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3047 unsigned DstCount = DstSize / 32;
3048 unsigned InsertCount = InsertSize / 32;
3049 unsigned StartIdx =
Offset / 32;
3051 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3054 for (
unsigned I = 0;
I < StartIdx; ++
I)
3057 if (InsertCount == 1) {
3061 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3064 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3065 for (
unsigned I = 0;
I < InsertCount; ++
I)
3069 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3072 B.buildMergeLikeInstr(DstReg, MergeVec);
3074 MI.eraseFromParent();
3101 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3102 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3103 B.buildIntToPtr(Dst, IntElt);
3105 MI.eraseFromParent();
3112 std::optional<ValueAndVReg> MaybeIdxVal =
3116 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3119 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3120 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3125 MI.eraseFromParent();
3154 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3155 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3156 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3158 B.buildIntToPtr(Dst, IntVecDest);
3159 MI.eraseFromParent();
3166 std::optional<ValueAndVReg> MaybeIdxVal =
3171 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3174 if (IdxVal < NumElts) {
3176 for (
unsigned i = 0; i < NumElts; ++i)
3178 B.buildUnmerge(SrcRegs, Vec);
3180 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3181 B.buildMergeLikeInstr(Dst, SrcRegs);
3186 MI.eraseFromParent();
3197 unsigned Flags =
MI.getFlags();
3201 if (ST.hasTrigReducedRange()) {
3202 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3203 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3204 .addUse(MulVal.getReg(0))
3208 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3211 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3215 MI.eraseFromParent();
3223 unsigned GAFlags)
const {
3252 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3254 if (ST.has64BitLiterals()) {
3258 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3262 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3271 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3272 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3275 B.buildExtract(DstReg, PCReg, 0);
3285 if (RequiresHighHalf && ST.has64BitLiterals()) {
3287 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3288 B.buildInstr(AMDGPU::S_MOV_B64)
3303 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3306 B.buildInstr(AMDGPU::S_MOV_B32)
3311 if (RequiresHighHalf) {
3313 "Must provide a 64-bit pointer type!");
3316 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3318 B.buildInstr(AMDGPU::S_MOV_B32)
3329 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3331 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3335 if (AddrDst != DstReg)
3336 B.buildCast(DstReg, AddrDst);
3337 }
else if (AddrLo != DstReg) {
3340 B.buildCast(DstReg, AddrLo);
3349 unsigned AS = Ty.getAddressSpace();
3357 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3361 Fn,
"local memory global used by non-kernel function",
3370 B.buildUndef(DstReg);
3371 MI.eraseFromParent();
3395 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3396 B.buildIntToPtr(DstReg, Sz);
3397 MI.eraseFromParent();
3403 MI.eraseFromParent();
3407 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3409 MI.eraseFromParent();
3417 MI.eraseFromParent();
3423 MI.eraseFromParent();
3439 if (Ty.getSizeInBits() == 32) {
3441 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3442 B.buildExtract(DstReg,
Load, 0);
3444 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3446 MI.eraseFromParent();
3469 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3471 MI.getOperand(1).setReg(Cast.getReg(0));
3476 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3502 if (WideMemSize == ValSize) {
3508 MI.setMemRefs(MF, {WideMMO});
3514 if (ValSize > WideMemSize)
3521 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3522 B.buildTrunc(ValReg, WideLoad).getReg(0);
3529 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3530 B.buildExtract(ValReg, WideLoad, 0);
3534 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3535 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3539 MI.eraseFromParent();
3552 Register DataReg =
MI.getOperand(0).getReg();
3597 "this should not have been custom lowered");
3602 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3604 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3608 .setMemRefs(
MI.memoperands());
3610 MI.eraseFromParent();
3618 switch (
DefMI->getOpcode()) {
3619 case TargetOpcode::G_INTRINSIC: {
3621 case Intrinsic::amdgcn_frexp_mant:
3622 case Intrinsic::amdgcn_log:
3623 case Intrinsic::amdgcn_log_clamp:
3624 case Intrinsic::amdgcn_exp2:
3625 case Intrinsic::amdgcn_sqrt:
3633 case TargetOpcode::G_FSQRT:
3635 case TargetOpcode::G_FFREXP: {
3636 if (
DefMI->getOperand(0).getReg() == Src)
3640 case TargetOpcode::G_FPEXT: {
3661std::pair<Register, Register>
3663 unsigned Flags)
const {
3667 auto SmallestNormal =
B.buildFConstant(
3669 auto IsLtSmallestNormal =
3672 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3673 auto One =
B.buildFConstant(
F32, 1.0);
3675 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3676 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3678 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3691 LLT Ty =
B.getMRI()->getType(Dst);
3692 unsigned Flags =
MI.getFlags();
3696 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3697 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3698 .addUse(Ext.getReg(0))
3700 B.buildFPTrunc(Dst,
Log2, Flags);
3701 MI.eraseFromParent();
3709 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3712 MI.eraseFromParent();
3716 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3717 .addUse(ScaledInput)
3720 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3721 auto Zero =
B.buildFConstant(Ty, 0.0);
3723 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3724 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3726 MI.eraseFromParent();
3732 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3733 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3738 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3739 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3744 unsigned Flags =
MI.getFlags();
3754 auto PromoteSrc =
B.buildFPExt(
F32,
X);
3756 B.buildFPTrunc(Dst, LogVal);
3761 MI.eraseFromParent();
3770 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3773 if (ST.hasFastFMAF32()) {
3775 const float c_log10 = 0x1.344134p-2f;
3776 const float cc_log10 = 0x1.09f79ep-26f;
3779 const float c_log = 0x1.62e42ep-1f;
3780 const float cc_log = 0x1.efa39ep-25f;
3782 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3783 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3787 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3788 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3789 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3790 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3791 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3794 const float ch_log10 = 0x1.344000p-2f;
3795 const float ct_log10 = 0x1.3509f6p-18f;
3798 const float ch_log = 0x1.62e000p-1f;
3799 const float ct_log = 0x1.0bfbe8p-15f;
3801 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3802 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3804 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
3805 auto YH =
B.buildAnd(Ty,
Y, MaskConst);
3806 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3810 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3813 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3815 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3818 const bool IsFiniteOnly =
3821 if (!IsFiniteOnly) {
3824 auto Fabs =
B.buildFAbs(Ty,
Y);
3827 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3831 auto Zero =
B.buildFConstant(Ty, 0.0);
3833 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3834 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3835 B.buildFSub(Dst, R, Shift, Flags);
3837 B.buildCopy(Dst, R);
3840 MI.eraseFromParent();
3846 unsigned Flags)
const {
3847 const double Log2BaseInverted =
3850 LLT Ty =
B.getMRI()->getType(Dst);
3855 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3858 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3859 auto Zero =
B.buildFConstant(Ty, 0.0);
3861 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3862 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3864 if (ST.hasFastFMAF32())
3865 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3867 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3868 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3875 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3876 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3879 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3880 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3891 unsigned Flags =
MI.getFlags();
3892 LLT Ty =
B.getMRI()->getType(Dst);
3899 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3900 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3901 .addUse(Ext.getReg(0))
3903 B.buildFPTrunc(Dst,
Log2, Flags);
3904 MI.eraseFromParent();
3914 MI.eraseFromParent();
3922 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3924 RangeCheckConst, Flags);
3926 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3927 auto Zero =
B.buildFConstant(Ty, 0.0);
3928 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3929 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3931 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3932 .addUse(AddInput.getReg(0))
3935 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3936 auto One =
B.buildFConstant(Ty, 1.0);
3937 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3938 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3939 MI.eraseFromParent();
3944 const SrcOp &Src,
unsigned Flags) {
3945 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3948 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3949 .addUse(Src.getReg())
3952 return B.buildFExp2(Dst, Src, Flags);
3958 bool IsExp10)
const {
3959 LLT Ty =
B.getMRI()->getType(
X);
3963 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3964 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3971 LLT Ty =
B.getMRI()->getType(Dst);
3977 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3980 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3981 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3982 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3985 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3987 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3988 .addUse(ExpInput.getReg(0))
3991 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3992 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3993 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3999 unsigned Flags)
const {
4000 LLT Ty =
B.getMRI()->getType(Dst);
4004 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4005 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4007 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4008 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4009 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4010 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4011 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4021 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4025 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4026 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4027 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4029 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4030 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4032 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4033 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4034 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4035 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4037 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4038 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4039 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4041 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4059 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4061 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4063 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4065 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4066 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4067 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4068 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4070 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4071 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4072 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4073 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4075 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4076 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4077 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4078 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4079 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4081 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4082 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4083 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4084 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4087 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4088 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4089 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4091 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4092 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4093 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4094 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4095 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4099 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4100 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4102 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4104 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4106 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4108 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4110 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4111 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4112 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4113 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4115 auto One =
B.buildFConstant(
F64, 1.0);
4116 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4117 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4120 auto DnInt =
B.buildFPTOSI(I32, Dn);
4121 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4128 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4135 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4137 MI.eraseFromParent();
4145 const unsigned Flags =
MI.getFlags();
4153 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4161 MI.eraseFromParent();
4172 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4175 B.buildFPTrunc(Dst, Lowered, Flags);
4176 MI.eraseFromParent();
4187 MI.eraseFromParent();
4215 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4218 if (ST.hasFastFMAF32()) {
4220 const float cc_exp = 0x1.4ae0bep-26f;
4221 const float c_exp10 = 0x1.a934f0p+1f;
4222 const float cc_exp10 = 0x1.2f346ep-24f;
4224 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4225 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4226 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4227 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4229 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4230 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4232 const float ch_exp = 0x1.714000p+0f;
4233 const float cl_exp = 0x1.47652ap-12f;
4235 const float ch_exp10 = 0x1.a92000p+1f;
4236 const float cl_exp10 = 0x1.4f0978p-11f;
4238 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
4239 auto XH =
B.buildAnd(Ty,
X, MaskConst);
4240 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4242 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4243 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4245 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4246 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4249 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4250 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4253 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4256 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4257 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4259 auto IntE =
B.buildFPTOSI(I32, E);
4261 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4262 .addUse(
A.getReg(0))
4264 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4266 auto UnderflowCheckConst =
4267 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4268 auto Zero =
B.buildFConstant(Ty, 0.0);
4272 R =
B.buildSelect(Ty, Underflow, Zero, R);
4275 auto OverflowCheckConst =
4276 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4281 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4284 B.buildCopy(Dst, R);
4285 MI.eraseFromParent();
4294 unsigned Flags =
MI.getFlags();
4295 LLT Ty =
B.getMRI()->getType(Dst);
4298 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4299 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4300 .addUse(Log.getReg(0))
4303 B.buildFExp2(Dst,
Mul, Flags);
4304 }
else if (Ty ==
F16) {
4306 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4307 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4308 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4309 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4310 .addUse(Ext0.getReg(0))
4311 .addUse(Ext1.getReg(0))
4313 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul), Flags);
4317 MI.eraseFromParent();
4325 ModSrc = SrcFNeg->getOperand(1).getReg();
4327 ModSrc = SrcFAbs->getOperand(1).getReg();
4329 ModSrc = SrcFAbs->getOperand(1).getReg();
4339 Register OrigSrc =
MI.getOperand(1).getReg();
4340 unsigned Flags =
MI.getFlags();
4342 "this should not have been custom lowered");
4352 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4372 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4374 B.buildFMinNum(Min, Fract, Const, Flags);
4379 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4382 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4383 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4385 MI.eraseFromParent();
4403 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4405 Src0 =
B.buildTrunc(
I16,
MI.getOperand(1).getReg()).getReg(0);
4406 Src1 =
B.buildTrunc(
I16,
MI.getOperand(2).getReg()).getReg(0);
4409 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4410 B.buildBitcast(Dst,
Merge);
4412 MI.eraseFromParent();
4429 bool UsePartialMad64_32,
4430 bool SeparateOddAlignedProducts)
const {
4445 auto getZero32 = [&]() ->
Register {
4447 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4450 auto getZero64 = [&]() ->
Register {
4452 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4457 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4468 if (CarryIn.empty())
4471 bool HaveCarryOut =
true;
4473 if (CarryIn.size() == 1) {
4475 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4479 CarryAccum = getZero32();
4481 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4482 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4484 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4489 LocalAccum = getZero32();
4490 HaveCarryOut =
false;
4495 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4496 LocalAccum =
Add.getReg(0);
4510 auto buildMadChain =
4513 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4514 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4521 if (LocalAccum.size() == 1 &&
4522 (!UsePartialMad64_32 || !CarryIn.empty())) {
4525 unsigned j1 = DstIndex - j0;
4526 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4530 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4532 LocalAccum[0] =
Mul.getReg(0);
4534 if (CarryIn.empty()) {
4535 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4538 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4544 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4548 if (j0 <= DstIndex) {
4549 bool HaveSmallAccum =
false;
4552 if (LocalAccum[0]) {
4553 if (LocalAccum.size() == 1) {
4554 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4555 HaveSmallAccum =
true;
4556 }
else if (LocalAccum[1]) {
4557 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4558 HaveSmallAccum =
false;
4560 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4561 HaveSmallAccum =
true;
4564 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4566 HaveSmallAccum =
true;
4570 unsigned j1 = DstIndex - j0;
4571 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4575 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4576 {Src0[j0], Src1[j1], Tmp});
4577 Tmp = Mad.getReg(0);
4578 if (!HaveSmallAccum)
4579 CarryOut.push_back(Mad.getReg(1));
4580 HaveSmallAccum =
false;
4583 }
while (j0 <= DstIndex);
4585 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4586 LocalAccum[0] = Unmerge.getReg(0);
4587 if (LocalAccum.size() > 1)
4588 LocalAccum[1] = Unmerge.getReg(1);
4615 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4616 Carry OddCarryIn = std::move(OddCarry);
4617 Carry EvenCarryIn = std::move(EvenCarry);
4622 if (2 * i < Accum.
size()) {
4623 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4624 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4629 if (!SeparateOddAlignedProducts) {
4630 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4631 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4633 bool IsHighest = 2 * i >= Accum.
size();
4636 .take_front(IsHighest ? 1 : 2);
4637 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4643 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4645 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4647 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4650 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4653 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4654 Lo->getOperand(1).getReg());
4655 Accum[2 * i] =
Hi.getReg(0);
4656 SeparateOddCarry =
Hi.getReg(1);
4663 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4664 EvenCarryIn.push_back(CarryOut);
4666 if (2 * i < Accum.
size()) {
4667 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4668 OddCarry.push_back(CarryOut);
4680 assert(ST.hasMad64_32());
4681 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4693 unsigned Size = Ty.getSizeInBits();
4694 if (ST.hasVMulU64Inst() &&
Size == 64)
4697 unsigned NumParts =
Size / 32;
4709 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4713 for (
unsigned i = 0; i < NumParts; ++i) {
4717 B.buildUnmerge(Src0Parts, Src0);
4718 B.buildUnmerge(Src1Parts, Src1);
4721 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4722 SeparateOddAlignedProducts);
4724 B.buildMergeLikeInstr(DstReg, AccumRegs);
4725 MI.eraseFromParent();
4740 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4741 ? AMDGPU::G_AMDGPU_FFBH_U32
4742 : AMDGPU::G_AMDGPU_FFBL_B32;
4743 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4746 MI.eraseFromParent();
4756 TypeSize NumBits = SrcTy.getSizeInBits();
4761 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4762 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4763 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4764 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4765 B.buildTrunc(Dst, Ctlz);
4766 MI.eraseFromParent();
4777 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4778 unsigned BitWidth = SrcTy.getSizeInBits();
4780 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4781 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4782 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4783 MI.eraseFromParent();
4789 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4792 return ConstVal == -1;
4799 Register CondDef =
MI.getOperand(0).getReg();
4818 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4827 UncondBrTarget = &*NextMBB;
4829 if (
Next->getOpcode() != AMDGPU::G_BR)
4848 *ArgRC,
B.getDebugLoc(), ArgTy);
4852 const unsigned Mask = Arg->
getMask();
4860 auto ShiftAmt =
B.buildConstant(I32, Shift);
4861 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4864 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4866 B.buildCopy(DstReg, LiveIn);
4876 if (!ST.hasClusters()) {
4879 MI.eraseFromParent();
4899 auto One =
B.buildConstant(I32, 1);
4900 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4901 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4902 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4909 B.buildCopy(DstReg, GlobalIdXYZ);
4910 MI.eraseFromParent();
4914 B.buildCopy(DstReg, ClusterIdXYZ);
4915 MI.eraseFromParent();
4920 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4922 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4923 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4925 .addImm(ClusterIdField);
4926 auto Zero =
B.buildConstant(I32, 0);
4929 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4930 MI.eraseFromParent();
4972 auto LoadConstant = [&](
unsigned N) {
4973 B.buildConstant(DstReg,
N);
4977 if (ST.hasArchitectedSGPRs() &&
4984 Arg = &WorkGroupIDX;
4985 ArgRC = &AMDGPU::SReg_32RegClass;
4989 Arg = &WorkGroupIDY;
4990 ArgRC = &AMDGPU::SReg_32RegClass;
4994 Arg = &WorkGroupIDZ;
4995 ArgRC = &AMDGPU::SReg_32RegClass;
4999 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5000 return LoadConstant(0);
5001 Arg = &ClusterWorkGroupIDX;
5002 ArgRC = &AMDGPU::SReg_32RegClass;
5006 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5007 return LoadConstant(0);
5008 Arg = &ClusterWorkGroupIDY;
5009 ArgRC = &AMDGPU::SReg_32RegClass;
5013 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5014 return LoadConstant(0);
5015 Arg = &ClusterWorkGroupIDZ;
5016 ArgRC = &AMDGPU::SReg_32RegClass;
5021 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5022 Arg = &ClusterWorkGroupMaxIDX;
5023 ArgRC = &AMDGPU::SReg_32RegClass;
5028 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5029 Arg = &ClusterWorkGroupMaxIDY;
5030 ArgRC = &AMDGPU::SReg_32RegClass;
5035 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5036 Arg = &ClusterWorkGroupMaxIDZ;
5037 ArgRC = &AMDGPU::SReg_32RegClass;
5041 Arg = &ClusterWorkGroupMaxFlatID;
5042 ArgRC = &AMDGPU::SReg_32RegClass;
5057 return LoadConstant(0);
5062 B.buildUndef(DstReg);
5066 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5078 MI.eraseFromParent();
5084 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5085 MI.eraseFromParent();
5092 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5106 B.buildUndef(DstReg);
5107 MI.eraseFromParent();
5111 if (Arg->isMasked()) {
5125 MI.eraseFromParent();
5140 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5149 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5157 Align Alignment)
const {
5161 "unexpected kernarg parameter type");
5168 MI.eraseFromParent();
5200 auto FloatY =
B.buildUITOFP(
F32,
Y);
5201 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5203 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5204 auto Z =
B.buildFPTOUI(I32, ScaledY);
5207 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5208 auto NegYZ =
B.buildMul(I32, NegY, Z);
5209 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5212 auto Q =
B.buildUMulH(I32,
X, Z);
5213 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5216 auto One =
B.buildConstant(I32, 1);
5219 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5220 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5225 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5228 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5247 auto Unmerge =
B.buildUnmerge(I32, Val);
5249 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5250 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5252 auto Mad =
B.buildFMAD(
5256 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5257 auto Mul1 =
B.buildFMul(
5261 auto Mul2 =
B.buildFMul(
5263 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5266 auto Mad2 =
B.buildFMAD(
5270 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5271 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5273 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5288 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5290 auto Zero64 =
B.buildConstant(I64, 0);
5291 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5293 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5294 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5296 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5297 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5298 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5300 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5301 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5302 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5304 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5305 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5306 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5307 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5308 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5310 auto Zero32 =
B.buildConstant(I32, 0);
5311 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5312 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5313 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5315 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5316 Register NumerLo = UnmergeNumer.getReg(0);
5317 Register NumerHi = UnmergeNumer.getReg(1);
5319 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5320 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5321 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5322 Register Mul3_Lo = UnmergeMul3.getReg(0);
5323 Register Mul3_Hi = UnmergeMul3.getReg(1);
5324 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5325 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5326 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5327 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5329 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5330 Register DenomLo = UnmergeDenom.getReg(0);
5331 Register DenomHi = UnmergeDenom.getReg(1);
5334 auto C1 =
B.buildSExt(I32, CmpHi);
5337 auto C2 =
B.buildSExt(I32, CmpLo);
5340 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5347 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5348 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5349 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5350 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5352 auto One64 =
B.buildConstant(I64, 1);
5353 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5359 auto C6 =
B.buildSelect(
5363 auto Add4 =
B.buildAdd(I64, Add3, One64);
5364 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5366 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5367 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5368 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5374 auto Sel1 =
B.buildSelect(
5381 auto Sel2 =
B.buildSelect(
5392 switch (
MI.getOpcode()) {
5395 case AMDGPU::G_UDIV: {
5396 DstDivReg =
MI.getOperand(0).getReg();
5399 case AMDGPU::G_UREM: {
5400 DstRemReg =
MI.getOperand(0).getReg();
5403 case AMDGPU::G_UDIVREM: {
5404 DstDivReg =
MI.getOperand(0).getReg();
5405 DstRemReg =
MI.getOperand(1).getReg();
5412 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5413 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5414 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5424 MI.eraseFromParent();
5435 if (Ty != I32 && Ty != I64)
5438 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5439 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5440 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5442 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5443 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5444 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5446 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5447 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5449 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5450 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5452 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5453 switch (
MI.getOpcode()) {
5456 case AMDGPU::G_SDIV: {
5457 DstDivReg =
MI.getOperand(0).getReg();
5461 case AMDGPU::G_SREM: {
5462 DstRemReg =
MI.getOperand(0).getReg();
5466 case AMDGPU::G_SDIVREM: {
5467 DstDivReg =
MI.getOperand(0).getReg();
5468 DstRemReg =
MI.getOperand(1).getReg();
5481 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5482 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5483 B.buildSub(DstDivReg, SignXor, Sign);
5487 auto Sign = LHSign.getReg(0);
5488 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5489 B.buildSub(DstRemReg, SignXor, Sign);
5492 MI.eraseFromParent();
5508 if (!AllowInaccurateRcp && ResTy !=
F16)
5519 if (CLHS->isOne()) {
5520 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5524 MI.eraseFromParent();
5529 if (CLHS->isMinusOne()) {
5530 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5531 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5532 .addUse(FNeg.getReg(0))
5535 MI.eraseFromParent();
5542 if (!AllowInaccurateRcp &&
5547 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5550 B.buildFMul(Res, LHS, RCP, Flags);
5552 MI.eraseFromParent();
5567 if (!AllowInaccurateRcp)
5575 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5577 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5578 auto One =
B.buildFConstant(ResTy, 1.0);
5580 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5584 R =
B.buildFNeg(ResTy, R);
5586 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5587 R =
B.buildFMA(ResTy, Tmp0, R, R);
5589 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5590 R =
B.buildFMA(ResTy, Tmp1, R, R);
5593 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5594 B.buildCopy(Res, R);
5595 MI.eraseFromParent();
5599 auto Ret =
B.buildFMul(ResTy,
X, R);
5600 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5602 B.buildFMA(Res, Tmp2, R, Ret);
5603 MI.eraseFromParent();
5634 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5635 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5636 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5637 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5638 .addUse(RHSExt.getReg(0))
5640 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5642 if (ST.hasMadMacF32Insts()) {
5643 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5644 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5645 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5647 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5648 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5649 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5651 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5652 auto TmpInt =
B.buildBitcast(I32, Tmp);
5653 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5654 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5655 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5656 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5657 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5658 .addUse(RDst.getReg(0))
5663 MI.eraseFromParent();
5676 unsigned SPDenormMode =
5679 if (ST.hasDenormModeInst()) {
5681 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5683 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5684 B.buildInstr(AMDGPU::S_DENORM_MODE)
5685 .addImm(NewDenormModeValue);
5688 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5689 .addImm(SPDenormMode)
5710 auto One =
B.buildFConstant(
F32, 1.0f);
5712 auto DenominatorScaled =
5713 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5718 auto NumeratorScaled =
5719 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5725 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5726 .addUse(DenominatorScaled.getReg(0))
5728 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5731 const bool HasDynamicDenormals =
5736 if (!PreservesDenormals) {
5737 if (HasDynamicDenormals) {
5739 B.buildInstr(AMDGPU::S_GETREG_B32)
5740 .addDef(SavedSPDenormMode)
5746 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5747 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5748 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5749 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5750 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5751 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5753 if (!PreservesDenormals) {
5754 if (HasDynamicDenormals) {
5755 assert(SavedSPDenormMode);
5756 B.buildInstr(AMDGPU::S_SETREG_B32)
5757 .addReg(SavedSPDenormMode)
5763 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5764 .addUse(Fma4.getReg(0))
5765 .addUse(Fma1.getReg(0))
5766 .addUse(Fma3.getReg(0))
5767 .addUse(NumeratorScaled.getReg(1))
5770 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5771 .addUse(Fmas.getReg(0))
5776 MI.eraseFromParent();
5794 auto One =
B.buildFConstant(
F64, 1.0);
5796 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5802 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5804 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5805 .addUse(DivScale0.getReg(0))
5808 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5809 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5810 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5812 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5818 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5819 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5820 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5823 if (!ST.hasUsableDivScaleConditionOutput()) {
5830 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5831 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5832 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5833 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5836 Scale1Unmerge.getReg(1));
5838 Scale0Unmerge.getReg(1));
5839 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5841 Scale = DivScale1.getReg(1);
5844 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5845 .addUse(Fma4.getReg(0))
5846 .addUse(Fma3.getReg(0))
5847 .addUse(
Mul.getReg(0))
5851 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5852 .addUse(Fmas.getReg(0))
5857 MI.eraseFromParent();
5872 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5875 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5879 if (ST.hasFractBug()) {
5880 auto Fabs =
B.buildFAbs(Ty, Val);
5884 auto Zero =
B.buildConstant(InstrExpTy, 0);
5885 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5886 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5889 B.buildCopy(Res0, Mant);
5890 B.buildSExtOrTrunc(Res1, Exp);
5892 MI.eraseFromParent();
5906 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5909 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5910 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5911 auto C2 =
B.buildFConstant(
F32, 1.0f);
5914 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5916 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5918 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5919 .addUse(Mul0.getReg(0))
5922 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5924 B.buildFMul(Res, Sel, Mul1, Flags);
5926 MI.eraseFromParent();
5935 unsigned Flags =
MI.getFlags();
5936 assert(!ST.has16BitInsts());
5937 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5938 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5939 .addUse(Ext.getReg(0))
5941 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5942 MI.eraseFromParent();
5952 const unsigned Flags =
MI.getFlags();
5960 MI.eraseFromParent();
5964 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5966 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5967 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5968 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5973 .addUse(SqrtX.getReg(0))
5976 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5977 auto NegOne =
B.buildConstant(I32, -1);
5978 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5980 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5981 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5983 auto PosOne =
B.buildConstant(I32, 1);
5984 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5986 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5987 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
5989 auto Zero =
B.buildFConstant(
F32, 0.0f);
5993 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
5997 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6000 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6001 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6003 auto Half =
B.buildFConstant(
F32, 0.5f);
6004 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6005 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6006 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6007 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6008 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6009 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6010 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6011 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6014 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6016 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6018 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6021 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6023 MI.eraseFromParent();
6057 unsigned Flags =
MI.getFlags();
6062 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6064 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6068 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6069 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6070 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6073 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6075 auto Half =
B.buildFConstant(
F64, 0.5);
6076 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6077 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6079 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6080 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6082 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6083 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6085 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6086 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6088 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6090 Register SqrtRet = SqrtS2.getReg(0);
6092 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6093 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6094 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6097 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6098 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6099 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6104 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6113 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6115 MI.eraseFromParent();
6146 auto Flags =
MI.getFlags();
6158 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6168 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6169 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6174 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6176 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6177 MI.eraseFromParent();
6189 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6190 IID == Intrinsic::amdgcn_permlanex16;
6191 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6192 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6193 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6194 IID == Intrinsic::amdgcn_permlane_up ||
6195 IID == Intrinsic::amdgcn_permlane_down ||
6196 IID == Intrinsic::amdgcn_permlane_xor;
6200 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6202 case Intrinsic::amdgcn_readfirstlane:
6203 case Intrinsic::amdgcn_permlane64:
6204 return LaneOp.getReg(0);
6205 case Intrinsic::amdgcn_readlane:
6206 case Intrinsic::amdgcn_set_inactive:
6207 case Intrinsic::amdgcn_set_inactive_chain_arg:
6208 return LaneOp.addUse(Src1).getReg(0);
6209 case Intrinsic::amdgcn_writelane:
6210 case Intrinsic::amdgcn_permlane_bcast:
6211 case Intrinsic::amdgcn_permlane_up:
6212 case Intrinsic::amdgcn_permlane_down:
6213 case Intrinsic::amdgcn_permlane_xor:
6214 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6215 case Intrinsic::amdgcn_permlane16:
6216 case Intrinsic::amdgcn_permlanex16: {
6218 int64_t Src4 =
MI.getOperand(6).getImm();
6219 int64_t Src5 =
MI.getOperand(7).getImm();
6220 return LaneOp.addUse(Src1)
6227 case Intrinsic::amdgcn_mov_dpp8:
6228 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6229 case Intrinsic::amdgcn_update_dpp:
6230 return LaneOp.addUse(Src1)
6231 .addImm(
MI.getOperand(4).getImm())
6232 .addImm(
MI.getOperand(5).getImm())
6233 .addImm(
MI.getOperand(6).getImm())
6234 .addImm(
MI.getOperand(7).getImm())
6244 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6245 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6246 IsPermlaneShuffle) {
6247 Src1 =
MI.getOperand(3).getReg();
6248 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6249 IsPermlaneShuffle) {
6250 Src2 =
MI.getOperand(4).getReg();
6255 unsigned Size = Ty.getSizeInBits();
6257 unsigned SplitSize = 32;
6258 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6259 ST.hasDPALU_DPP() &&
6263 if (
Size == SplitSize) {
6270 bool IsFloat = Ty.getScalarType().isFloat();
6274 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6276 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6278 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6282 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6284 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6285 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6287 if (IID == Intrinsic::amdgcn_writelane)
6288 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6290 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6292 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6294 B.buildTrunc(DstReg, LaneOpDst);
6295 MI.eraseFromParent();
6299 if (
Size % SplitSize != 0)
6303 bool NeedsBitcast =
false;
6304 if (IntTy.isVector()) {
6307 if (EltSize == SplitSize) {
6308 PartialResTy = EltTy;
6309 }
else if (EltSize == 16 || EltSize == 32) {
6310 unsigned NElem = SplitSize / EltSize;
6313 NeedsBitcast =
true;
6318 unsigned NumParts =
Size / SplitSize;
6322 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6323 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6325 if (IID == Intrinsic::amdgcn_writelane)
6326 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6328 for (
unsigned i = 0; i < NumParts; ++i) {
6329 Src0 = Src0Parts.
getReg(i);
6331 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6332 Src1 = Src1Parts.
getReg(i);
6334 if (IID == Intrinsic::amdgcn_writelane)
6335 Src2 = Src2Parts.
getReg(i);
6337 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6340 if (NeedsBitcast || IsFloat)
6343 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6345 B.buildMergeLikeInstr(DstReg, PartialRes);
6347 MI.eraseFromParent();
6355 ST.getTargetLowering()->getImplicitParameterOffset(
6365 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6366 B.buildConstant(IdxTy,
Offset).getReg(0));
6377 Register Pointer =
MI.getOperand(2).getReg();
6379 Register NumRecords =
MI.getOperand(4).getReg();
6385 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6387 auto ExtStride =
B.buildAnyExt(I32, Stride);
6389 if (ST.has45BitNumRecordsBufferResource()) {
6390 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6394 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6395 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6396 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6397 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6401 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6402 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6403 auto ExtShiftedStride =
6404 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6405 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6406 auto ExtShiftedFlags =
6407 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6408 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6410 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6411 B.buildMergeValues(Result, {LowHalf, HighHalf});
6413 NumRecords =
B.buildTrunc(I32, NumRecords).getReg(0);
6414 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6415 auto LowHalf = Unmerge.getReg(0);
6416 auto HighHalf = Unmerge.getReg(1);
6418 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6419 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6420 auto ShiftConst =
B.buildConstant(I32, 16);
6421 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6422 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6423 Register NewHighHalfReg = NewHighHalf.getReg(0);
6424 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6427 MI.eraseFromParent();
6444 MI.eraseFromParent();
6452 std::optional<uint32_t> KnownSize =
6454 if (KnownSize.has_value())
6455 B.buildConstant(DstReg, *KnownSize);
6473 MI.eraseFromParent();
6480 unsigned AddrSpace)
const {
6482 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6486 ST.hasGloballyAddressableScratch()) {
6488 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6489 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6491 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6493 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6495 B.buildConstant(I32, 1u << 26));
6500 MI.eraseFromParent();
6510std::pair<Register, unsigned>
6522 bool CheckNUW = ST.hasGFX1250Insts();
6524 MRI, OrigOffset,
nullptr, CheckNUW);
6528 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6538 unsigned Overflow = ImmOffset & ~MaxImm;
6539 ImmOffset -= Overflow;
6540 if ((int32_t)Overflow < 0) {
6541 Overflow += ImmOffset;
6545 if (Overflow != 0) {
6547 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6549 auto OverflowVal =
B.buildConstant(I32, Overflow);
6550 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6555 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6557 return std::pair(BaseReg, ImmOffset);
6564 bool ImageStore)
const {
6572 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6574 if (ST.hasUnpackedD16VMem()) {
6575 auto Unmerge =
B.buildUnmerge(
I16, RegI16);
6578 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6579 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6587 if (ImageStore && ST.hasImageStoreD16Bug()) {
6590 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6592 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6599 auto Unmerge =
B.buildUnmerge(
I16, RegI16);
6600 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6602 PackedRegs.
resize(6,
B.buildUndef(
I16).getReg(0));
6610 auto Unmerge =
B.buildUnmerge(I32, Reg);
6611 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6613 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6623 Reg =
B.buildPadVectorWithUndefElements(
6632 bool IsFormat)
const {
6642 VData =
B.buildBitcast(Ty, VData).getReg(0);
6650 if (Ty.isVector()) {
6651 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6663 bool IsFormat)
const {
6670 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6677 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6678 const Function &Fn =
B.getMF().getFunction();
6680 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6681 MI.eraseFromParent();
6693 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6696 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6700 VIndex =
MI.getOperand(3).getReg();
6703 VIndex =
B.buildConstant(I32, 0).getReg(0);
6706 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6707 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6711 Format =
MI.getOperand(5 + OpOffset).getImm();
6715 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6721 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6722 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6723 }
else if (IsFormat) {
6724 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6725 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6729 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6732 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6735 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6740 auto MIB =
B.buildInstr(
Opc)
6751 MIB.addImm(AuxiliaryData)
6752 .addImm(HasVIndex ? -1 : 0)
6753 .addMemOperand(MMO);
6755 MI.eraseFromParent();
6761 unsigned ImmOffset,
unsigned Format,
6764 auto MIB =
B.buildInstr(
Opc)
6775 MIB.addImm(AuxiliaryData)
6776 .addImm(HasVIndex ? -1 : 0)
6777 .addMemOperand(MMO);
6783 bool IsTyped)
const {
6797 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6798 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6800 StatusDst =
MI.getOperand(1).getReg();
6805 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6808 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6811 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6814 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6817 VIndex =
B.buildConstant(I32, 0).getReg(0);
6820 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6821 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6825 Format =
MI.getOperand(5 + OpOffset).getImm();
6829 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6839 Dst =
MI.getOperand(0).getReg();
6840 B.setInsertPt(
B.getMBB(),
MI);
6847 Dst =
MI.getOperand(0).getReg();
6848 B.setInsertPt(
B.getMBB(),
MI);
6852 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6853 const bool Unpacked = ST.hasUnpackedD16VMem();
6855 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6856 const Function &Fn =
B.getMF().getFunction();
6858 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6861 B.buildUndef(StatusDst);
6862 MI.eraseFromParent();
6874 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6875 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6876 }
else if (IsFormat) {
6880 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6882 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6883 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6888 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6889 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6892 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6893 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6896 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6897 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6903 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6904 unsigned NumLoadDWords = NumValueDWords + 1;
6906 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6908 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6909 bool IsFloat = Ty.getScalarType().isFloat();
6914 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6916 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6917 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6918 B.buildTrunc(DstInt, ExtDst);
6919 }
else if (NumValueDWords == 1) {
6920 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6923 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6924 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6926 B.buildUnmerge(LoadElts, LoadDstReg);
6928 B.buildMergeLikeInstr(DstInt, LoadElts);
6931 B.buildBitcast(Dst, DstInt);
6933 (IsD16 && !Ty.isVector())) {
6934 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6936 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6937 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6938 B.buildTrunc(Dst, LoadDstReg);
6939 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6941 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6943 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6944 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6946 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6948 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6949 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6950 B.buildMergeLikeInstr(Dst, Repack);
6953 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6956 MI.eraseFromParent();
6962 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6963 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6964 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6965 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6966 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6967 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6968 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6969 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6970 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6971 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6972 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6973 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6974 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6975 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6976 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6977 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6978 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6979 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6980 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6981 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6982 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6983 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6984 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6985 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
6986 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
6987 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
6988 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
6989 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
6990 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
6991 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
6992 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
6993 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
6994 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
6995 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
6996 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
6997 case Intrinsic::amdgcn_raw_buffer_atomic_and:
6998 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
6999 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7000 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7001 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7002 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7003 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7004 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7005 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7006 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7007 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7008 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7009 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7010 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7011 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7012 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7013 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7014 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7015 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7016 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7017 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7018 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7019 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7020 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7021 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7022 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7023 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7024 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7025 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7026 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7027 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7028 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7029 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7030 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7031 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7032 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7033 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7034 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7036 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7037 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7038 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7039 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7040 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7041 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7042 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7043 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7044 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7045 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7046 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7047 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7048 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7049 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7050 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7051 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7060 const bool IsCmpSwap =
7061 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7062 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7063 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7064 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7075 CmpVal =
MI.getOperand(3).getReg();
7080 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7081 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7084 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7087 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7093 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7094 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7095 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7114 .addImm(AuxiliaryData)
7115 .addImm(HasVIndex ? -1 : 0)
7116 .addMemOperand(MMO);
7118 MI.eraseFromParent();
7128 bool IsA16,
bool IsG16) {
7142 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7147 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7151 "Bias needs to be converted to 16 bit in A16 mode");
7153 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7157 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7161 if (((
I + 1) >= EndIdx) ||
7168 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7170 B.buildBuildVector(V2EltTy,
7171 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7176 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7187 int DimIdx,
int NumVAddrs) {
7189 for (
int I = 0;
I != NumVAddrs; ++
I) {
7191 if (
SrcOp.isReg()) {
7194 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7195 if (
B.getMRI()->getType(
Reg) != I32)
7196 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7201 int NumAddrRegs = AddrRegs.
size();
7202 if (NumAddrRegs != 1) {
7203 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7206 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7209 for (
int I = 1;
I != NumVAddrs; ++
I) {
7212 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7234 const unsigned NumDefs =
MI.getNumExplicitDefs();
7235 const unsigned ArgOffset = NumDefs + 1;
7236 bool IsTFE = NumDefs == 2;
7254 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7258 const bool IsAtomicPacked16Bit =
7259 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7260 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7267 const bool GradTyIs16 = GradTy ==
I16 || GradTy ==
F16;
7268 const bool AddrTyIs16 = AddrTy ==
I16 || AddrTy ==
F16;
7269 const bool DataTyIs16 =
7270 Ty.getScalarType() ==
I16 || Ty.getScalarType() ==
F16;
7272 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7273 const bool IsA16 = AddrTyIs16;
7274 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7277 if (!BaseOpcode->
Atomic) {
7278 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7281 }
else if (DMask != 0) {
7283 }
else if (!IsTFE && !BaseOpcode->
Store) {
7285 B.buildUndef(
MI.getOperand(0));
7286 MI.eraseFromParent();
7294 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7295 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7296 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7297 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7298 unsigned NewOpcode = LoadOpcode;
7299 if (BaseOpcode->
Store)
7300 NewOpcode = StoreOpcode;
7302 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7305 MI.setDesc(
B.getTII().get(NewOpcode));
7309 if (IsTFE && DMask == 0) {
7312 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7315 if (BaseOpcode->
Atomic) {
7320 if (Ty.isVector() && !IsAtomicPacked16Bit)
7327 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7328 MI.getOperand(2).setReg(
Concat.getReg(0));
7329 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7333 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7336 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7342 if (IsA16 && !ST.hasA16()) {
7347 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7348 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7350 if (IsA16 || IsG16) {
7358 const bool UseNSA = ST.hasNSAEncoding() &&
7359 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7360 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7361 const bool UsePartialNSA =
7362 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7364 if (UsePartialNSA) {
7368 auto Concat =
B.buildConcatVectors(
7369 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7370 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7371 PackedRegs.
resize(NSAMaxSize);
7372 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7374 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7375 PackedRegs[0] =
Concat.getReg(0);
7379 const unsigned NumPacked = PackedRegs.
size();
7382 if (!
SrcOp.isReg()) {
7392 SrcOp.setReg(AMDGPU::NoRegister);
7409 const bool UseNSA = ST.hasNSAEncoding() &&
7410 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7411 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7412 const bool UsePartialNSA =
7413 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7415 if (UsePartialNSA) {
7417 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7419 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7434 if (!Ty.isVector() || !IsD16)
7438 if (RepackedReg != VData) {
7439 MI.getOperand(1).setReg(RepackedReg);
7447 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7450 if (NumElts < DMaskLanes)
7453 if (NumElts > 4 || DMaskLanes > 4)
7464 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7465 const LLT AdjustedTy =
7481 if (IsD16 && ST.hasUnpackedD16VMem()) {
7488 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7489 unsigned RoundedSize = 32 * RoundedElts;
7493 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7498 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7504 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7508 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7509 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7513 MI.getOperand(0).setReg(NewResultReg);
7521 Dst1Reg =
MI.getOperand(1).getReg();
7522 if (MRI->
getType(Dst1Reg) != I32)
7526 MI.removeOperand(1);
7529 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7530 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7531 B.buildBitcast(DstReg, Unmerge.getReg(0));
7532 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7541 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7543 if (ResultNumRegs == 1) {
7545 ResultRegs[0] = NewResultReg;
7548 for (
int I = 0;
I != NumDataRegs; ++
I)
7550 B.buildUnmerge(ResultRegs, NewResultReg);
7555 ResultRegs.
resize(NumDataRegs);
7560 if (IsD16 && !Ty.isVector()) {
7561 B.buildTrunc(DstReg, ResultRegs[0]);
7566 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7567 !ST.hasUnpackedD16VMem()) {
7568 B.buildBitcast(DstReg, ResultRegs[0]);
7580 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7582 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7583 }
else if (ST.hasUnpackedD16VMem()) {
7585 Reg =
B.buildTrunc(
I16, Reg).getReg(0);
7589 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7593 for (
int I = 0;
I != NumElts; ++
I)
7600 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7601 B.buildBuildVector(DstReg, ResultRegs);
7605 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7606 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7611 if (Ty == V3I16 || Ty == V3F16) {
7613 if (ResultRegs.
size() == 1) {
7614 NewResultReg = ResultRegs[0];
7615 }
else if (ResultRegs.
size() == 2) {
7617 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7632 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7634 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7636 if (ResizeDst != DstReg)
7637 B.buildBitcast(DstReg, ResizeDst);
7641 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7642 B.buildConcatVectors(DstReg, ResultRegs);
7651 Register OrigDst =
MI.getOperand(0).getReg();
7653 LLT Ty =
B.getMRI()->getType(OrigDst);
7654 unsigned Size = Ty.getSizeInBits();
7657 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7659 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7660 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7663 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7665 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7674 B.setInsertPt(
B.getMBB(),
MI);
7679 B.setInsertPt(
B.getMBB(),
MI);
7685 MI.setDesc(
B.getTII().get(
Opc));
7686 MI.removeOperand(1);
7689 const unsigned MemSize = (
Size + 7) / 8;
7690 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7697 MI.addMemOperand(MF, MMO);
7698 if (Dst != OrigDst) {
7699 MI.getOperand(0).setReg(Dst);
7700 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7701 B.buildTrunc(OrigDst, Dst);
7723 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7724 MI.removeOperand(0);
7734 if (!ST.hasTrapHandler() ||
7738 return ST.supportsGetDoorbellID() ?
7751 MI.eraseFromParent();
7761 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7763 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7767 MI.eraseFromParent();
7776 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7783 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7803 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7806 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7807 B.buildCopy(SGPR01, Temp);
7808 B.buildInstr(AMDGPU::S_TRAP)
7811 MI.eraseFromParent();
7822 B.buildCopy(SGPR01, LiveIn);
7823 B.buildInstr(AMDGPU::S_TRAP)
7827 MI.eraseFromParent();
7836 if (ST.hasPrivEnabledTrap2NopBug()) {
7837 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7839 MI.eraseFromParent();
7843 B.buildInstr(AMDGPU::S_TRAP)
7845 MI.eraseFromParent();
7854 if (!ST.hasTrapHandler() ||
7858 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7861 B.buildInstr(AMDGPU::S_TRAP)
7865 MI.eraseFromParent();
7879 Register NodePtr =
MI.getOperand(2).getReg();
7880 Register RayExtent =
MI.getOperand(3).getReg();
7881 Register RayOrigin =
MI.getOperand(4).getReg();
7883 Register RayInvDir =
MI.getOperand(6).getReg();
7886 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7893 const unsigned NumVDataDwords = 4;
7894 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7895 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7897 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7899 const unsigned BaseOpcodes[2][2] = {
7900 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7901 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7902 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7906 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7907 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7908 : AMDGPU::MIMGEncGfx10NSA,
7909 NumVDataDwords, NumVAddrDwords);
7913 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7914 : AMDGPU::MIMGEncGfx10Default,
7915 NumVDataDwords, NumVAddrDwords);
7920 if (UseNSA && IsGFX11Plus) {
7921 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7922 auto SrcInt =
B.buildBitcast(V3I32, Src);
7923 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7924 auto Merged =
B.buildMergeLikeInstr(
7925 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7926 Ops.push_back(Merged.getReg(0));
7929 Ops.push_back(NodePtr);
7930 Ops.push_back(RayExtent);
7931 packLanes(RayOrigin);
7934 auto UnmergeRayDir =
7935 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayDir));
7936 auto UnmergeRayInvDir =
7937 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayInvDir));
7938 auto MergedDir =
B.buildMergeLikeInstr(
7941 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7942 UnmergeRayDir.getReg(0)}))
7945 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7946 UnmergeRayDir.getReg(1)}))
7949 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7950 UnmergeRayDir.getReg(2)}))
7952 Ops.push_back(MergedDir.getReg(0));
7955 packLanes(RayInvDir);
7959 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7960 Ops.push_back(Unmerge.getReg(0));
7961 Ops.push_back(Unmerge.getReg(1));
7963 Ops.push_back(NodePtr);
7965 Ops.push_back(RayExtent);
7967 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7968 auto SrcInt =
B.buildBitcast(V3I32, Src);
7969 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7970 Ops.push_back(Unmerge.getReg(0));
7971 Ops.push_back(Unmerge.getReg(1));
7972 Ops.push_back(Unmerge.getReg(2));
7975 packLanes(RayOrigin);
7977 auto UnmergeRayDir =
7978 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayDir));
7979 auto UnmergeRayInvDir =
7980 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayInvDir));
7984 B.buildMergeLikeInstr(R1,
7985 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
7986 B.buildMergeLikeInstr(
7987 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
7988 B.buildMergeLikeInstr(
7989 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
7995 packLanes(RayInvDir);
8004 Ops.push_back(MergedOps);
8007 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8016 .addImm(IsA16 ? 1 : 0)
8019 MI.eraseFromParent();
8029 Register DstOrigin =
MI.getOperand(1).getReg();
8031 Register NodePtr =
MI.getOperand(4).getReg();
8032 Register RayExtent =
MI.getOperand(5).getReg();
8033 Register InstanceMask =
MI.getOperand(6).getReg();
8034 Register RayOrigin =
MI.getOperand(7).getReg();
8036 Register Offsets =
MI.getOperand(9).getReg();
8037 Register TDescr =
MI.getOperand(10).getReg();
8040 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8041 const unsigned NumVDataDwords = 10;
8042 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8044 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8045 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8046 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8049 auto RayExtentInstanceMaskVec =
8050 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8051 B.buildAnyExt(I32, InstanceMask)});
8053 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8054 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8060 .addUse(RayExtentInstanceMaskVec.getReg(0))
8067 MI.eraseFromParent();
8076 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8077 MI.eraseFromParent();
8084 if (!ST.hasArchitectedSGPRs())
8088 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8089 auto LSB =
B.buildConstant(I32, 25);
8090 auto Width =
B.buildConstant(I32, 5);
8091 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8092 MI.eraseFromParent();
8100 unsigned Width)
const {
8104 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8105 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8108 MI.eraseFromParent();
8128 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8132 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8135 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8136 MI.eraseFromParent();
8149 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8153 .addReg(Unmerge.getReg(0));
8157 .addReg(Unmerge.getReg(1));
8158 MI.eraseFromParent();
8170 case Intrinsic::amdgcn_icmp: {
8181 if (!Src1Const || Src1Const->Value != 0)
8185 int64_t Pred =
MI.getOperand(4).getImm();
8191 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8192 MI.eraseFromParent();
8195 case Intrinsic::sponentry:
8201 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8204 B.buildIntToPtr(DstReg, TmpReg);
8205 MI.eraseFromParent();
8207 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8209 B.buildFrameIndex(
MI.getOperand(0), FI);
8210 MI.eraseFromParent();
8213 case Intrinsic::amdgcn_if:
8214 case Intrinsic::amdgcn_else: {
8217 bool Negated =
false;
8229 std::swap(CondBrTarget, UncondBrTarget);
8231 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8232 if (IntrID == Intrinsic::amdgcn_if) {
8233 B.buildInstr(AMDGPU::SI_IF)
8236 .addMBB(UncondBrTarget);
8238 B.buildInstr(AMDGPU::SI_ELSE)
8241 .addMBB(UncondBrTarget);
8250 B.buildBr(*CondBrTarget);
8255 MI.eraseFromParent();
8256 BrCond->eraseFromParent();
8262 case Intrinsic::amdgcn_loop: {
8265 bool Negated =
false;
8275 std::swap(CondBrTarget, UncondBrTarget);
8277 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8278 B.buildInstr(AMDGPU::SI_LOOP)
8280 .addMBB(UncondBrTarget);
8285 B.buildBr(*CondBrTarget);
8287 MI.eraseFromParent();
8288 BrCond->eraseFromParent();
8295 case Intrinsic::amdgcn_wave_reduce_min:
8296 case Intrinsic::amdgcn_wave_reduce_umin:
8297 case Intrinsic::amdgcn_wave_reduce_fmin:
8298 case Intrinsic::amdgcn_wave_reduce_max:
8299 case Intrinsic::amdgcn_wave_reduce_umax:
8300 case Intrinsic::amdgcn_wave_reduce_fmax:
8301 case Intrinsic::amdgcn_wave_reduce_add:
8302 case Intrinsic::amdgcn_wave_reduce_fadd:
8303 case Intrinsic::amdgcn_wave_reduce_sub:
8304 case Intrinsic::amdgcn_wave_reduce_fsub:
8305 case Intrinsic::amdgcn_wave_reduce_and:
8306 case Intrinsic::amdgcn_wave_reduce_or:
8307 case Intrinsic::amdgcn_wave_reduce_xor: {
8312 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8313 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8314 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8315 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8316 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8317 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8318 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8319 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8320 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8327 .addUse(Ext.getReg(0))
8328 .addImm(
MI.getOperand(3).getImm());
8330 B.buildFPTrunc(DstReg, NewDst);
8332 B.buildTrunc(DstReg, NewDst);
8333 MI.eraseFromParent();
8336 case Intrinsic::amdgcn_addrspacecast_nonnull:
8338 case Intrinsic::amdgcn_make_buffer_rsrc:
8340 case Intrinsic::amdgcn_kernarg_segment_ptr:
8343 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8344 MI.eraseFromParent();
8350 case Intrinsic::amdgcn_implicitarg_ptr:
8352 case Intrinsic::amdgcn_workitem_id_x:
8355 case Intrinsic::amdgcn_workitem_id_y:
8358 case Intrinsic::amdgcn_workitem_id_z:
8361 case Intrinsic::amdgcn_workgroup_id_x:
8366 case Intrinsic::amdgcn_workgroup_id_y:
8371 case Intrinsic::amdgcn_workgroup_id_z:
8376 case Intrinsic::amdgcn_cluster_id_x:
8377 return ST.hasClusters() &&
8380 case Intrinsic::amdgcn_cluster_id_y:
8381 return ST.hasClusters() &&
8384 case Intrinsic::amdgcn_cluster_id_z:
8385 return ST.hasClusters() &&
8388 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8389 return ST.hasClusters() &&
8392 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8393 return ST.hasClusters() &&
8396 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8397 return ST.hasClusters() &&
8400 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8401 return ST.hasClusters() &&
8403 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8404 return ST.hasClusters() &&
8407 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8408 return ST.hasClusters() &&
8411 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8412 return ST.hasClusters() &&
8415 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8416 return ST.hasClusters() &&
8420 case Intrinsic::amdgcn_wave_id:
8422 case Intrinsic::amdgcn_lds_kernel_id:
8425 case Intrinsic::amdgcn_dispatch_ptr:
8428 case Intrinsic::amdgcn_queue_ptr:
8431 case Intrinsic::amdgcn_implicit_buffer_ptr:
8434 case Intrinsic::amdgcn_dispatch_id:
8437 case Intrinsic::r600_read_ngroups_x:
8441 case Intrinsic::r600_read_ngroups_y:
8444 case Intrinsic::r600_read_ngroups_z:
8447 case Intrinsic::r600_read_local_size_x:
8450 case Intrinsic::r600_read_local_size_y:
8454 case Intrinsic::r600_read_local_size_z:
8457 case Intrinsic::amdgcn_fdiv_fast:
8459 case Intrinsic::amdgcn_is_shared:
8461 case Intrinsic::amdgcn_is_private:
8463 case Intrinsic::amdgcn_wavefrontsize: {
8464 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8465 MI.eraseFromParent();
8468 case Intrinsic::amdgcn_s_buffer_load:
8470 case Intrinsic::amdgcn_raw_buffer_store:
8471 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8472 case Intrinsic::amdgcn_struct_buffer_store:
8473 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8475 case Intrinsic::amdgcn_raw_buffer_store_format:
8476 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8477 case Intrinsic::amdgcn_struct_buffer_store_format:
8478 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8480 case Intrinsic::amdgcn_raw_tbuffer_store:
8481 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8482 case Intrinsic::amdgcn_struct_tbuffer_store:
8483 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8485 case Intrinsic::amdgcn_raw_buffer_load:
8486 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8487 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8488 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8489 case Intrinsic::amdgcn_struct_buffer_load:
8490 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8491 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8492 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8494 case Intrinsic::amdgcn_raw_buffer_load_format:
8495 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8496 case Intrinsic::amdgcn_struct_buffer_load_format:
8497 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8499 case Intrinsic::amdgcn_raw_tbuffer_load:
8500 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8501 case Intrinsic::amdgcn_struct_tbuffer_load:
8502 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8504 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8505 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8506 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8507 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8508 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8509 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8510 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8511 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8512 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8513 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8514 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8515 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8516 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8517 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8518 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8519 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8520 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8521 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8522 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8523 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8524 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8525 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8526 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8527 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8528 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8529 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8530 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8531 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8532 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8533 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8534 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8535 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8536 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8537 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8538 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8539 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8540 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8541 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8542 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8543 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8544 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8545 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8546 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8547 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8548 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8549 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8550 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8551 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8552 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8553 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8554 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8555 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8556 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8557 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8558 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8559 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8560 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8561 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8562 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8563 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8564 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8565 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8566 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8567 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8568 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8569 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8570 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8571 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8572 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8573 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8574 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8575 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8577 case Intrinsic::amdgcn_rsq_clamp:
8579 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8581 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8582 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8584 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8585 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8586 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8587 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8588 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8589 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8590 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8591 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8595 if (IndexArgTy != I64) {
8596 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8597 :
B.buildAnyExt(I64, Index);
8598 MI.getOperand(5).setReg(NewIndex.getReg(0));
8602 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8603 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8604 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8605 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8606 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8607 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8608 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8609 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8612 if (MRI.
getType(Index) != I32)
8613 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8616 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8617 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8618 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8619 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8620 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8621 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8622 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8623 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8624 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8626 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8630 if (IndexArgTy != IdxTy) {
8631 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8632 :
B.buildAnyExt(IdxTy, Index);
8633 MI.getOperand(7).setReg(NewIndex.getReg(0));
8638 case Intrinsic::amdgcn_fmed3: {
8644 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8645 MI.removeOperand(1);
8649 case Intrinsic::amdgcn_readlane:
8650 case Intrinsic::amdgcn_writelane:
8651 case Intrinsic::amdgcn_readfirstlane:
8652 case Intrinsic::amdgcn_permlane16:
8653 case Intrinsic::amdgcn_permlanex16:
8654 case Intrinsic::amdgcn_permlane64:
8655 case Intrinsic::amdgcn_set_inactive:
8656 case Intrinsic::amdgcn_set_inactive_chain_arg:
8657 case Intrinsic::amdgcn_mov_dpp8:
8658 case Intrinsic::amdgcn_update_dpp:
8659 case Intrinsic::amdgcn_permlane_bcast:
8660 case Intrinsic::amdgcn_permlane_up:
8661 case Intrinsic::amdgcn_permlane_down:
8662 case Intrinsic::amdgcn_permlane_xor:
8664 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8666 case Intrinsic::amdgcn_dead: {
8670 MI.eraseFromParent();
8673 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8674 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8675 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8676 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8677 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8678 MI.eraseFromParent();
8680 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8681 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8682 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8683 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8684 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8685 MI.eraseFromParent();
8687 case Intrinsic::amdgcn_av_load_b128:
8688 case Intrinsic::amdgcn_av_store_b128: {
8689 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8690 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8691 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8693 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8694 **
MI.memoperands_begin());
8695 MI.eraseFromParent();
8698 case Intrinsic::amdgcn_flat_load_monitor_b32:
8699 case Intrinsic::amdgcn_flat_load_monitor_b64:
8700 case Intrinsic::amdgcn_flat_load_monitor_b128:
8701 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8702 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8703 .add(
MI.getOperand(0))
8704 .add(
MI.getOperand(2))
8705 .addMemOperand(*
MI.memoperands_begin());
8706 MI.eraseFromParent();
8708 case Intrinsic::amdgcn_global_load_monitor_b32:
8709 case Intrinsic::amdgcn_global_load_monitor_b64:
8710 case Intrinsic::amdgcn_global_load_monitor_b128:
8711 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8712 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8713 .add(
MI.getOperand(0))
8714 .add(
MI.getOperand(2))
8715 .addMemOperand(*
MI.memoperands_begin());
8716 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 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.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
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
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 legalizeTrapHsa(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 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 getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, 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 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 legalizeLDSKernelId(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 legalizeFPow(MachineInstr &MI, MachineIRBuilder &B) 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 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
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
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(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 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)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
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.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
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 & unsupported()
The instruction is unsupported.
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 & 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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
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...
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 & 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 bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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...
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 truncate(size_type N)
Like resize, but requires that N is less than size().
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...
unsigned getPointerSizeInBits(unsigned AS) const
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.
@ 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.
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
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)
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)
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.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
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 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
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.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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.
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.