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();
1163 if (ST.has16BitInsts()) {
1177 if (ST.hasPackedFP32Ops())
1187 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1188 FMad.customFor({
S32,
S16});
1189 else if (ST.hasMadMacF32Insts())
1190 FMad.customFor({
S32});
1191 else if (ST.hasMadF16())
1192 FMad.customFor({
S16});
1197 if (ST.has16BitInsts()) {
1200 FRem.minScalar(0,
S32)
1209 .clampMaxNumElements(0,
S16, 2)
1229 if (ST.has16BitInsts())
1241 if (ST.has16BitInsts())
1254 .legalFor(ST.has16BitInsts(), {{S16, S16}})
1255 .legalFor(ST.hasVCvtPkIU16F32(), {{V2S16, V2S32}})
1259 if (
ST.has16BitInsts())
1262 if (
ST.hasVCvtPkIU16F32())
1272 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1273 .clampScalar(0,
S16,
S64)
1277 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1283 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1287 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1288 .clampScalar(0,
S16,
S64)
1292 if (
ST.has16BitInsts()) {
1293 getActionDefinitionsBuilder(
1294 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1296 .clampScalar(0,
S16,
S64)
1299 getActionDefinitionsBuilder(
1300 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1302 .clampScalar(0,
S32,
S64)
1305 getActionDefinitionsBuilder(
1306 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1309 .clampScalar(0,
S32,
S64)
1313 getActionDefinitionsBuilder(G_PTR_ADD)
1319 getActionDefinitionsBuilder(G_PTRMASK)
1321 .scalarSameSizeAs(1, 0)
1325 getActionDefinitionsBuilder(G_ICMP)
1337 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1338 .legalForCartesianProduct(
1339 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1340 if (
ST.has16BitInsts()) {
1341 CmpBuilder.legalFor({{
S1,
S16}});
1352 {
S1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1354 if (
ST.hasSALUFloatInsts())
1363 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1364 if (
ST.has16BitInsts())
1365 ExpOps.customFor({{
S32}, {
S16}});
1367 ExpOps.customFor({
S32});
1368 ExpOps.clampScalar(0, MinScalarFPTy,
S32)
1371 getActionDefinitionsBuilder(G_FPOWI)
1372 .clampScalar(0, MinScalarFPTy,
S32)
1375 getActionDefinitionsBuilder(G_FLOG2)
1376 .legalFor(
ST.has16BitInsts(), {S16})
1381 getActionDefinitionsBuilder(G_FEXP2)
1382 .legalFor(
ST.has16BitInsts(), {S16})
1388 getActionDefinitionsBuilder({G_FLOG, G_FLOG10, G_FEXP, G_FEXP10});
1390 LogOps.clampScalar(0, MinScalarFPTy,
S32)
1394 getActionDefinitionsBuilder(G_CTPOP)
1396 .clampScalar(0,
S32,
S32)
1397 .widenScalarToNextPow2(1, 32)
1398 .clampScalar(1,
S32,
S64)
1400 .widenScalarToNextPow2(0, 32);
1403 if (
ST.has16BitInsts())
1404 getActionDefinitionsBuilder(G_IS_FPCLASS)
1405 .legalForCartesianProduct({
S1}, FPTypes16)
1406 .widenScalarToNextPow2(1)
1410 getActionDefinitionsBuilder(G_IS_FPCLASS)
1411 .legalForCartesianProduct({
S1}, FPTypesBase)
1412 .lowerFor({
S1,
S16})
1413 .widenScalarToNextPow2(1)
1420 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1422 .clampScalar(0,
S32,
S32)
1423 .clampScalar(1,
S32,
S64)
1424 .widenScalarToNextPow2(0, 32)
1425 .widenScalarToNextPow2(1, 32)
1429 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1432 .clampScalar(0,
S32,
S32)
1433 .clampScalar(1,
S32,
S64)
1435 .widenScalarToNextPow2(0, 32)
1436 .widenScalarToNextPow2(1, 32);
1438 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1440 .clampScalar(0,
S32,
S32)
1441 .clampScalar(1,
S32,
S64)
1443 .widenScalarToNextPow2(0, 32)
1444 .widenScalarToNextPow2(1, 32);
1446 getActionDefinitionsBuilder(G_CTLS)
1449 .clampScalar(0,
S32,
S32)
1450 .clampScalar(1,
S32,
S32);
1454 getActionDefinitionsBuilder(G_BITREVERSE)
1456 .clampScalar(0,
S32,
S64)
1458 .widenScalarToNextPow2(0);
1460 if (
ST.has16BitInsts()) {
1461 getActionDefinitionsBuilder(G_BSWAP)
1463 .clampMaxNumElementsStrict(0,
S16, 2)
1466 .widenScalarToNextPow2(0)
1467 .clampScalar(0,
S16,
S32)
1470 if (
ST.hasVOP3PInsts()) {
1471 getActionDefinitionsBuilder(G_ABS)
1473 .clampMaxNumElements(0,
S16, 2)
1475 .widenScalarToNextPow2(0)
1478 if (
ST.hasMinMaxI64Insts()) {
1479 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1481 .clampMaxNumElements(0,
S16, 2)
1483 .widenScalarToNextPow2(0)
1487 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1489 .clampMaxNumElements(0,
S16, 2)
1491 .widenScalarToNextPow2(0)
1496 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1498 .widenScalarToNextPow2(0)
1505 getActionDefinitionsBuilder(G_BSWAP)
1510 .widenScalarToNextPow2(0)
1515 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1518 .widenScalarToNextPow2(0)
1523 getActionDefinitionsBuilder(G_INTTOPTR)
1525 .legalForCartesianProduct(AddrSpaces64, {
S64})
1526 .legalForCartesianProduct(AddrSpaces32, {
S32})
1539 getActionDefinitionsBuilder(G_PTRTOINT)
1541 .legalForCartesianProduct(AddrSpaces64, {
S64})
1542 .legalForCartesianProduct(AddrSpaces32, {
S32})
1555 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1559 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1560 bool IsLoad) ->
bool {
1564 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1578 unsigned NumRegs = (MemSize + 31) / 32;
1580 if (!
ST.hasDwordx3LoadStores())
1591 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1592 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1593 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1599 for (
unsigned Op : {G_LOAD, G_STORE}) {
1600 const bool IsStore =
Op == G_STORE;
1602 auto &Actions = getActionDefinitionsBuilder(
Op);
1605 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1608 {
S64, GlobalPtr,
S64, GlobalAlign32},
1611 {
S32, GlobalPtr,
S8, GlobalAlign8},
1612 {
S32, GlobalPtr,
S16, GlobalAlign16},
1614 {
S32, LocalPtr,
S32, 32},
1615 {
S64, LocalPtr,
S64, 32},
1617 {
S32, LocalPtr,
S8, 8},
1618 {
S32, LocalPtr,
S16, 16},
1621 {
S32, PrivatePtr,
S32, 32},
1622 {
S32, PrivatePtr,
S8, 8},
1623 {
S32, PrivatePtr,
S16, 16},
1626 {
S32, ConstantPtr,
S32, GlobalAlign32},
1629 {
S64, ConstantPtr,
S64, GlobalAlign32},
1630 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1632 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1633 {{S16, GlobalPtr, S8, GlobalAlign8},
1634 {S16, GlobalPtr, S16, GlobalAlign16},
1635 {S16, LocalPtr, S8, 8},
1636 {S16, LocalPtr, S16, 16},
1637 {S16, PrivatePtr, S8, 8},
1638 {S16, PrivatePtr, S16, 16}});
1648 Actions.unsupportedIf(
1649 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1663 Actions.customIf(
typeIs(1, Constant32Ptr));
1689 return !Query.
Types[0].isVector() &&
1690 needToSplitMemOp(Query,
Op == G_LOAD);
1692 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1697 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1700 if (DstSize > MemSize)
1706 if (MemSize > MaxSize)
1714 return Query.
Types[0].isVector() &&
1715 needToSplitMemOp(Query,
Op == G_LOAD);
1717 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1731 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1732 if (MemSize > MaxSize) {
1736 if (MaxSize % EltSize == 0) {
1742 unsigned NumPieces = MemSize / MaxSize;
1746 if (NumPieces == 1 || NumPieces >= NumElts ||
1747 NumElts % NumPieces != 0)
1748 return std::pair(0, EltTy);
1756 return std::pair(0, EltTy);
1771 return std::pair(0, EltTy);
1776 .widenScalarToNextPow2(0)
1783 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1784 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1785 {
S32, GlobalPtr,
S16, 2 * 8},
1786 {
S32, LocalPtr,
S8, 8},
1787 {
S32, LocalPtr,
S16, 16},
1788 {
S32, PrivatePtr,
S8, 8},
1789 {
S32, PrivatePtr,
S16, 16},
1790 {
S32, ConstantPtr,
S8, 8},
1791 {
S32, ConstantPtr,
S16, 2 * 8}})
1792 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1793 {{S16, GlobalPtr, S8, GlobalAlign8},
1794 {S16, LocalPtr, S8, GlobalAlign8},
1795 {S16, PrivatePtr, S8, GlobalAlign8},
1796 {S16, ConstantPtr, S8, GlobalAlign8}})
1801 if (
ST.hasFlatAddressSpace()) {
1802 ExtLoads.legalForTypesWithMemDesc(
1803 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1805 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1806 {{S16, FlatPtr, S8, GlobalAlign8}});
1814 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1816 ExtLoads.narrowScalarIf(
1823 ExtLoads.clampScalar(0,
S32,
S32)
1824 .widenScalarToNextPow2(0)
1827 auto &Atomics = getActionDefinitionsBuilder(
1828 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1829 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1830 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1831 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1832 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1833 {
S64, GlobalPtr}, {
S64, LocalPtr},
1834 {
S32, RegionPtr}, {
S64, RegionPtr}});
1835 if (
ST.hasFlatAddressSpace()) {
1836 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1840 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1841 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1842 if (
ST.hasFlatAddressSpace()) {
1843 Atomics32.legalFor({{
S32, FlatPtr}});
1847 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1848 if (
ST.hasLDSFPAtomicAddF32()) {
1849 Atomic.legalFor({{
S32, LocalPtr}, {
S32, RegionPtr}});
1850 if (
ST.hasLdsAtomicAddF64())
1851 Atomic.legalFor({{
S64, LocalPtr}});
1852 if (
ST.hasAtomicDsPkAdd16Insts())
1853 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1855 if (
ST.hasAtomicFaddInsts())
1856 Atomic.legalFor({{
S32, GlobalPtr}});
1857 if (
ST.hasFlatAtomicFaddF32Inst())
1858 Atomic.legalFor({{
S32, FlatPtr}});
1860 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1871 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1872 ST.hasAtomicBufferGlobalPkAddF16Insts())
1873 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1874 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1875 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1876 if (
ST.hasAtomicFlatPkAdd16Insts())
1877 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1882 auto &AtomicFMinFMax =
1883 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1884 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1886 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1887 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1888 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1889 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1890 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1891 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1892 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1893 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1897 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1898 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1899 {
S32, FlatPtr}, {
S64, FlatPtr}})
1900 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1901 {
S32, RegionPtr}, {
S64, RegionPtr}});
1905 getActionDefinitionsBuilder(G_SELECT)
1907 LocalPtr, FlatPtr, PrivatePtr,
1911 .clampScalar(0,
S16,
S64)
1915 .clampMaxNumElements(0,
S32, 2)
1916 .clampMaxNumElements(0, LocalPtr, 2)
1917 .clampMaxNumElements(0, PrivatePtr, 2)
1919 .widenScalarToNextPow2(0)
1924 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1926 if (
ST.has16BitInsts()) {
1927 if (
ST.hasVOP3PInsts()) {
1929 .clampMaxNumElements(0,
S16, 2);
1931 Shifts.legalFor({{
S16,
S16}});
1934 Shifts.widenScalarIf(
1939 const LLT AmountTy = Query.
Types[1];
1945 Shifts.clampScalar(1,
S32,
S32);
1946 Shifts.widenScalarToNextPow2(0, 16);
1947 Shifts.clampScalar(0,
S16,
S64);
1949 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1957 Shifts.clampScalar(1,
S32,
S32);
1958 Shifts.widenScalarToNextPow2(0, 32);
1959 Shifts.clampScalar(0,
S32,
S64);
1961 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1966 Shifts.scalarize(0);
1968 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1969 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1970 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1971 unsigned IdxTypeIdx = 2;
1973 getActionDefinitionsBuilder(
Op)
1975 const LLT EltTy = Query.
Types[EltTypeIdx];
1976 const LLT VecTy = Query.
Types[VecTypeIdx];
1977 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1979 const bool isLegalVecType =
1989 return (EltSize == 32 || EltSize == 64) &&
2005 const LLT EltTy = Query.
Types[EltTypeIdx];
2006 const LLT VecTy = Query.
Types[VecTypeIdx];
2010 const unsigned TargetEltSize =
2011 DstEltSize % 64 == 0 ? 64 : 32;
2012 return std::pair(VecTypeIdx,
2016 .clampScalar(EltTypeIdx,
S32,
S64)
2017 .clampScalar(VecTypeIdx,
S32,
S64)
2018 .clampScalar(IdxTypeIdx,
S32,
S32)
2019 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2028 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2030 const LLT &EltTy = Query.
Types[1].getElementType();
2031 return Query.
Types[0] != EltTy;
2034 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2035 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2036 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2037 getActionDefinitionsBuilder(
Op)
2040 const LLT BigTy = Query.
Types[BigTyIdx];
2046 const LLT LitTy = Query.
Types[LitTyIdx];
2051 .widenScalarToNextPow2(BigTyIdx, 32)
2059 const LLT BigTy = Query.
Types[BigTyIdx];
2060 const LLT LitTy = Query.
Types[LitTyIdx];
2068 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2078 if (
ST.hasScalarPackInsts()) {
2081 .minScalarOrElt(0,
S16)
2084 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2088 BuildVector.customFor({
V2S16,
S16});
2089 BuildVector.minScalarOrElt(0,
S32);
2091 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2099 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2101 .clampMaxNumElements(0,
S32, 32)
2102 .clampMaxNumElements(1,
S16, 2)
2103 .clampMaxNumElements(0,
S16, 64);
2105 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2108 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2109 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2110 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2112 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2113 const LLT Ty = Query.
Types[TypeIdx];
2125 getActionDefinitionsBuilder(
Op)
2129 const LLT BigTy = Query.
Types[BigTyIdx];
2135 .widenScalarToNextPow2(LitTyIdx, 16)
2144 .clampScalar(LitTyIdx,
S32,
S512)
2145 .widenScalarToNextPow2(LitTyIdx, 32)
2149 return notValidElt(Query, LitTyIdx);
2154 return notValidElt(Query, BigTyIdx);
2159 if (
Op == G_MERGE_VALUES) {
2160 Builder.widenScalarIf(
2163 const LLT Ty = Query.
Types[LitTyIdx];
2169 Builder.widenScalarIf(
2171 const LLT Ty = Query.
Types[BigTyIdx];
2177 const LLT &Ty = Query.
Types[BigTyIdx];
2179 if (NewSizeInBits >= 256) {
2181 if (RoundedTo < NewSizeInBits)
2182 NewSizeInBits = RoundedTo;
2184 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2193 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2194 .legalFor({{
S32}, {
S64}})
2195 .clampScalar(0,
S32,
S64);
2197 if (
ST.hasVOP3PInsts()) {
2198 SextInReg.lowerFor({{
V2S16}})
2202 .clampMaxNumElementsStrict(0,
S16, 2);
2203 }
else if (
ST.has16BitInsts()) {
2204 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2208 SextInReg.lowerFor({{
S32}, {
S64}});
2213 .clampScalar(0,
S32,
S64)
2216 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2220 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2221 FSHRActionDefs.legalFor({{
S32,
S32}})
2222 .clampMaxNumElementsStrict(0,
S16, 2);
2223 if (
ST.hasVOP3PInsts())
2225 FSHRActionDefs.scalarize(0).lower();
2227 if (
ST.hasVOP3PInsts()) {
2228 getActionDefinitionsBuilder(G_FSHL)
2230 .clampMaxNumElementsStrict(0,
S16, 2)
2234 getActionDefinitionsBuilder(G_FSHL)
2239 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2242 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2244 getActionDefinitionsBuilder(G_FENCE)
2247 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2252 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2254 .clampScalar(1,
S32,
S32)
2255 .clampScalar(0,
S32,
S64)
2256 .widenScalarToNextPow2(0)
2259 getActionDefinitionsBuilder(
2263 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2264 G_READ_REGISTER, G_WRITE_REGISTER,
2269 if (
ST.hasIEEEMinimumMaximumInsts()) {
2270 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2271 .legalFor(FPTypesPK16)
2272 .clampMaxNumElements(0,
S16, 2)
2274 }
else if (
ST.hasVOP3PInsts()) {
2275 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2277 .clampMaxNumElementsStrict(0,
S16, 2)
2281 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2283 .clampScalar(0,
S32,
S64)
2287 getActionDefinitionsBuilder(
2288 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2291 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2293 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2294 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2295 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2298 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2300 getActionDefinitionsBuilder(
2301 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2302 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2303 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2304 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2309 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2310 G_INTRINSIC_CONVERGENT,
2311 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2323 switch (
MI.getOpcode()) {
2324 case TargetOpcode::G_ADDRSPACE_CAST:
2326 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2328 case TargetOpcode::G_FCEIL:
2330 case TargetOpcode::G_FREM:
2332 case TargetOpcode::G_INTRINSIC_TRUNC:
2334 case TargetOpcode::G_SITOFP:
2336 case TargetOpcode::G_UITOFP:
2338 case TargetOpcode::G_FPTOSI:
2340 case TargetOpcode::G_FPTOUI:
2342 case TargetOpcode::G_FMINNUM:
2343 case TargetOpcode::G_FMAXNUM:
2344 case TargetOpcode::G_FMINIMUMNUM:
2345 case TargetOpcode::G_FMAXIMUMNUM:
2347 case TargetOpcode::G_EXTRACT:
2349 case TargetOpcode::G_INSERT:
2351 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2353 case TargetOpcode::G_INSERT_VECTOR_ELT:
2355 case TargetOpcode::G_FSIN:
2356 case TargetOpcode::G_FCOS:
2358 case TargetOpcode::G_GLOBAL_VALUE:
2360 case TargetOpcode::G_LOAD:
2361 case TargetOpcode::G_SEXTLOAD:
2362 case TargetOpcode::G_ZEXTLOAD:
2364 case TargetOpcode::G_STORE:
2366 case TargetOpcode::G_FMAD:
2368 case TargetOpcode::G_FDIV:
2370 case TargetOpcode::G_FFREXP:
2372 case TargetOpcode::G_FSQRT:
2374 case TargetOpcode::G_UDIV:
2375 case TargetOpcode::G_UREM:
2376 case TargetOpcode::G_UDIVREM:
2378 case TargetOpcode::G_SDIV:
2379 case TargetOpcode::G_SREM:
2380 case TargetOpcode::G_SDIVREM:
2382 case TargetOpcode::G_ATOMIC_CMPXCHG:
2384 case TargetOpcode::G_FLOG2:
2386 case TargetOpcode::G_FLOG:
2387 case TargetOpcode::G_FLOG10:
2389 case TargetOpcode::G_FEXP2:
2391 case TargetOpcode::G_FEXP:
2392 case TargetOpcode::G_FEXP10:
2394 case TargetOpcode::G_FPOW:
2396 case TargetOpcode::G_FFLOOR:
2398 case TargetOpcode::G_BUILD_VECTOR:
2399 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2401 case TargetOpcode::G_MUL:
2403 case TargetOpcode::G_CTLZ:
2404 case TargetOpcode::G_CTTZ:
2406 case TargetOpcode::G_CTLS:
2408 case TargetOpcode::G_CTLZ_ZERO_POISON:
2410 case TargetOpcode::G_STACKSAVE:
2412 case TargetOpcode::G_GET_FPENV:
2414 case TargetOpcode::G_SET_FPENV:
2416 case TargetOpcode::G_TRAP:
2418 case TargetOpcode::G_DEBUGTRAP:
2438 if (ST.hasApertureRegs()) {
2443 ? AMDGPU::SRC_SHARED_BASE
2444 : AMDGPU::SRC_PRIVATE_BASE;
2445 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2446 !ST.hasGloballyAddressableScratch()) &&
2447 "Cannot use src_private_base with globally addressable scratch!");
2450 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2451 return B.buildUnmerge(I32, Dst).getReg(1);
2466 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2482 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2485 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2507 B.buildObjectPtrOffset(
2510 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2518 switch (Def->getOpcode()) {
2519 case AMDGPU::G_FRAME_INDEX:
2520 case AMDGPU::G_GLOBAL_VALUE:
2521 case AMDGPU::G_BLOCK_ADDR:
2523 case AMDGPU::G_CONSTANT: {
2524 const ConstantInt *CI = Def->getOperand(1).getCImm();
2541 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2543 Intrinsic::amdgcn_addrspacecast_nonnull));
2549 :
MI.getOperand(1).getReg();
2553 unsigned SrcAS = SrcTy.getAddressSpace();
2563 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2570 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2572 ST.hasGloballyAddressableScratch()) {
2575 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2577 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2578 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2580 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2581 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2582 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2586 return B.buildExtract(Dst, Src, 0).getReg(0);
2592 castFlatToLocalOrPrivate(Dst);
2593 MI.eraseFromParent();
2599 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2600 auto FlatNull =
B.buildConstant(SrcTy, 0);
2603 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2607 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2609 MI.eraseFromParent();
2616 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2619 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2622 ST.hasGloballyAddressableScratch()) {
2626 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2627 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2631 if (ST.isWave64()) {
2632 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2638 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2639 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2641 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2645 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2646 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2648 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2649 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2658 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2664 castLocalOrPrivateToFlat(Dst);
2665 MI.eraseFromParent();
2669 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2676 SegmentNull.getReg(0));
2678 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2680 MI.eraseFromParent();
2685 SrcTy.getSizeInBits() == 64) {
2687 B.buildExtract(Dst, Src, 0);
2688 MI.eraseFromParent();
2695 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2696 auto PtrLo =
B.buildPtrToInt(I32, Src);
2697 if (AddrHiVal == 0) {
2698 auto Zext =
B.buildZExt(I64, PtrLo);
2699 B.buildIntToPtr(Dst, Zext);
2701 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2702 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2705 MI.eraseFromParent();
2712 MI.eraseFromParent();
2721 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2726 auto C1 =
B.buildFConstant(Ty, C1Val);
2727 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2730 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2731 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2733 auto C2 =
B.buildFConstant(Ty, C2Val);
2734 auto Fabs =
B.buildFAbs(Ty, Src);
2737 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2738 MI.eraseFromParent();
2755 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2757 const auto Zero =
B.buildFConstant(
F64, 0.0);
2758 const auto One =
B.buildFConstant(
F64, 1.0);
2761 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2762 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2765 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2766 MI.eraseFromParent();
2774 Register Src0Reg =
MI.getOperand(1).getReg();
2775 Register Src1Reg =
MI.getOperand(2).getReg();
2776 auto Flags =
MI.getFlags();
2779 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2780 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2781 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2782 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2783 MI.eraseFromParent();
2789 const unsigned FractBits = 52;
2790 const unsigned ExpBits = 11;
2793 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2794 auto Const1 =
B.buildConstant(I32, ExpBits);
2796 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2798 .addUse(Const0.getReg(0))
2799 .addUse(Const1.getReg(0));
2801 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2814 auto SrcInt =
B.buildBitcast(I64, Src);
2817 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2824 const unsigned FractBits = 52;
2827 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2828 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2830 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2832 const auto Zero32 =
B.buildConstant(I32, 0);
2835 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2837 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2838 auto Not =
B.buildNot(I64, Shr);
2839 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2840 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2845 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2846 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2847 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2848 MI.eraseFromParent();
2864 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2865 auto ThirtyTwo =
B.buildConstant(I32, 32);
2868 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2869 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2871 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2872 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2875 B.buildFAdd(Dst, LdExp, CvtLo);
2876 MI.eraseFromParent();
2882 auto One =
B.buildConstant(I32, 1);
2886 auto ThirtyOne =
B.buildConstant(I32, 31);
2887 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2888 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2889 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2890 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2891 .addUse(Unmerge.getReg(1));
2892 auto LS2 =
B.buildSub(I32, LS, One);
2893 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2895 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2896 auto Norm =
B.buildShl(I64, Src, ShAmt);
2897 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2898 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2899 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2900 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2901 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2902 B.buildFLdexp(Dst, FVal, Scale);
2903 MI.eraseFromParent();
2923 unsigned Flags =
MI.getFlags();
2934 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2942 auto SrcInt =
B.buildBitcast(I32, Src);
2943 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2944 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2948 K0 =
B.buildFConstant(
2950 K1 =
B.buildFConstant(
2953 K0 =
B.buildFConstant(
2955 K1 =
B.buildFConstant(
2959 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2960 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2961 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2963 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2964 :
B.buildFPTOUI(I32, FloorMul);
2965 auto Lo =
B.buildFPTOUI(I32, Fma);
2969 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2971 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2974 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2975 MI.eraseFromParent();
3007 unsigned StartIdx =
Offset / 32;
3011 if (DstCount == 1) {
3013 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3018 for (
unsigned I = 0;
I < DstCount; ++
I)
3019 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3020 B.buildMergeLikeInstr(DstReg, MergeVec);
3023 MI.eraseFromParent();
3033 Register InsertSrc =
MI.getOperand(2).getReg();
3042 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3046 unsigned DstCount = DstSize / 32;
3047 unsigned InsertCount = InsertSize / 32;
3048 unsigned StartIdx =
Offset / 32;
3050 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3053 for (
unsigned I = 0;
I < StartIdx; ++
I)
3056 if (InsertCount == 1) {
3060 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3063 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3064 for (
unsigned I = 0;
I < InsertCount; ++
I)
3068 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3071 B.buildMergeLikeInstr(DstReg, MergeVec);
3073 MI.eraseFromParent();
3100 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3101 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3102 B.buildIntToPtr(Dst, IntElt);
3104 MI.eraseFromParent();
3111 std::optional<ValueAndVReg> MaybeIdxVal =
3115 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3118 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3119 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3124 MI.eraseFromParent();
3153 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3154 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3155 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3157 B.buildIntToPtr(Dst, IntVecDest);
3158 MI.eraseFromParent();
3165 std::optional<ValueAndVReg> MaybeIdxVal =
3170 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3173 if (IdxVal < NumElts) {
3175 for (
unsigned i = 0; i < NumElts; ++i)
3177 B.buildUnmerge(SrcRegs, Vec);
3179 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3180 B.buildMergeLikeInstr(Dst, SrcRegs);
3185 MI.eraseFromParent();
3196 unsigned Flags =
MI.getFlags();
3200 if (ST.hasTrigReducedRange()) {
3201 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3202 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3203 .addUse(MulVal.getReg(0))
3207 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3210 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3214 MI.eraseFromParent();
3222 unsigned GAFlags)
const {
3251 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3253 if (ST.has64BitLiterals()) {
3257 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3261 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3270 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3271 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3274 B.buildExtract(DstReg, PCReg, 0);
3284 if (RequiresHighHalf && ST.has64BitLiterals()) {
3286 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3287 B.buildInstr(AMDGPU::S_MOV_B64)
3302 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3305 B.buildInstr(AMDGPU::S_MOV_B32)
3310 if (RequiresHighHalf) {
3312 "Must provide a 64-bit pointer type!");
3315 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3317 B.buildInstr(AMDGPU::S_MOV_B32)
3328 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3330 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3334 if (AddrDst != DstReg)
3335 B.buildCast(DstReg, AddrDst);
3336 }
else if (AddrLo != DstReg) {
3339 B.buildCast(DstReg, AddrLo);
3348 unsigned AS = Ty.getAddressSpace();
3356 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3360 Fn,
"local memory global used by non-kernel function",
3369 B.buildUndef(DstReg);
3370 MI.eraseFromParent();
3394 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3395 B.buildIntToPtr(DstReg, Sz);
3396 MI.eraseFromParent();
3402 MI.eraseFromParent();
3406 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3408 MI.eraseFromParent();
3416 MI.eraseFromParent();
3422 MI.eraseFromParent();
3438 if (Ty.getSizeInBits() == 32) {
3440 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3441 B.buildExtract(DstReg,
Load, 0);
3443 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3445 MI.eraseFromParent();
3468 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3470 MI.getOperand(1).setReg(Cast.getReg(0));
3475 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3501 if (WideMemSize == ValSize) {
3507 MI.setMemRefs(MF, {WideMMO});
3513 if (ValSize > WideMemSize)
3520 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3521 B.buildTrunc(ValReg, WideLoad).getReg(0);
3528 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3529 B.buildExtract(ValReg, WideLoad, 0);
3533 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3534 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3538 MI.eraseFromParent();
3551 Register DataReg =
MI.getOperand(0).getReg();
3596 "this should not have been custom lowered");
3601 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3603 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3607 .setMemRefs(
MI.memoperands());
3609 MI.eraseFromParent();
3617 switch (
DefMI->getOpcode()) {
3618 case TargetOpcode::G_INTRINSIC: {
3620 case Intrinsic::amdgcn_frexp_mant:
3621 case Intrinsic::amdgcn_log:
3622 case Intrinsic::amdgcn_log_clamp:
3623 case Intrinsic::amdgcn_exp2:
3624 case Intrinsic::amdgcn_sqrt:
3632 case TargetOpcode::G_FSQRT:
3634 case TargetOpcode::G_FFREXP: {
3635 if (
DefMI->getOperand(0).getReg() == Src)
3639 case TargetOpcode::G_FPEXT: {
3660std::pair<Register, Register>
3662 unsigned Flags)
const {
3666 auto SmallestNormal =
B.buildFConstant(
3668 auto IsLtSmallestNormal =
3671 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3672 auto One =
B.buildFConstant(
F32, 1.0);
3674 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3675 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3677 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3690 LLT Ty =
B.getMRI()->getType(Dst);
3691 unsigned Flags =
MI.getFlags();
3695 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3696 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3697 .addUse(Ext.getReg(0))
3699 B.buildFPTrunc(Dst,
Log2, Flags);
3700 MI.eraseFromParent();
3708 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3711 MI.eraseFromParent();
3715 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3716 .addUse(ScaledInput)
3719 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3720 auto Zero =
B.buildFConstant(Ty, 0.0);
3722 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3723 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3725 MI.eraseFromParent();
3731 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3732 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3737 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3738 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3743 unsigned Flags =
MI.getFlags();
3753 auto PromoteSrc =
B.buildFPExt(
F32,
X);
3755 B.buildFPTrunc(Dst, LogVal);
3760 MI.eraseFromParent();
3769 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3772 if (ST.hasFastFMAF32()) {
3774 const float c_log10 = 0x1.344134p-2f;
3775 const float cc_log10 = 0x1.09f79ep-26f;
3778 const float c_log = 0x1.62e42ep-1f;
3779 const float cc_log = 0x1.efa39ep-25f;
3781 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3782 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3786 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3787 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3788 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3789 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3790 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3793 const float ch_log10 = 0x1.344000p-2f;
3794 const float ct_log10 = 0x1.3509f6p-18f;
3797 const float ch_log = 0x1.62e000p-1f;
3798 const float ct_log = 0x1.0bfbe8p-15f;
3800 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3801 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3803 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
3804 auto YH =
B.buildAnd(Ty,
Y, MaskConst);
3805 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3809 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3812 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3814 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3817 const bool IsFiniteOnly =
3820 if (!IsFiniteOnly) {
3823 auto Fabs =
B.buildFAbs(Ty,
Y);
3826 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3830 auto Zero =
B.buildFConstant(Ty, 0.0);
3832 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3833 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3834 B.buildFSub(Dst, R, Shift, Flags);
3836 B.buildCopy(Dst, R);
3839 MI.eraseFromParent();
3845 unsigned Flags)
const {
3846 const double Log2BaseInverted =
3849 LLT Ty =
B.getMRI()->getType(Dst);
3854 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3857 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3858 auto Zero =
B.buildFConstant(Ty, 0.0);
3860 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3861 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3863 if (ST.hasFastFMAF32())
3864 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3866 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3867 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3874 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3875 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3878 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3879 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3890 unsigned Flags =
MI.getFlags();
3891 LLT Ty =
B.getMRI()->getType(Dst);
3898 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3899 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3900 .addUse(Ext.getReg(0))
3902 B.buildFPTrunc(Dst,
Log2, Flags);
3903 MI.eraseFromParent();
3913 MI.eraseFromParent();
3921 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3923 RangeCheckConst, Flags);
3925 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3926 auto Zero =
B.buildFConstant(Ty, 0.0);
3927 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3928 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3930 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3931 .addUse(AddInput.getReg(0))
3934 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3935 auto One =
B.buildFConstant(Ty, 1.0);
3936 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3937 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3938 MI.eraseFromParent();
3943 const SrcOp &Src,
unsigned Flags) {
3944 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3947 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3948 .addUse(Src.getReg())
3951 return B.buildFExp2(Dst, Src, Flags);
3957 bool IsExp10)
const {
3958 LLT Ty =
B.getMRI()->getType(
X);
3962 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3963 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3970 LLT Ty =
B.getMRI()->getType(Dst);
3976 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3979 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3980 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3981 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3984 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3986 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3987 .addUse(ExpInput.getReg(0))
3990 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3991 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3992 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3998 unsigned Flags)
const {
3999 LLT Ty =
B.getMRI()->getType(Dst);
4003 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4004 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4006 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4007 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4008 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4009 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4010 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4020 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4024 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4025 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4026 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4028 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4029 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4031 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4032 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4033 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4034 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4036 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4037 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4038 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4040 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4058 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4060 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4062 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4064 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4065 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4066 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4067 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4069 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4070 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4071 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4072 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4074 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4075 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4076 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4077 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4078 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4080 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4081 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4082 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4083 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4086 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4087 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4088 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4090 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4091 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4092 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4093 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4094 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4098 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4099 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4101 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4103 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4105 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4107 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4109 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4110 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4111 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4112 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4114 auto One =
B.buildFConstant(
F64, 1.0);
4115 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4116 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4119 auto DnInt =
B.buildFPTOSI(I32, Dn);
4120 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4127 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4134 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4136 MI.eraseFromParent();
4144 const unsigned Flags =
MI.getFlags();
4152 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4160 MI.eraseFromParent();
4171 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4174 B.buildFPTrunc(Dst, Lowered, Flags);
4175 MI.eraseFromParent();
4186 MI.eraseFromParent();
4214 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4217 if (ST.hasFastFMAF32()) {
4219 const float cc_exp = 0x1.4ae0bep-26f;
4220 const float c_exp10 = 0x1.a934f0p+1f;
4221 const float cc_exp10 = 0x1.2f346ep-24f;
4223 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4224 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4225 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4226 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4228 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4229 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4231 const float ch_exp = 0x1.714000p+0f;
4232 const float cl_exp = 0x1.47652ap-12f;
4234 const float ch_exp10 = 0x1.a92000p+1f;
4235 const float cl_exp10 = 0x1.4f0978p-11f;
4237 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
4238 auto XH =
B.buildAnd(Ty,
X, MaskConst);
4239 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4241 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4242 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4244 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4245 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4248 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4249 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4252 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4255 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4256 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4258 auto IntE =
B.buildFPTOSI(I32, E);
4260 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4261 .addUse(
A.getReg(0))
4263 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4265 auto UnderflowCheckConst =
4266 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4267 auto Zero =
B.buildFConstant(Ty, 0.0);
4271 R =
B.buildSelect(Ty, Underflow, Zero, R);
4274 auto OverflowCheckConst =
4275 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4280 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4283 B.buildCopy(Dst, R);
4284 MI.eraseFromParent();
4293 unsigned Flags =
MI.getFlags();
4294 LLT Ty =
B.getMRI()->getType(Dst);
4297 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4298 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4299 .addUse(Log.getReg(0))
4302 B.buildFExp2(Dst,
Mul, Flags);
4303 }
else if (Ty ==
F16) {
4305 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4306 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4307 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4308 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4309 .addUse(Ext0.getReg(0))
4310 .addUse(Ext1.getReg(0))
4312 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul), Flags);
4316 MI.eraseFromParent();
4324 ModSrc = SrcFNeg->getOperand(1).getReg();
4326 ModSrc = SrcFAbs->getOperand(1).getReg();
4328 ModSrc = SrcFAbs->getOperand(1).getReg();
4338 Register OrigSrc =
MI.getOperand(1).getReg();
4339 unsigned Flags =
MI.getFlags();
4341 "this should not have been custom lowered");
4351 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4371 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4373 B.buildFMinNum(Min, Fract, Const, Flags);
4378 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4381 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4382 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4384 MI.eraseFromParent();
4402 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4404 Src0 =
B.buildTrunc(
I16,
MI.getOperand(1).getReg()).getReg(0);
4405 Src1 =
B.buildTrunc(
I16,
MI.getOperand(2).getReg()).getReg(0);
4408 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4409 B.buildBitcast(Dst,
Merge);
4411 MI.eraseFromParent();
4428 bool UsePartialMad64_32,
4429 bool SeparateOddAlignedProducts)
const {
4444 auto getZero32 = [&]() ->
Register {
4446 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4449 auto getZero64 = [&]() ->
Register {
4451 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4456 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4467 if (CarryIn.empty())
4470 bool HaveCarryOut =
true;
4472 if (CarryIn.size() == 1) {
4474 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4478 CarryAccum = getZero32();
4480 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4481 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4483 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4488 LocalAccum = getZero32();
4489 HaveCarryOut =
false;
4494 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4495 LocalAccum =
Add.getReg(0);
4509 auto buildMadChain =
4512 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4513 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4520 if (LocalAccum.size() == 1 &&
4521 (!UsePartialMad64_32 || !CarryIn.empty())) {
4524 unsigned j1 = DstIndex - j0;
4525 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4529 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4531 LocalAccum[0] =
Mul.getReg(0);
4533 if (CarryIn.empty()) {
4534 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4537 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4543 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4547 if (j0 <= DstIndex) {
4548 bool HaveSmallAccum =
false;
4551 if (LocalAccum[0]) {
4552 if (LocalAccum.size() == 1) {
4553 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4554 HaveSmallAccum =
true;
4555 }
else if (LocalAccum[1]) {
4556 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4557 HaveSmallAccum =
false;
4559 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4560 HaveSmallAccum =
true;
4563 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4565 HaveSmallAccum =
true;
4569 unsigned j1 = DstIndex - j0;
4570 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4574 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4575 {Src0[j0], Src1[j1], Tmp});
4576 Tmp = Mad.getReg(0);
4577 if (!HaveSmallAccum)
4578 CarryOut.push_back(Mad.getReg(1));
4579 HaveSmallAccum =
false;
4582 }
while (j0 <= DstIndex);
4584 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4585 LocalAccum[0] = Unmerge.getReg(0);
4586 if (LocalAccum.size() > 1)
4587 LocalAccum[1] = Unmerge.getReg(1);
4614 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4615 Carry OddCarryIn = std::move(OddCarry);
4616 Carry EvenCarryIn = std::move(EvenCarry);
4621 if (2 * i < Accum.
size()) {
4622 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4623 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4628 if (!SeparateOddAlignedProducts) {
4629 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4630 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4632 bool IsHighest = 2 * i >= Accum.
size();
4635 .take_front(IsHighest ? 1 : 2);
4636 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4642 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4644 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4646 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4649 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4652 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4653 Lo->getOperand(1).getReg());
4654 Accum[2 * i] =
Hi.getReg(0);
4655 SeparateOddCarry =
Hi.getReg(1);
4662 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4663 EvenCarryIn.push_back(CarryOut);
4665 if (2 * i < Accum.
size()) {
4666 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4667 OddCarry.push_back(CarryOut);
4679 assert(ST.hasMad64_32());
4680 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4692 unsigned Size = Ty.getSizeInBits();
4693 if (ST.hasVMulU64Inst() &&
Size == 64)
4696 unsigned NumParts =
Size / 32;
4708 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4712 for (
unsigned i = 0; i < NumParts; ++i) {
4716 B.buildUnmerge(Src0Parts, Src0);
4717 B.buildUnmerge(Src1Parts, Src1);
4720 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4721 SeparateOddAlignedProducts);
4723 B.buildMergeLikeInstr(DstReg, AccumRegs);
4724 MI.eraseFromParent();
4739 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4740 ? AMDGPU::G_AMDGPU_FFBH_U32
4741 : AMDGPU::G_AMDGPU_FFBL_B32;
4742 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4745 MI.eraseFromParent();
4755 TypeSize NumBits = SrcTy.getSizeInBits();
4760 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4761 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4762 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4763 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4764 B.buildTrunc(Dst, Ctlz);
4765 MI.eraseFromParent();
4776 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4777 unsigned BitWidth = SrcTy.getSizeInBits();
4779 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4780 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4781 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4782 MI.eraseFromParent();
4788 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4791 return ConstVal == -1;
4798 Register CondDef =
MI.getOperand(0).getReg();
4817 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4826 UncondBrTarget = &*NextMBB;
4828 if (
Next->getOpcode() != AMDGPU::G_BR)
4847 *ArgRC,
B.getDebugLoc(), ArgTy);
4851 const unsigned Mask = Arg->
getMask();
4859 auto ShiftAmt =
B.buildConstant(I32, Shift);
4860 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4863 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4865 B.buildCopy(DstReg, LiveIn);
4875 if (!ST.hasClusters()) {
4878 MI.eraseFromParent();
4898 auto One =
B.buildConstant(I32, 1);
4899 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4900 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4901 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4908 B.buildCopy(DstReg, GlobalIdXYZ);
4909 MI.eraseFromParent();
4913 B.buildCopy(DstReg, ClusterIdXYZ);
4914 MI.eraseFromParent();
4919 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4921 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4922 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4924 .addImm(ClusterIdField);
4925 auto Zero =
B.buildConstant(I32, 0);
4928 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4929 MI.eraseFromParent();
4971 auto LoadConstant = [&](
unsigned N) {
4972 B.buildConstant(DstReg,
N);
4976 if (ST.hasArchitectedSGPRs() &&
4983 Arg = &WorkGroupIDX;
4984 ArgRC = &AMDGPU::SReg_32RegClass;
4988 Arg = &WorkGroupIDY;
4989 ArgRC = &AMDGPU::SReg_32RegClass;
4993 Arg = &WorkGroupIDZ;
4994 ArgRC = &AMDGPU::SReg_32RegClass;
4998 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
4999 return LoadConstant(0);
5000 Arg = &ClusterWorkGroupIDX;
5001 ArgRC = &AMDGPU::SReg_32RegClass;
5005 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5006 return LoadConstant(0);
5007 Arg = &ClusterWorkGroupIDY;
5008 ArgRC = &AMDGPU::SReg_32RegClass;
5012 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5013 return LoadConstant(0);
5014 Arg = &ClusterWorkGroupIDZ;
5015 ArgRC = &AMDGPU::SReg_32RegClass;
5020 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5021 Arg = &ClusterWorkGroupMaxIDX;
5022 ArgRC = &AMDGPU::SReg_32RegClass;
5027 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5028 Arg = &ClusterWorkGroupMaxIDY;
5029 ArgRC = &AMDGPU::SReg_32RegClass;
5034 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5035 Arg = &ClusterWorkGroupMaxIDZ;
5036 ArgRC = &AMDGPU::SReg_32RegClass;
5040 Arg = &ClusterWorkGroupMaxFlatID;
5041 ArgRC = &AMDGPU::SReg_32RegClass;
5056 return LoadConstant(0);
5061 B.buildUndef(DstReg);
5065 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5077 MI.eraseFromParent();
5083 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5084 MI.eraseFromParent();
5091 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5105 B.buildUndef(DstReg);
5106 MI.eraseFromParent();
5110 if (Arg->isMasked()) {
5124 MI.eraseFromParent();
5139 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5148 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5156 Align Alignment)
const {
5160 "unexpected kernarg parameter type");
5167 MI.eraseFromParent();
5199 auto FloatY =
B.buildUITOFP(
F32,
Y);
5200 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5202 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5203 auto Z =
B.buildFPTOUI(I32, ScaledY);
5206 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5207 auto NegYZ =
B.buildMul(I32, NegY, Z);
5208 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5211 auto Q =
B.buildUMulH(I32,
X, Z);
5212 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5215 auto One =
B.buildConstant(I32, 1);
5218 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5219 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5224 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5227 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5246 auto Unmerge =
B.buildUnmerge(I32, Val);
5248 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5249 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5251 auto Mad =
B.buildFMAD(
5255 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5256 auto Mul1 =
B.buildFMul(
5260 auto Mul2 =
B.buildFMul(
5262 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5265 auto Mad2 =
B.buildFMAD(
5269 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5270 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5272 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5287 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5289 auto Zero64 =
B.buildConstant(I64, 0);
5290 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5292 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5293 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5295 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5296 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5297 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5299 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5300 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5301 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5303 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5304 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5305 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5306 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5307 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5309 auto Zero32 =
B.buildConstant(I32, 0);
5310 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5311 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5312 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5314 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5315 Register NumerLo = UnmergeNumer.getReg(0);
5316 Register NumerHi = UnmergeNumer.getReg(1);
5318 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5319 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5320 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5321 Register Mul3_Lo = UnmergeMul3.getReg(0);
5322 Register Mul3_Hi = UnmergeMul3.getReg(1);
5323 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5324 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5325 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5326 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5328 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5329 Register DenomLo = UnmergeDenom.getReg(0);
5330 Register DenomHi = UnmergeDenom.getReg(1);
5333 auto C1 =
B.buildSExt(I32, CmpHi);
5336 auto C2 =
B.buildSExt(I32, CmpLo);
5339 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5346 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5347 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5348 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5349 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5351 auto One64 =
B.buildConstant(I64, 1);
5352 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5358 auto C6 =
B.buildSelect(
5362 auto Add4 =
B.buildAdd(I64, Add3, One64);
5363 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5365 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5366 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5367 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5373 auto Sel1 =
B.buildSelect(
5380 auto Sel2 =
B.buildSelect(
5391 switch (
MI.getOpcode()) {
5394 case AMDGPU::G_UDIV: {
5395 DstDivReg =
MI.getOperand(0).getReg();
5398 case AMDGPU::G_UREM: {
5399 DstRemReg =
MI.getOperand(0).getReg();
5402 case AMDGPU::G_UDIVREM: {
5403 DstDivReg =
MI.getOperand(0).getReg();
5404 DstRemReg =
MI.getOperand(1).getReg();
5411 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5412 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5413 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5423 MI.eraseFromParent();
5434 if (Ty != I32 && Ty != I64)
5437 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5438 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5439 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5441 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5442 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5443 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5445 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5446 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5448 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5449 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5451 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5452 switch (
MI.getOpcode()) {
5455 case AMDGPU::G_SDIV: {
5456 DstDivReg =
MI.getOperand(0).getReg();
5460 case AMDGPU::G_SREM: {
5461 DstRemReg =
MI.getOperand(0).getReg();
5465 case AMDGPU::G_SDIVREM: {
5466 DstDivReg =
MI.getOperand(0).getReg();
5467 DstRemReg =
MI.getOperand(1).getReg();
5480 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5481 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5482 B.buildSub(DstDivReg, SignXor, Sign);
5486 auto Sign = LHSign.getReg(0);
5487 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5488 B.buildSub(DstRemReg, SignXor, Sign);
5491 MI.eraseFromParent();
5507 if (!AllowInaccurateRcp && ResTy !=
F16)
5518 if (CLHS->isOne()) {
5519 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5523 MI.eraseFromParent();
5528 if (CLHS->isMinusOne()) {
5529 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5530 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5531 .addUse(FNeg.getReg(0))
5534 MI.eraseFromParent();
5541 if (!AllowInaccurateRcp &&
5546 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5549 B.buildFMul(Res, LHS, RCP, Flags);
5551 MI.eraseFromParent();
5566 if (!AllowInaccurateRcp)
5574 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5576 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5577 auto One =
B.buildFConstant(ResTy, 1.0);
5579 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5583 R =
B.buildFNeg(ResTy, R);
5585 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5586 R =
B.buildFMA(ResTy, Tmp0, R, R);
5588 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5589 R =
B.buildFMA(ResTy, Tmp1, R, R);
5592 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5593 B.buildCopy(Res, R);
5594 MI.eraseFromParent();
5598 auto Ret =
B.buildFMul(ResTy,
X, R);
5599 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5601 B.buildFMA(Res, Tmp2, R, Ret);
5602 MI.eraseFromParent();
5633 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5634 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5635 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5636 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5637 .addUse(RHSExt.getReg(0))
5639 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5641 if (ST.hasMadMacF32Insts()) {
5642 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5643 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5644 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5646 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5647 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5648 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5650 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5651 auto TmpInt =
B.buildBitcast(I32, Tmp);
5652 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5653 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5654 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5655 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5656 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5657 .addUse(RDst.getReg(0))
5662 MI.eraseFromParent();
5675 unsigned SPDenormMode =
5678 if (ST.hasDenormModeInst()) {
5680 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5682 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5683 B.buildInstr(AMDGPU::S_DENORM_MODE)
5684 .addImm(NewDenormModeValue);
5687 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5688 .addImm(SPDenormMode)
5709 auto One =
B.buildFConstant(
F32, 1.0f);
5711 auto DenominatorScaled =
5712 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5717 auto NumeratorScaled =
5718 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5724 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5725 .addUse(DenominatorScaled.getReg(0))
5727 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5730 const bool HasDynamicDenormals =
5735 if (!PreservesDenormals) {
5736 if (HasDynamicDenormals) {
5738 B.buildInstr(AMDGPU::S_GETREG_B32)
5739 .addDef(SavedSPDenormMode)
5745 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5746 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5747 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5748 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5749 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5750 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5752 if (!PreservesDenormals) {
5753 if (HasDynamicDenormals) {
5754 assert(SavedSPDenormMode);
5755 B.buildInstr(AMDGPU::S_SETREG_B32)
5756 .addReg(SavedSPDenormMode)
5762 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5763 .addUse(Fma4.getReg(0))
5764 .addUse(Fma1.getReg(0))
5765 .addUse(Fma3.getReg(0))
5766 .addUse(NumeratorScaled.getReg(1))
5769 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5770 .addUse(Fmas.getReg(0))
5775 MI.eraseFromParent();
5793 auto One =
B.buildFConstant(
F64, 1.0);
5795 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5801 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5803 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5804 .addUse(DivScale0.getReg(0))
5807 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5808 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5809 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5811 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5817 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5818 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5819 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5822 if (!ST.hasUsableDivScaleConditionOutput()) {
5829 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5830 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5831 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5832 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5835 Scale1Unmerge.getReg(1));
5837 Scale0Unmerge.getReg(1));
5838 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5840 Scale = DivScale1.getReg(1);
5843 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5844 .addUse(Fma4.getReg(0))
5845 .addUse(Fma3.getReg(0))
5846 .addUse(
Mul.getReg(0))
5850 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5851 .addUse(Fmas.getReg(0))
5856 MI.eraseFromParent();
5871 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5874 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5878 if (ST.hasFractBug()) {
5879 auto Fabs =
B.buildFAbs(Ty, Val);
5883 auto Zero =
B.buildConstant(InstrExpTy, 0);
5884 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5885 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5888 B.buildCopy(Res0, Mant);
5889 B.buildSExtOrTrunc(Res1, Exp);
5891 MI.eraseFromParent();
5905 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5908 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5909 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5910 auto C2 =
B.buildFConstant(
F32, 1.0f);
5913 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5915 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5917 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5918 .addUse(Mul0.getReg(0))
5921 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5923 B.buildFMul(Res, Sel, Mul1, Flags);
5925 MI.eraseFromParent();
5934 unsigned Flags =
MI.getFlags();
5935 assert(!ST.has16BitInsts());
5936 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5937 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5938 .addUse(Ext.getReg(0))
5940 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5941 MI.eraseFromParent();
5951 const unsigned Flags =
MI.getFlags();
5959 MI.eraseFromParent();
5963 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5965 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5966 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5967 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5972 .addUse(SqrtX.getReg(0))
5975 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5976 auto NegOne =
B.buildConstant(I32, -1);
5977 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5979 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5980 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5982 auto PosOne =
B.buildConstant(I32, 1);
5983 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5985 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5986 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
5988 auto Zero =
B.buildFConstant(
F32, 0.0f);
5992 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
5996 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
5999 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6000 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6002 auto Half =
B.buildFConstant(
F32, 0.5f);
6003 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6004 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6005 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6006 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6007 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6008 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6009 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6010 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6013 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6015 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6017 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6020 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6022 MI.eraseFromParent();
6056 unsigned Flags =
MI.getFlags();
6061 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6063 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6067 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6068 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6069 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6072 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6074 auto Half =
B.buildFConstant(
F64, 0.5);
6075 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6076 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6078 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6079 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6081 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6082 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6084 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6085 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6087 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6089 Register SqrtRet = SqrtS2.getReg(0);
6091 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6092 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6093 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6096 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6097 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6098 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6103 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6112 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6114 MI.eraseFromParent();
6145 auto Flags =
MI.getFlags();
6157 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6167 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6168 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6173 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6175 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6176 MI.eraseFromParent();
6188 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6189 IID == Intrinsic::amdgcn_permlanex16;
6190 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6191 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6192 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6193 IID == Intrinsic::amdgcn_permlane_up ||
6194 IID == Intrinsic::amdgcn_permlane_down ||
6195 IID == Intrinsic::amdgcn_permlane_xor;
6199 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6201 case Intrinsic::amdgcn_readfirstlane:
6202 case Intrinsic::amdgcn_permlane64:
6203 return LaneOp.getReg(0);
6204 case Intrinsic::amdgcn_readlane:
6205 case Intrinsic::amdgcn_set_inactive:
6206 case Intrinsic::amdgcn_set_inactive_chain_arg:
6207 return LaneOp.addUse(Src1).getReg(0);
6208 case Intrinsic::amdgcn_writelane:
6209 case Intrinsic::amdgcn_permlane_bcast:
6210 case Intrinsic::amdgcn_permlane_up:
6211 case Intrinsic::amdgcn_permlane_down:
6212 case Intrinsic::amdgcn_permlane_xor:
6213 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6214 case Intrinsic::amdgcn_permlane16:
6215 case Intrinsic::amdgcn_permlanex16: {
6217 int64_t Src4 =
MI.getOperand(6).getImm();
6218 int64_t Src5 =
MI.getOperand(7).getImm();
6219 return LaneOp.addUse(Src1)
6226 case Intrinsic::amdgcn_mov_dpp8:
6227 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6228 case Intrinsic::amdgcn_update_dpp:
6229 return LaneOp.addUse(Src1)
6230 .addImm(
MI.getOperand(4).getImm())
6231 .addImm(
MI.getOperand(5).getImm())
6232 .addImm(
MI.getOperand(6).getImm())
6233 .addImm(
MI.getOperand(7).getImm())
6243 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6244 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6245 IsPermlaneShuffle) {
6246 Src1 =
MI.getOperand(3).getReg();
6247 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6248 IsPermlaneShuffle) {
6249 Src2 =
MI.getOperand(4).getReg();
6254 unsigned Size = Ty.getSizeInBits();
6256 unsigned SplitSize = 32;
6257 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6258 ST.hasDPALU_DPP() &&
6262 if (
Size == SplitSize) {
6269 bool IsFloat = Ty.getScalarType().isFloat();
6273 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6275 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6277 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6281 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6283 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6284 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6286 if (IID == Intrinsic::amdgcn_writelane)
6287 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6289 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6291 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6293 B.buildTrunc(DstReg, LaneOpDst);
6294 MI.eraseFromParent();
6298 if (
Size % SplitSize != 0)
6302 bool NeedsBitcast =
false;
6303 if (IntTy.isVector()) {
6306 if (EltSize == SplitSize) {
6307 PartialResTy = EltTy;
6308 }
else if (EltSize == 16 || EltSize == 32) {
6309 unsigned NElem = SplitSize / EltSize;
6312 NeedsBitcast =
true;
6317 unsigned NumParts =
Size / SplitSize;
6321 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6322 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6324 if (IID == Intrinsic::amdgcn_writelane)
6325 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6327 for (
unsigned i = 0; i < NumParts; ++i) {
6328 Src0 = Src0Parts.
getReg(i);
6330 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6331 Src1 = Src1Parts.
getReg(i);
6333 if (IID == Intrinsic::amdgcn_writelane)
6334 Src2 = Src2Parts.
getReg(i);
6336 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6339 if (NeedsBitcast || IsFloat)
6342 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6344 B.buildMergeLikeInstr(DstReg, PartialRes);
6346 MI.eraseFromParent();
6354 ST.getTargetLowering()->getImplicitParameterOffset(
6364 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6365 B.buildConstant(IdxTy,
Offset).getReg(0));
6376 Register Pointer =
MI.getOperand(2).getReg();
6378 Register NumRecords =
MI.getOperand(4).getReg();
6384 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6386 auto ExtStride =
B.buildAnyExt(I32, Stride);
6388 if (ST.has45BitNumRecordsBufferResource()) {
6389 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6393 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6394 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6395 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6396 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6400 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6401 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6402 auto ExtShiftedStride =
6403 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6404 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6405 auto ExtShiftedFlags =
6406 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6407 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6409 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6410 B.buildMergeValues(Result, {LowHalf, HighHalf});
6412 NumRecords =
B.buildTrunc(I32, NumRecords).getReg(0);
6413 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6414 auto LowHalf = Unmerge.getReg(0);
6415 auto HighHalf = Unmerge.getReg(1);
6417 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6418 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6419 auto ShiftConst =
B.buildConstant(I32, 16);
6420 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6421 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6422 Register NewHighHalfReg = NewHighHalf.getReg(0);
6423 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6426 MI.eraseFromParent();
6443 MI.eraseFromParent();
6451 std::optional<uint32_t> KnownSize =
6453 if (KnownSize.has_value())
6454 B.buildConstant(DstReg, *KnownSize);
6472 MI.eraseFromParent();
6479 unsigned AddrSpace)
const {
6481 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6485 ST.hasGloballyAddressableScratch()) {
6487 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6488 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6490 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6492 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6494 B.buildConstant(I32, 1u << 26));
6499 MI.eraseFromParent();
6509std::pair<Register, unsigned>
6521 bool CheckNUW = ST.hasGFX1250Insts();
6523 MRI, OrigOffset,
nullptr, CheckNUW);
6527 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6537 unsigned Overflow = ImmOffset & ~MaxImm;
6538 ImmOffset -= Overflow;
6539 if ((int32_t)Overflow < 0) {
6540 Overflow += ImmOffset;
6544 if (Overflow != 0) {
6546 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6548 auto OverflowVal =
B.buildConstant(I32, Overflow);
6549 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6554 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6556 return std::pair(BaseReg, ImmOffset);
6563 bool ImageStore)
const {
6571 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6573 if (ST.hasUnpackedD16VMem()) {
6574 auto Unmerge =
B.buildUnmerge(
I16, RegI16);
6577 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6578 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6586 if (ImageStore && ST.hasImageStoreD16Bug()) {
6589 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6591 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6598 auto Unmerge =
B.buildUnmerge(
I16, RegI16);
6599 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6601 PackedRegs.
resize(6,
B.buildUndef(
I16).getReg(0));
6609 auto Unmerge =
B.buildUnmerge(I32, Reg);
6610 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6612 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6622 Reg =
B.buildPadVectorWithUndefElements(
6631 bool IsFormat)
const {
6641 VData =
B.buildBitcast(Ty, VData).getReg(0);
6649 if (Ty.isVector()) {
6650 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6662 bool IsFormat)
const {
6669 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6676 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6677 const Function &Fn =
B.getMF().getFunction();
6679 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6680 MI.eraseFromParent();
6692 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6695 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6699 VIndex =
MI.getOperand(3).getReg();
6702 VIndex =
B.buildConstant(I32, 0).getReg(0);
6705 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6706 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6710 Format =
MI.getOperand(5 + OpOffset).getImm();
6714 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6720 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6721 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6722 }
else if (IsFormat) {
6723 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6724 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6728 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6731 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6734 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6739 auto MIB =
B.buildInstr(
Opc)
6750 MIB.addImm(AuxiliaryData)
6751 .addImm(HasVIndex ? -1 : 0)
6752 .addMemOperand(MMO);
6754 MI.eraseFromParent();
6760 unsigned ImmOffset,
unsigned Format,
6763 auto MIB =
B.buildInstr(
Opc)
6774 MIB.addImm(AuxiliaryData)
6775 .addImm(HasVIndex ? -1 : 0)
6776 .addMemOperand(MMO);
6782 bool IsTyped)
const {
6796 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6797 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6799 StatusDst =
MI.getOperand(1).getReg();
6804 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6807 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6810 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6813 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6816 VIndex =
B.buildConstant(I32, 0).getReg(0);
6819 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6820 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6824 Format =
MI.getOperand(5 + OpOffset).getImm();
6828 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6838 Dst =
MI.getOperand(0).getReg();
6839 B.setInsertPt(
B.getMBB(),
MI);
6846 Dst =
MI.getOperand(0).getReg();
6847 B.setInsertPt(
B.getMBB(),
MI);
6851 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6852 const bool Unpacked = ST.hasUnpackedD16VMem();
6854 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6855 const Function &Fn =
B.getMF().getFunction();
6857 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6860 B.buildUndef(StatusDst);
6861 MI.eraseFromParent();
6873 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6874 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6875 }
else if (IsFormat) {
6879 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6881 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6882 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6887 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6888 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6891 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6892 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6895 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6896 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6902 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6903 unsigned NumLoadDWords = NumValueDWords + 1;
6905 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6907 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6908 bool IsFloat = Ty.getScalarType().isFloat();
6913 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6915 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6916 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6917 B.buildTrunc(DstInt, ExtDst);
6918 }
else if (NumValueDWords == 1) {
6919 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6922 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6923 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6925 B.buildUnmerge(LoadElts, LoadDstReg);
6927 B.buildMergeLikeInstr(DstInt, LoadElts);
6930 B.buildBitcast(Dst, DstInt);
6932 (IsD16 && !Ty.isVector())) {
6933 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6935 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6936 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6937 B.buildTrunc(Dst, LoadDstReg);
6938 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6940 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6942 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6943 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6945 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6947 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6948 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6949 B.buildMergeLikeInstr(Dst, Repack);
6952 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6955 MI.eraseFromParent();
6961 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6962 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6963 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6964 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6965 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6966 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6967 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6968 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6969 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6970 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6971 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6972 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6973 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6974 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6975 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6976 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6977 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6978 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6979 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6980 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6981 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6982 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6983 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6984 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
6985 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
6986 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
6987 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
6988 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
6989 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
6990 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
6991 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
6992 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
6993 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
6994 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
6995 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
6996 case Intrinsic::amdgcn_raw_buffer_atomic_and:
6997 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
6998 case Intrinsic::amdgcn_struct_buffer_atomic_and:
6999 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7000 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7001 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7002 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7003 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7004 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7005 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7006 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7007 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7008 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7009 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7010 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7011 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7012 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7013 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7014 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7015 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7016 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7017 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7018 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7019 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7020 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7021 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7022 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7023 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7024 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7025 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7026 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7027 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7028 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7029 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7030 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7031 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7032 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7033 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7034 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7035 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7036 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7037 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7038 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7039 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7040 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7041 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7042 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7043 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7044 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7045 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7046 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7047 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7048 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7049 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7050 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7059 const bool IsCmpSwap =
7060 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7061 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7062 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7063 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7074 CmpVal =
MI.getOperand(3).getReg();
7079 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7080 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7083 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7086 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7092 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7093 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7094 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7113 .addImm(AuxiliaryData)
7114 .addImm(HasVIndex ? -1 : 0)
7115 .addMemOperand(MMO);
7117 MI.eraseFromParent();
7127 bool IsA16,
bool IsG16) {
7141 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7146 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7150 "Bias needs to be converted to 16 bit in A16 mode");
7152 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7156 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7160 if (((
I + 1) >= EndIdx) ||
7167 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7169 B.buildBuildVector(V2EltTy,
7170 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7175 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7186 int DimIdx,
int NumVAddrs) {
7188 for (
int I = 0;
I != NumVAddrs; ++
I) {
7190 if (
SrcOp.isReg()) {
7193 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7194 if (
B.getMRI()->getType(
Reg) != I32)
7195 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7200 int NumAddrRegs = AddrRegs.
size();
7201 if (NumAddrRegs != 1) {
7202 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7205 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7208 for (
int I = 1;
I != NumVAddrs; ++
I) {
7211 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7233 const unsigned NumDefs =
MI.getNumExplicitDefs();
7234 const unsigned ArgOffset = NumDefs + 1;
7235 bool IsTFE = NumDefs == 2;
7253 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7257 const bool IsAtomicPacked16Bit =
7258 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7259 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7266 const bool GradTyIs16 = GradTy ==
I16 || GradTy ==
F16;
7267 const bool AddrTyIs16 = AddrTy ==
I16 || AddrTy ==
F16;
7268 const bool DataTyIs16 =
7269 Ty.getScalarType() ==
I16 || Ty.getScalarType() ==
F16;
7271 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7272 const bool IsA16 = AddrTyIs16;
7273 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7276 if (!BaseOpcode->
Atomic) {
7277 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7280 }
else if (DMask != 0) {
7282 }
else if (!IsTFE && !BaseOpcode->
Store) {
7284 B.buildUndef(
MI.getOperand(0));
7285 MI.eraseFromParent();
7293 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7294 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7295 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7296 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7297 unsigned NewOpcode = LoadOpcode;
7298 if (BaseOpcode->
Store)
7299 NewOpcode = StoreOpcode;
7301 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7304 MI.setDesc(
B.getTII().get(NewOpcode));
7308 if (IsTFE && DMask == 0) {
7311 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7314 if (BaseOpcode->
Atomic) {
7319 if (Ty.isVector() && !IsAtomicPacked16Bit)
7326 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7327 MI.getOperand(2).setReg(
Concat.getReg(0));
7328 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7332 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7335 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7341 if (IsA16 && !ST.hasA16()) {
7346 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7347 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7349 if (IsA16 || IsG16) {
7357 const bool UseNSA = ST.hasNSAEncoding() &&
7358 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7359 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7360 const bool UsePartialNSA =
7361 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7363 if (UsePartialNSA) {
7367 auto Concat =
B.buildConcatVectors(
7368 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7369 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7370 PackedRegs.
resize(NSAMaxSize);
7371 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7373 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7374 PackedRegs[0] =
Concat.getReg(0);
7378 const unsigned NumPacked = PackedRegs.
size();
7381 if (!
SrcOp.isReg()) {
7391 SrcOp.setReg(AMDGPU::NoRegister);
7408 const bool UseNSA = ST.hasNSAEncoding() &&
7409 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7410 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7411 const bool UsePartialNSA =
7412 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7414 if (UsePartialNSA) {
7416 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7418 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7433 if (!Ty.isVector() || !IsD16)
7437 if (RepackedReg != VData) {
7438 MI.getOperand(1).setReg(RepackedReg);
7446 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7449 if (NumElts < DMaskLanes)
7452 if (NumElts > 4 || DMaskLanes > 4)
7463 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7464 const LLT AdjustedTy =
7480 if (IsD16 && ST.hasUnpackedD16VMem()) {
7487 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7488 unsigned RoundedSize = 32 * RoundedElts;
7492 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7497 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7503 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7507 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7508 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7512 MI.getOperand(0).setReg(NewResultReg);
7520 Dst1Reg =
MI.getOperand(1).getReg();
7521 if (MRI->
getType(Dst1Reg) != I32)
7525 MI.removeOperand(1);
7528 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7529 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7530 B.buildBitcast(DstReg, Unmerge.getReg(0));
7531 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7540 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7542 if (ResultNumRegs == 1) {
7544 ResultRegs[0] = NewResultReg;
7547 for (
int I = 0;
I != NumDataRegs; ++
I)
7549 B.buildUnmerge(ResultRegs, NewResultReg);
7554 ResultRegs.
resize(NumDataRegs);
7559 if (IsD16 && !Ty.isVector()) {
7560 B.buildTrunc(DstReg, ResultRegs[0]);
7565 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7566 !ST.hasUnpackedD16VMem()) {
7567 B.buildBitcast(DstReg, ResultRegs[0]);
7579 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7581 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7582 }
else if (ST.hasUnpackedD16VMem()) {
7584 Reg =
B.buildTrunc(
I16, Reg).getReg(0);
7588 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7592 for (
int I = 0;
I != NumElts; ++
I)
7599 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7600 B.buildBuildVector(DstReg, ResultRegs);
7604 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7605 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7610 if (Ty == V3I16 || Ty == V3F16) {
7612 if (ResultRegs.
size() == 1) {
7613 NewResultReg = ResultRegs[0];
7614 }
else if (ResultRegs.
size() == 2) {
7616 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7631 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7633 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7635 if (ResizeDst != DstReg)
7636 B.buildBitcast(DstReg, ResizeDst);
7640 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7641 B.buildConcatVectors(DstReg, ResultRegs);
7650 Register OrigDst =
MI.getOperand(0).getReg();
7652 LLT Ty =
B.getMRI()->getType(OrigDst);
7653 unsigned Size = Ty.getSizeInBits();
7656 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7658 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7659 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7662 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7664 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7673 B.setInsertPt(
B.getMBB(),
MI);
7678 B.setInsertPt(
B.getMBB(),
MI);
7684 MI.setDesc(
B.getTII().get(
Opc));
7685 MI.removeOperand(1);
7688 const unsigned MemSize = (
Size + 7) / 8;
7689 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7696 MI.addMemOperand(MF, MMO);
7697 if (Dst != OrigDst) {
7698 MI.getOperand(0).setReg(Dst);
7699 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7700 B.buildTrunc(OrigDst, Dst);
7722 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7723 MI.removeOperand(0);
7733 if (!ST.hasTrapHandler() ||
7737 return ST.supportsGetDoorbellID() ?
7750 MI.eraseFromParent();
7760 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7762 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7766 MI.eraseFromParent();
7775 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7782 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7802 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7805 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7806 B.buildCopy(SGPR01, Temp);
7807 B.buildInstr(AMDGPU::S_TRAP)
7810 MI.eraseFromParent();
7821 B.buildCopy(SGPR01, LiveIn);
7822 B.buildInstr(AMDGPU::S_TRAP)
7826 MI.eraseFromParent();
7835 if (ST.hasPrivEnabledTrap2NopBug()) {
7836 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7838 MI.eraseFromParent();
7842 B.buildInstr(AMDGPU::S_TRAP)
7844 MI.eraseFromParent();
7853 if (!ST.hasTrapHandler() ||
7857 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7860 B.buildInstr(AMDGPU::S_TRAP)
7864 MI.eraseFromParent();
7878 Register NodePtr =
MI.getOperand(2).getReg();
7879 Register RayExtent =
MI.getOperand(3).getReg();
7880 Register RayOrigin =
MI.getOperand(4).getReg();
7882 Register RayInvDir =
MI.getOperand(6).getReg();
7885 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7892 const unsigned NumVDataDwords = 4;
7893 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7894 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7896 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7898 const unsigned BaseOpcodes[2][2] = {
7899 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7900 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7901 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7905 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7906 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7907 : AMDGPU::MIMGEncGfx10NSA,
7908 NumVDataDwords, NumVAddrDwords);
7912 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7913 : AMDGPU::MIMGEncGfx10Default,
7914 NumVDataDwords, NumVAddrDwords);
7919 if (UseNSA && IsGFX11Plus) {
7920 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7921 auto SrcInt =
B.buildBitcast(V3I32, Src);
7922 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7923 auto Merged =
B.buildMergeLikeInstr(
7924 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7925 Ops.push_back(Merged.getReg(0));
7928 Ops.push_back(NodePtr);
7929 Ops.push_back(RayExtent);
7930 packLanes(RayOrigin);
7933 auto UnmergeRayDir =
7934 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayDir));
7935 auto UnmergeRayInvDir =
7936 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayInvDir));
7937 auto MergedDir =
B.buildMergeLikeInstr(
7940 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7941 UnmergeRayDir.getReg(0)}))
7944 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7945 UnmergeRayDir.getReg(1)}))
7948 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7949 UnmergeRayDir.getReg(2)}))
7951 Ops.push_back(MergedDir.getReg(0));
7954 packLanes(RayInvDir);
7958 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7959 Ops.push_back(Unmerge.getReg(0));
7960 Ops.push_back(Unmerge.getReg(1));
7962 Ops.push_back(NodePtr);
7964 Ops.push_back(RayExtent);
7966 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7967 auto SrcInt =
B.buildBitcast(V3I32, Src);
7968 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7969 Ops.push_back(Unmerge.getReg(0));
7970 Ops.push_back(Unmerge.getReg(1));
7971 Ops.push_back(Unmerge.getReg(2));
7974 packLanes(RayOrigin);
7976 auto UnmergeRayDir =
7977 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayDir));
7978 auto UnmergeRayInvDir =
7979 B.buildUnmerge({
I16,
I16,
I16},
B.buildBitcast(V3I16, RayInvDir));
7983 B.buildMergeLikeInstr(R1,
7984 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
7985 B.buildMergeLikeInstr(
7986 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
7987 B.buildMergeLikeInstr(
7988 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
7994 packLanes(RayInvDir);
8003 Ops.push_back(MergedOps);
8006 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8015 .addImm(IsA16 ? 1 : 0)
8018 MI.eraseFromParent();
8028 Register DstOrigin =
MI.getOperand(1).getReg();
8030 Register NodePtr =
MI.getOperand(4).getReg();
8031 Register RayExtent =
MI.getOperand(5).getReg();
8032 Register InstanceMask =
MI.getOperand(6).getReg();
8033 Register RayOrigin =
MI.getOperand(7).getReg();
8035 Register Offsets =
MI.getOperand(9).getReg();
8036 Register TDescr =
MI.getOperand(10).getReg();
8039 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8040 const unsigned NumVDataDwords = 10;
8041 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8043 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8044 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8045 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8048 auto RayExtentInstanceMaskVec =
8049 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8050 B.buildAnyExt(I32, InstanceMask)});
8052 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8053 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8059 .addUse(RayExtentInstanceMaskVec.getReg(0))
8066 MI.eraseFromParent();
8075 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8076 MI.eraseFromParent();
8083 if (!ST.hasArchitectedSGPRs())
8087 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8088 auto LSB =
B.buildConstant(I32, 25);
8089 auto Width =
B.buildConstant(I32, 5);
8090 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8091 MI.eraseFromParent();
8099 unsigned Width)
const {
8103 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8104 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8107 MI.eraseFromParent();
8127 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8131 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8134 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8135 MI.eraseFromParent();
8148 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8152 .addReg(Unmerge.getReg(0));
8156 .addReg(Unmerge.getReg(1));
8157 MI.eraseFromParent();
8169 case Intrinsic::amdgcn_icmp: {
8180 if (!Src1Const || Src1Const->Value != 0)
8184 int64_t Pred =
MI.getOperand(4).getImm();
8190 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8191 MI.eraseFromParent();
8194 case Intrinsic::sponentry:
8200 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8203 B.buildIntToPtr(DstReg, TmpReg);
8204 MI.eraseFromParent();
8206 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8208 B.buildFrameIndex(
MI.getOperand(0), FI);
8209 MI.eraseFromParent();
8212 case Intrinsic::amdgcn_if:
8213 case Intrinsic::amdgcn_else: {
8216 bool Negated =
false;
8228 std::swap(CondBrTarget, UncondBrTarget);
8230 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8231 if (IntrID == Intrinsic::amdgcn_if) {
8232 B.buildInstr(AMDGPU::SI_IF)
8235 .addMBB(UncondBrTarget);
8237 B.buildInstr(AMDGPU::SI_ELSE)
8240 .addMBB(UncondBrTarget);
8249 B.buildBr(*CondBrTarget);
8254 MI.eraseFromParent();
8255 BrCond->eraseFromParent();
8261 case Intrinsic::amdgcn_loop: {
8264 bool Negated =
false;
8274 std::swap(CondBrTarget, UncondBrTarget);
8276 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8277 B.buildInstr(AMDGPU::SI_LOOP)
8279 .addMBB(UncondBrTarget);
8284 B.buildBr(*CondBrTarget);
8286 MI.eraseFromParent();
8287 BrCond->eraseFromParent();
8294 case Intrinsic::amdgcn_wave_reduce_min:
8295 case Intrinsic::amdgcn_wave_reduce_umin:
8296 case Intrinsic::amdgcn_wave_reduce_fmin:
8297 case Intrinsic::amdgcn_wave_reduce_max:
8298 case Intrinsic::amdgcn_wave_reduce_umax:
8299 case Intrinsic::amdgcn_wave_reduce_fmax:
8300 case Intrinsic::amdgcn_wave_reduce_add:
8301 case Intrinsic::amdgcn_wave_reduce_fadd:
8302 case Intrinsic::amdgcn_wave_reduce_sub:
8303 case Intrinsic::amdgcn_wave_reduce_fsub:
8304 case Intrinsic::amdgcn_wave_reduce_and:
8305 case Intrinsic::amdgcn_wave_reduce_or:
8306 case Intrinsic::amdgcn_wave_reduce_xor: {
8311 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8312 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8313 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8314 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8315 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8316 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8317 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8318 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8319 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8326 .addUse(Ext.getReg(0))
8327 .addImm(
MI.getOperand(3).getImm());
8329 B.buildFPTrunc(DstReg, NewDst);
8331 B.buildTrunc(DstReg, NewDst);
8332 MI.eraseFromParent();
8335 case Intrinsic::amdgcn_addrspacecast_nonnull:
8337 case Intrinsic::amdgcn_make_buffer_rsrc:
8339 case Intrinsic::amdgcn_kernarg_segment_ptr:
8342 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8343 MI.eraseFromParent();
8349 case Intrinsic::amdgcn_implicitarg_ptr:
8351 case Intrinsic::amdgcn_workitem_id_x:
8354 case Intrinsic::amdgcn_workitem_id_y:
8357 case Intrinsic::amdgcn_workitem_id_z:
8360 case Intrinsic::amdgcn_workgroup_id_x:
8365 case Intrinsic::amdgcn_workgroup_id_y:
8370 case Intrinsic::amdgcn_workgroup_id_z:
8375 case Intrinsic::amdgcn_cluster_id_x:
8376 return ST.hasClusters() &&
8379 case Intrinsic::amdgcn_cluster_id_y:
8380 return ST.hasClusters() &&
8383 case Intrinsic::amdgcn_cluster_id_z:
8384 return ST.hasClusters() &&
8387 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8388 return ST.hasClusters() &&
8391 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8392 return ST.hasClusters() &&
8395 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8396 return ST.hasClusters() &&
8399 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8400 return ST.hasClusters() &&
8402 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8403 return ST.hasClusters() &&
8406 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8407 return ST.hasClusters() &&
8410 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8411 return ST.hasClusters() &&
8414 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8415 return ST.hasClusters() &&
8419 case Intrinsic::amdgcn_wave_id:
8421 case Intrinsic::amdgcn_lds_kernel_id:
8424 case Intrinsic::amdgcn_dispatch_ptr:
8427 case Intrinsic::amdgcn_queue_ptr:
8430 case Intrinsic::amdgcn_implicit_buffer_ptr:
8433 case Intrinsic::amdgcn_dispatch_id:
8436 case Intrinsic::r600_read_ngroups_x:
8440 case Intrinsic::r600_read_ngroups_y:
8443 case Intrinsic::r600_read_ngroups_z:
8446 case Intrinsic::r600_read_local_size_x:
8449 case Intrinsic::r600_read_local_size_y:
8453 case Intrinsic::r600_read_local_size_z:
8456 case Intrinsic::amdgcn_fdiv_fast:
8458 case Intrinsic::amdgcn_is_shared:
8460 case Intrinsic::amdgcn_is_private:
8462 case Intrinsic::amdgcn_wavefrontsize: {
8463 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8464 MI.eraseFromParent();
8467 case Intrinsic::amdgcn_s_buffer_load:
8469 case Intrinsic::amdgcn_raw_buffer_store:
8470 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8471 case Intrinsic::amdgcn_struct_buffer_store:
8472 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8474 case Intrinsic::amdgcn_raw_buffer_store_format:
8475 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8476 case Intrinsic::amdgcn_struct_buffer_store_format:
8477 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8479 case Intrinsic::amdgcn_raw_tbuffer_store:
8480 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8481 case Intrinsic::amdgcn_struct_tbuffer_store:
8482 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8484 case Intrinsic::amdgcn_raw_buffer_load:
8485 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8486 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8487 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8488 case Intrinsic::amdgcn_struct_buffer_load:
8489 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8490 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8491 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8493 case Intrinsic::amdgcn_raw_buffer_load_format:
8494 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8495 case Intrinsic::amdgcn_struct_buffer_load_format:
8496 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8498 case Intrinsic::amdgcn_raw_tbuffer_load:
8499 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8500 case Intrinsic::amdgcn_struct_tbuffer_load:
8501 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8503 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8504 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8505 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8506 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8507 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8508 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8509 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8510 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8511 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8512 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8513 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8514 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8515 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8516 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8517 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8518 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8519 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8520 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8521 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8522 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8523 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8524 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8525 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8526 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8527 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8528 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8529 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8530 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8531 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8532 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8533 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8534 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8535 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8536 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8537 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8538 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8539 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8540 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8541 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8542 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8543 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8544 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8545 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8546 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8547 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8548 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8549 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8550 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8551 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8552 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8553 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8554 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8555 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8556 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8557 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8558 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8559 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8560 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8561 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8562 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8563 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8564 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8565 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8566 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8567 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8568 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8569 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8570 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8571 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8572 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8573 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8574 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8576 case Intrinsic::amdgcn_rsq_clamp:
8578 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8580 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8581 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8583 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8584 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8585 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8586 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8587 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8588 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8589 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8590 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8594 if (IndexArgTy != I64) {
8595 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8596 :
B.buildAnyExt(I64, Index);
8597 MI.getOperand(5).setReg(NewIndex.getReg(0));
8601 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8602 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8603 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8604 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8605 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8606 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8607 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8608 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8611 if (MRI.
getType(Index) != I32)
8612 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8615 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8616 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8617 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8618 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8619 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8620 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8621 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8622 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8623 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8625 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8629 if (IndexArgTy != IdxTy) {
8630 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8631 :
B.buildAnyExt(IdxTy, Index);
8632 MI.getOperand(7).setReg(NewIndex.getReg(0));
8637 case Intrinsic::amdgcn_fmed3: {
8643 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8644 MI.removeOperand(1);
8648 case Intrinsic::amdgcn_readlane:
8649 case Intrinsic::amdgcn_writelane:
8650 case Intrinsic::amdgcn_readfirstlane:
8651 case Intrinsic::amdgcn_permlane16:
8652 case Intrinsic::amdgcn_permlanex16:
8653 case Intrinsic::amdgcn_permlane64:
8654 case Intrinsic::amdgcn_set_inactive:
8655 case Intrinsic::amdgcn_set_inactive_chain_arg:
8656 case Intrinsic::amdgcn_mov_dpp8:
8657 case Intrinsic::amdgcn_update_dpp:
8658 case Intrinsic::amdgcn_permlane_bcast:
8659 case Intrinsic::amdgcn_permlane_up:
8660 case Intrinsic::amdgcn_permlane_down:
8661 case Intrinsic::amdgcn_permlane_xor:
8663 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8665 case Intrinsic::amdgcn_dead: {
8669 MI.eraseFromParent();
8672 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8673 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8674 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8675 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8676 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8677 MI.eraseFromParent();
8679 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8680 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8681 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8682 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8683 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8684 MI.eraseFromParent();
8686 case Intrinsic::amdgcn_av_load_b128:
8687 case Intrinsic::amdgcn_av_store_b128: {
8688 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8689 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8690 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8692 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8693 **
MI.memoperands_begin());
8694 MI.eraseFromParent();
8697 case Intrinsic::amdgcn_flat_load_monitor_b32:
8698 case Intrinsic::amdgcn_flat_load_monitor_b64:
8699 case Intrinsic::amdgcn_flat_load_monitor_b128:
8700 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8701 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8702 .add(
MI.getOperand(0))
8703 .add(
MI.getOperand(2))
8704 .addMemOperand(*
MI.memoperands_begin());
8705 MI.eraseFromParent();
8707 case Intrinsic::amdgcn_global_load_monitor_b32:
8708 case Intrinsic::amdgcn_global_load_monitor_b64:
8709 case Intrinsic::amdgcn_global_load_monitor_b128:
8710 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8711 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8712 .add(
MI.getOperand(0))
8713 .add(
MI.getOperand(2))
8714 .addMemOperand(*
MI.memoperands_begin());
8715 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.