36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
488 if (!ST.hasDwordx3LoadStores())
501 if (AlignBits < MemSize) {
504 Align(AlignBits / 8)))
534 const unsigned Size = Ty.getSizeInBits();
535 if (Ty.isPointerVector())
545 unsigned EltSize = Ty.getScalarSizeInBits();
546 return EltSize != 32 && EltSize != 64;
560 const unsigned Size = Ty.getSizeInBits();
561 if (
Size != MemSizeInBits)
562 return Size <= 32 && Ty.isVector();
568 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
577 uint64_t AlignInBits,
unsigned AddrSpace,
587 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
598 if (AlignInBits < RoundedSize)
605 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
617 Query.
Types[1].getAddressSpace(), Opcode);
637 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
641 std::array<Register, 4> VectorElems;
642 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
643 for (
unsigned I = 0;
I < NumParts; ++
I)
645 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
646 B.buildMergeValues(MO, VectorElems);
651 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
652 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
653 B.buildIntToPtr(MO, Scalar);
673 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
675 for (
unsigned I = 0;
I < NumParts; ++
I)
677 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
679 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
680 return B.buildBitcast(VectorTy, Scalar).getReg(0);
708 const LLT BufferStridedPtr =
711 const LLT CodePtr = FlatPtr;
713 const std::initializer_list<LLT> AddrSpaces64 = {
714 GlobalPtr, ConstantPtr, FlatPtr
717 const std::initializer_list<LLT> AddrSpaces32 = {
718 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
721 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
723 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
724 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
725 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
754 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
756 if (ST.hasAnyPackedU64Ops()) {
759 .clampMaxNumElementsStrict(0,
S16, 2)
765 }
else if (ST.hasScalarAddSub64()) {
768 .clampMaxNumElementsStrict(0,
S16, 2)
776 .clampMaxNumElementsStrict(0,
S16, 2)
783 if (ST.hasScalarSMulU64()) {
786 .clampMaxNumElementsStrict(0,
S16, 2)
794 .clampMaxNumElementsStrict(0,
S16, 2)
804 .minScalarOrElt(0,
S16)
809 }
else if (ST.has16BitInsts()) {
843 .widenScalarToNextMultipleOf(0, 32)
853 if (ST.hasMad64_32())
858 if (ST.hasIntClamp()) {
881 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
891 if (ST.hasVOP3PInsts()) {
893 .clampMaxNumElements(0,
S8, 2)
914 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
930 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
973 auto &FCanonicalizeActions =
975 auto &StrictFPOpActions =
982 if (ST.has16BitInsts()) {
983 if (ST.hasVOP3PInsts()) {
985 FCanonicalizeActions.legalFor({
F16,
V2F16});
986 StrictFPOpActions.legalFor({
F16,
V2F16});
988 FPOpActions.legalFor({
F16});
989 FCanonicalizeActions.legalFor({
F16});
990 StrictFPOpActions.legalFor({
F16});
993 TrigActions.customFor({
F16});
994 FDIVActions.customFor({
F16});
997 if (ST.hasBF16PackedInsts()) {
1001 .clampMaxNumElementsStrict(0,
BF16, 2);
1004 .clampMaxNumElementsStrict(0,
BF16, 2);
1007 .clampMaxNumElementsStrict(0,
BF16, 2);
1013 if (ST.hasAnyPackedFP32Ops()) {
1014 FPOpActions.legalFor({
V2F32});
1015 FCanonicalizeActions.legalFor({
V2F32});
1016 StrictFPOpActions.legalFor({
V2F32});
1017 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1018 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1019 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1022 if (ST.hasAnyPackedFP64Ops()) {
1023 FPOpActions.legalFor({
V2F64});
1024 FCanonicalizeActions.legalFor({
V2F64});
1025 StrictFPOpActions.legalFor({
V2F64});
1026 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1027 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1028 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1031 auto &MinNumMaxNumIeee =
1034 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1039 if (ST.has16BitInsts()) {
1040 MinNumMaxNumIeee.legalFor({
F16});
1041 MinNumMaxNum.customFor({
F16});
1045 if (ST.hasVOP3PInsts()) {
1046 MinNumMaxNumIeee.legalFor({
V2F16})
1049 .clampMaxNumElements(0,
F16, 2);
1050 MinNumMaxNum.customFor({
V2F16})
1053 .clampMaxNumElements(0,
F16, 2);
1057 if (ST.hasAnyPackedFP64Ops()) {
1058 MinNumMaxNum.customFor({
V2F64})
1061 .clampMaxNumElements(0,
F64, 2);
1065 if (ST.hasBF16PackedInsts()) {
1066 MinNumMaxNumIeee.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1069 .clampMaxNumElementsStrict(0,
BF16, 2);
1077 if (!ST.has16BitInsts()) {
1078 MinNumMaxNumIeee.minScalar(0,
F32);
1079 MinNumMaxNum.minScalar(0,
F32);
1082 if (ST.hasVOP3PInsts()) {
1083 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1084 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1085 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1093 if (!ST.has16BitInsts()) {
1104 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1107 if (ST.hasAnyPackedFP32Ops())
1111 if (ST.has16BitInsts()) {
1114 .legalFor(ST.hasBF16TransInsts(), {BF16})
1124 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1146 if (ST.hasFractBug()) {
1160 .legalFor({{
F32, I32}, {
F64, I32}})
1180 if (ST.hasCvtPkF16F32Inst()) {
1182 .clampMaxNumElements(0,
F16, 2);
1195 if (ST.has16BitInsts()) {
1209 if (ST.hasBF16PackedInsts()) {
1212 .clampMaxNumElementsStrict(0,
BF16, 2);
1217 if (ST.hasAnyPackedFP32Ops())
1225 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1226 FMad.customFor({
F32,
F16});
1227 else if (ST.hasMadMacF32Insts())
1228 FMad.customFor({
F32});
1229 else if (ST.hasMadF16())
1230 FMad.customFor({
F16});
1235 if (ST.has16BitInsts()) {
1238 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1246 .clampMaxNumElements(0,
S16, 2)
1262 .legalFor({{
F32, I32}, {
F64, I32}})
1266 if (ST.has16BitInsts())
1274 .legalFor({{I32,
F32}, {I32,
F64}})
1275 .customFor({{I64,
F32}, {I64,
F64}})
1278 .widenScalarFor({{I16,
BF16}, {I32,
BF16}, {I64,
BF16}},
1280 if (ST.has16BitInsts())
1289 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1290 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1291 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1295 if (
ST.has16BitInsts())
1298 if (
ST.hasVCvtPkIU16F32())
1308 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1309 .clampScalar(0, I16, I64)
1313 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1319 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1323 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1324 .clampScalar(0, I16, I64)
1328 auto &RoundingActions = getActionDefinitionsBuilder(
1329 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1330 if (
ST.has16BitInsts())
1338 if (!
ST.has16BitInsts())
1341 getActionDefinitionsBuilder(G_PTR_ADD)
1347 getActionDefinitionsBuilder(G_PTRMASK)
1349 .scalarSameSizeAs(1, 0)
1353 getActionDefinitionsBuilder(G_ICMP)
1365 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1366 .legalForCartesianProduct(
1367 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1368 if (
ST.has16BitInsts()) {
1369 CmpBuilder.legalFor({{
S1,
S16}});
1378 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1381 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1382 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1384 if (
ST.hasSALUFloatInsts())
1385 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1388 .widenScalarToNextPow2(1)
1392 getActionDefinitionsBuilder(G_FPOW)
1394 .clampScalar(0,
F32,
F32)
1397 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1399 getActionDefinitionsBuilder(G_FLOG2)
1400 .legalFor(
ST.has16BitInsts(), {F16})
1401 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1407 getActionDefinitionsBuilder(G_FEXP2)
1408 .legalFor(
ST.has16BitInsts(), {F16})
1409 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1415 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1419 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1424 getActionDefinitionsBuilder(G_CTPOP)
1426 .clampScalar(0,
S32,
S32)
1427 .widenScalarToNextPow2(1, 32)
1428 .clampScalar(1,
S32,
S64)
1430 .widenScalarToNextPow2(0, 32);
1433 if (
ST.has16BitInsts())
1434 getActionDefinitionsBuilder(G_IS_FPCLASS)
1435 .legalForCartesianProduct({
I1}, FPTypes16)
1436 .widenScalarToNextPow2(1)
1440 getActionDefinitionsBuilder(G_IS_FPCLASS)
1441 .legalForCartesianProduct({
I1}, FPTypesBase)
1442 .lowerFor({
I1,
F16})
1443 .widenScalarToNextPow2(1)
1450 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1452 .clampScalar(0,
S32,
S32)
1453 .clampScalar(1,
S32,
S64)
1454 .widenScalarToNextPow2(0, 32)
1455 .widenScalarToNextPow2(1, 32)
1459 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1462 .clampScalar(0,
S32,
S32)
1463 .clampScalar(1,
S32,
S64)
1465 .widenScalarToNextPow2(0, 32)
1466 .widenScalarToNextPow2(1, 32);
1468 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1470 .clampScalar(0,
S32,
S32)
1471 .clampScalar(1,
S32,
S64)
1473 .widenScalarToNextPow2(0, 32)
1474 .widenScalarToNextPow2(1, 32);
1476 getActionDefinitionsBuilder(G_CTLS)
1479 .clampScalar(0,
S32,
S32)
1480 .clampScalar(1,
S32,
S32);
1484 getActionDefinitionsBuilder(G_BITREVERSE)
1486 .clampScalar(0,
S32,
S64)
1488 .widenScalarToNextPow2(0);
1490 if (
ST.has16BitInsts()) {
1491 getActionDefinitionsBuilder(G_BSWAP)
1493 .clampMaxNumElementsStrict(0,
S16, 2)
1496 .widenScalarToNextPow2(0)
1497 .clampScalar(0,
S16,
S32)
1500 if (
ST.hasVOP3PInsts()) {
1501 getActionDefinitionsBuilder(G_ABS)
1503 .clampMaxNumElements(0,
S16, 2)
1505 .widenScalarToNextPow2(0)
1508 if (
ST.useMinMaxI64Insts()) {
1509 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1511 .clampMaxNumElements(0,
S16, 2)
1513 .widenScalarToNextPow2(0)
1517 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1519 .clampMaxNumElements(0,
S16, 2)
1521 .widenScalarToNextPow2(0)
1526 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1528 .widenScalarToNextPow2(0)
1535 getActionDefinitionsBuilder(G_BSWAP)
1540 .widenScalarToNextPow2(0)
1545 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1548 .widenScalarToNextPow2(0)
1553 getActionDefinitionsBuilder(G_INTTOPTR)
1555 .legalForCartesianProduct(AddrSpaces64, {
S64})
1556 .legalForCartesianProduct(AddrSpaces32, {
S32})
1569 getActionDefinitionsBuilder(G_PTRTOINT)
1571 .legalForCartesianProduct(AddrSpaces64, {
S64})
1572 .legalForCartesianProduct(AddrSpaces32, {
S32})
1585 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1589 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1590 bool IsLoad) ->
bool {
1594 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1607 !
ST.hasUsableDSOffset() && Query.
MMODescrs[0].AlignInBits == 32)
1612 unsigned NumRegs = (MemSize + 31) / 32;
1614 if (!
ST.hasDwordx3LoadStores())
1625 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1626 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1627 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1628 unsigned LocalAlign64 =
ST.hasUsableDSOffset() ? 32 : 64;
1634 for (
unsigned Op : {G_LOAD, G_STORE}) {
1635 const bool IsStore =
Op == G_STORE;
1637 auto &Actions = getActionDefinitionsBuilder(
Op);
1640 Actions.legalForTypesWithMemDesc(
1641 {{
S32, GlobalPtr,
S32, GlobalAlign32},
1644 {
S64, GlobalPtr,
S64, GlobalAlign32},
1647 {
S32, GlobalPtr,
S8, GlobalAlign8},
1648 {
S32, GlobalPtr,
S16, GlobalAlign16},
1650 {
S32, LocalPtr,
S32, 32},
1651 {
S64, LocalPtr,
S64, LocalAlign64},
1653 {
S32, LocalPtr,
S8, 8},
1654 {
S32, LocalPtr,
S16, 16},
1657 {
S32, PrivatePtr,
S32, 32},
1658 {
S32, PrivatePtr,
S8, 8},
1659 {
S32, PrivatePtr,
S16, 16},
1662 {
S32, ConstantPtr,
S32, GlobalAlign32},
1665 {
S64, ConstantPtr,
S64, GlobalAlign32}});
1667 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1668 {{S16, GlobalPtr, S8, GlobalAlign8},
1669 {S16, GlobalPtr, S16, GlobalAlign16},
1670 {S16, LocalPtr, S8, 8},
1671 {S16, LocalPtr, S16, 16},
1672 {S16, PrivatePtr, S8, 8},
1673 {S16, PrivatePtr, S16, 16}});
1683 Actions.unsupportedIf(
1684 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1698 Actions.customIf(
typeIs(1, Constant32Ptr));
1724 return !Query.
Types[0].isVector() &&
1725 needToSplitMemOp(Query,
Op == G_LOAD);
1727 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1732 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1735 if (DstSize > MemSize)
1741 if (MemSize > MaxSize)
1749 return Query.
Types[0].isVector() &&
1750 needToSplitMemOp(Query,
Op == G_LOAD);
1752 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1766 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1767 if (MemSize > MaxSize) {
1771 if (MaxSize % EltSize == 0) {
1777 unsigned NumPieces = MemSize / MaxSize;
1781 if (NumPieces == 1 || NumPieces >= NumElts ||
1782 NumElts % NumPieces != 0)
1783 return std::pair(0, EltTy);
1791 return std::pair(0, EltTy);
1806 return std::pair(0, EltTy);
1811 .widenScalarToNextPow2(0)
1818 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1819 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1820 {
S32, GlobalPtr,
S16, 2 * 8},
1821 {
S32, LocalPtr,
S8, 8},
1822 {
S32, LocalPtr,
S16, 16},
1823 {
S32, PrivatePtr,
S8, 8},
1824 {
S32, PrivatePtr,
S16, 16},
1825 {
S32, ConstantPtr,
S8, 8},
1826 {
S32, ConstantPtr,
S16, 2 * 8}})
1827 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1828 {{S16, GlobalPtr, S8, GlobalAlign8},
1829 {S16, LocalPtr, S8, GlobalAlign8},
1830 {S16, PrivatePtr, S8, GlobalAlign8},
1831 {S16, ConstantPtr, S8, GlobalAlign8}})
1836 if (
ST.hasFlatAddressSpace()) {
1837 ExtLoads.legalForTypesWithMemDesc(
1838 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1840 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1841 {{S16, FlatPtr, S8, GlobalAlign8}});
1849 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1851 ExtLoads.narrowScalarIf(
1858 ExtLoads.clampScalar(0,
S32,
S32)
1859 .widenScalarToNextPow2(0)
1862 auto &Atomics = getActionDefinitionsBuilder(
1863 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1864 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1865 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1866 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1867 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1868 {
S64, GlobalPtr}, {
S64, LocalPtr},
1869 {
S32, RegionPtr}, {
S64, RegionPtr}});
1870 if (
ST.hasFlatAddressSpace()) {
1871 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1875 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1876 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1877 if (
ST.hasFlatAddressSpace()) {
1878 Atomics32.legalFor({{
S32, FlatPtr}});
1882 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1883 if (
ST.hasLDSFPAtomicAddF32()) {
1885 if (
ST.hasLdsAtomicAddF64())
1887 if (
ST.hasAtomicDsPkAdd16Insts())
1890 if (
ST.hasAtomicFaddInsts())
1892 if (
ST.hasFlatAtomicFaddF32Inst())
1895 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1899 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1902 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1903 ST.hasAtomicBufferGlobalPkAddF16Insts())
1905 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1907 if (
ST.hasAtomicFlatPkAdd16Insts())
1913 auto &AtomicFMinFMax =
1914 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1915 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1917 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1918 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1919 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1920 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1921 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1922 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1923 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1924 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1928 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1929 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1930 {
S32, FlatPtr}, {
S64, FlatPtr}})
1931 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1932 {
S32, RegionPtr}, {
S64, RegionPtr}});
1936 getActionDefinitionsBuilder(G_SELECT)
1938 LocalPtr, FlatPtr, PrivatePtr,
1942 .clampScalar(0,
S16,
S64)
1946 .clampMaxNumElements(0,
S32, 2)
1947 .clampMaxNumElements(0, LocalPtr, 2)
1948 .clampMaxNumElements(0, PrivatePtr, 2)
1950 .widenScalarToNextPow2(0)
1955 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1957 if (
ST.has16BitInsts()) {
1958 if (
ST.hasVOP3PInsts()) {
1960 .clampMaxNumElements(0,
S16, 2);
1962 Shifts.legalFor({{
S16,
S16}});
1965 Shifts.widenScalarIf(
1970 const LLT AmountTy = Query.
Types[1];
1976 Shifts.clampScalar(1,
S32,
S32);
1977 Shifts.widenScalarToNextPow2(0, 16);
1978 Shifts.clampScalar(0,
S16,
S64);
1980 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1988 Shifts.clampScalar(1,
S32,
S32);
1989 Shifts.widenScalarToNextPow2(0, 32);
1990 Shifts.clampScalar(0,
S32,
S64);
1992 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1997 Shifts.scalarize(0);
1999 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
2000 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
2001 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
2002 unsigned IdxTypeIdx = 2;
2004 getActionDefinitionsBuilder(
Op)
2006 const LLT EltTy = Query.
Types[EltTypeIdx];
2007 const LLT VecTy = Query.
Types[VecTypeIdx];
2008 const LLT IdxTy = Query.
Types[IdxTypeIdx];
2010 const bool isLegalVecType =
2020 return (EltSize == 32 || EltSize == 64) &&
2036 const LLT EltTy = Query.
Types[EltTypeIdx];
2037 const LLT VecTy = Query.
Types[VecTypeIdx];
2041 const unsigned TargetEltSize =
2042 DstEltSize % 64 == 0 ? 64 : 32;
2043 return std::pair(VecTypeIdx,
2047 .clampScalar(EltTypeIdx,
S32,
S64)
2048 .clampScalar(VecTypeIdx,
S32,
S64)
2049 .clampScalar(IdxTypeIdx,
S32,
S32)
2050 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2059 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2061 const LLT &EltTy = Query.
Types[1].getElementType();
2062 return Query.
Types[0] != EltTy;
2065 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2066 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2067 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2068 getActionDefinitionsBuilder(
Op)
2071 const LLT BigTy = Query.
Types[BigTyIdx];
2077 const LLT LitTy = Query.
Types[LitTyIdx];
2082 .widenScalarToNextPow2(BigTyIdx, 32)
2090 const LLT BigTy = Query.
Types[BigTyIdx];
2091 const LLT LitTy = Query.
Types[LitTyIdx];
2099 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2109 if (
ST.hasScalarPackInsts()) {
2112 .minScalarOrElt(0,
S16)
2115 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2119 BuildVector.customFor({
V2S16,
S16});
2120 BuildVector.minScalarOrElt(0,
S32);
2122 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2130 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2132 .clampMaxNumElements(0,
S32, 32)
2133 .clampMaxNumElements(1,
S16, 2)
2134 .clampMaxNumElements(0,
S16, 64);
2136 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2139 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2140 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2141 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2143 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2144 const LLT Ty = Query.
Types[TypeIdx];
2156 getActionDefinitionsBuilder(
Op)
2160 const LLT BigTy = Query.
Types[BigTyIdx];
2166 .widenScalarToNextPow2(LitTyIdx, 16)
2175 .clampScalar(LitTyIdx,
S32,
S512)
2176 .widenScalarToNextPow2(LitTyIdx, 32)
2180 return notValidElt(Query, LitTyIdx);
2185 return notValidElt(Query, BigTyIdx);
2190 if (
Op == G_MERGE_VALUES) {
2191 Builder.widenScalarIf(
2194 const LLT Ty = Query.
Types[LitTyIdx];
2200 Builder.widenScalarIf(
2202 const LLT Ty = Query.
Types[BigTyIdx];
2208 const LLT &Ty = Query.
Types[BigTyIdx];
2210 if (NewSizeInBits >= 256) {
2212 if (RoundedTo < NewSizeInBits)
2213 NewSizeInBits = RoundedTo;
2215 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2224 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2225 .legalFor({{
S32}, {
S64}})
2226 .clampScalar(0,
S32,
S64);
2228 if (
ST.hasVOP3PInsts()) {
2229 SextInReg.lowerFor({{
V2S16}})
2233 .clampMaxNumElementsStrict(0,
S16, 2);
2234 }
else if (
ST.has16BitInsts()) {
2235 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2239 SextInReg.lowerFor({{
S32}, {
S64}});
2244 .clampScalar(0,
S32,
S64)
2247 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2251 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2252 FSHRActionDefs.legalFor({{
S32,
S32}})
2253 .clampMaxNumElementsStrict(0,
S16, 2);
2254 if (
ST.hasVOP3PInsts())
2256 FSHRActionDefs.scalarize(0).lower();
2258 if (
ST.hasVOP3PInsts()) {
2259 getActionDefinitionsBuilder(G_FSHL)
2261 .clampMaxNumElementsStrict(0,
S16, 2)
2265 getActionDefinitionsBuilder(G_FSHL)
2270 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2273 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2275 getActionDefinitionsBuilder(G_FENCE)
2278 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2283 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2285 .clampScalar(1,
S32,
S32)
2286 .clampScalar(0,
S32,
S64)
2287 .widenScalarToNextPow2(0)
2290 getActionDefinitionsBuilder(
2294 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2300 if (
ST.hasIEEEMinimumMaximumInsts()) {
2301 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2302 .legalFor(FPTypesPK16)
2303 .clampMaxNumElements(0,
F16, 2)
2305 }
else if (
ST.hasVOP3PInsts()) {
2306 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2308 .clampMaxNumElementsStrict(0,
F16, 2)
2312 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2314 .clampScalar(0,
F32,
F64)
2318 getActionDefinitionsBuilder(
2319 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2322 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2324 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2325 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2326 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2329 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2331 getActionDefinitionsBuilder(
2332 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2333 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2334 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2335 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2340 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2341 G_INTRINSIC_CONVERGENT,
2342 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2354 switch (
MI.getOpcode()) {
2355 case TargetOpcode::G_ADDRSPACE_CAST:
2357 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2359 case TargetOpcode::G_FCEIL:
2361 case TargetOpcode::G_FREM:
2363 case TargetOpcode::G_INTRINSIC_TRUNC:
2365 case TargetOpcode::G_SITOFP:
2367 case TargetOpcode::G_UITOFP:
2369 case TargetOpcode::G_FPTOSI:
2371 case TargetOpcode::G_FPTOUI:
2373 case TargetOpcode::G_FMINNUM:
2374 case TargetOpcode::G_FMAXNUM:
2375 case TargetOpcode::G_FMINIMUMNUM:
2376 case TargetOpcode::G_FMAXIMUMNUM:
2378 case TargetOpcode::G_EXTRACT:
2380 case TargetOpcode::G_INSERT:
2382 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2384 case TargetOpcode::G_INSERT_VECTOR_ELT:
2386 case TargetOpcode::G_FSIN:
2387 case TargetOpcode::G_FCOS:
2389 case TargetOpcode::G_GLOBAL_VALUE:
2391 case TargetOpcode::G_LOAD:
2392 case TargetOpcode::G_SEXTLOAD:
2393 case TargetOpcode::G_ZEXTLOAD:
2395 case TargetOpcode::G_STORE:
2397 case TargetOpcode::G_FMAD:
2399 case TargetOpcode::G_FDIV:
2401 case TargetOpcode::G_FFREXP:
2403 case TargetOpcode::G_FSQRT:
2405 case TargetOpcode::G_UDIV:
2406 case TargetOpcode::G_UREM:
2407 case TargetOpcode::G_UDIVREM:
2409 case TargetOpcode::G_SDIV:
2410 case TargetOpcode::G_SREM:
2411 case TargetOpcode::G_SDIVREM:
2413 case TargetOpcode::G_ATOMIC_CMPXCHG:
2415 case TargetOpcode::G_FLOG2:
2417 case TargetOpcode::G_FLOG:
2418 case TargetOpcode::G_FLOG10:
2420 case TargetOpcode::G_FEXP2:
2422 case TargetOpcode::G_FEXP:
2423 case TargetOpcode::G_FEXP10:
2425 case TargetOpcode::G_FPOW:
2427 case TargetOpcode::G_FFLOOR:
2429 case TargetOpcode::G_BUILD_VECTOR:
2430 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2432 case TargetOpcode::G_MUL:
2434 case TargetOpcode::G_CTLZ:
2435 case TargetOpcode::G_CTTZ:
2437 case TargetOpcode::G_CTLS:
2439 case TargetOpcode::G_CTLZ_ZERO_POISON:
2441 case TargetOpcode::G_STACKSAVE:
2443 case TargetOpcode::G_GET_FPENV:
2445 case TargetOpcode::G_SET_FPENV:
2447 case TargetOpcode::G_TRAP:
2449 case TargetOpcode::G_DEBUGTRAP:
2461 unsigned BaseAS = AS;
2466 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2470 auto Tag =
B.buildConstant(
S32, SANum);
2471 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2477Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2487 if (ST.hasApertureRegs()) {
2491 const unsigned ApertureRegNo =
2492 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2493 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2494 !ST.hasGloballyAddressableScratch()) &&
2495 "Cannot use src_private_base with globally addressable scratch!");
2498 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2499 return B.buildUnmerge(I32, Dst).getReg(1);
2514 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2530 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2533 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2547 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2555 B.buildObjectPtrOffset(
2558 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2566 switch (Def->getOpcode()) {
2567 case AMDGPU::G_FRAME_INDEX:
2568 case AMDGPU::G_GLOBAL_VALUE:
2569 case AMDGPU::G_BLOCK_ADDR:
2571 case AMDGPU::G_CONSTANT: {
2572 const ConstantInt *CI = Def->getOperand(1).getCImm();
2587 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2596 unsigned SrcAS = SrcTy.getAddressSpace();
2610 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2617 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2619 ST.hasGloballyAddressableScratch()) {
2622 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2624 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2625 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2627 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2628 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2629 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2632 return B.buildExtract(Dst, Src, 0).getReg(0);
2636 castFlatToLocalOrPrivate(Dst);
2637 MI.eraseFromParent();
2643 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2644 auto FlatNull =
B.buildConstant(SrcTy, 0);
2647 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2651 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2653 MI.eraseFromParent();
2660 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2663 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2666 ST.hasGloballyAddressableScratch()) {
2670 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2671 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2675 if (ST.isWave64()) {
2676 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2682 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2683 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2685 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2689 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2690 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2692 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2693 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2702 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2706 castLocalOrPrivateToFlat(Dst);
2707 MI.eraseFromParent();
2711 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2718 SegmentNull.getReg(0));
2720 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2722 MI.eraseFromParent();
2727 SrcTy.getSizeInBits() == 64) {
2729 B.buildExtract(Dst, Src, 0);
2730 MI.eraseFromParent();
2737 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2738 auto PtrLo =
B.buildPtrToInt(I32, Src);
2739 if (AddrHiVal == 0) {
2740 auto Zext =
B.buildZExt(I64, PtrLo);
2741 B.buildIntToPtr(Dst, Zext);
2743 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2744 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2747 MI.eraseFromParent();
2754 MI.eraseFromParent();
2763 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2768 auto C1 =
B.buildFConstant(Ty, C1Val);
2769 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2772 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2773 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2775 auto C2 =
B.buildFConstant(Ty, C2Val);
2776 auto Fabs =
B.buildFAbs(Ty, Src);
2779 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2780 MI.eraseFromParent();
2797 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2799 const auto Zero =
B.buildFConstant(
F64, 0.0);
2800 const auto One =
B.buildFConstant(
F64, 1.0);
2803 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2804 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2807 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2808 MI.eraseFromParent();
2816 Register Src0Reg =
MI.getOperand(1).getReg();
2817 Register Src1Reg =
MI.getOperand(2).getReg();
2818 auto Flags =
MI.getFlags();
2821 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2822 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2823 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2824 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2825 MI.eraseFromParent();
2831 const unsigned FractBits = 52;
2832 const unsigned ExpBits = 11;
2835 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2836 auto Const1 =
B.buildConstant(I32, ExpBits);
2838 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2840 .addUse(Const0.getReg(0))
2841 .addUse(Const1.getReg(0));
2843 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2856 auto SrcInt =
B.buildBitcast(I64, Src);
2859 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2866 const unsigned FractBits = 52;
2869 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2870 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2872 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2874 const auto Zero32 =
B.buildConstant(I32, 0);
2877 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2879 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2880 auto Not =
B.buildNot(I64, Shr);
2881 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2882 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2887 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2888 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2889 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2890 MI.eraseFromParent();
2906 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2907 auto ThirtyTwo =
B.buildConstant(I32, 32);
2910 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2911 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2913 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2914 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2917 B.buildFAdd(Dst, LdExp, CvtLo);
2918 MI.eraseFromParent();
2924 auto One =
B.buildConstant(I32, 1);
2928 auto ThirtyOne =
B.buildConstant(I32, 31);
2929 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2930 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2931 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2932 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2933 .addUse(Unmerge.getReg(1));
2934 auto LS2 =
B.buildSub(I32, LS, One);
2935 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2937 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2938 auto Norm =
B.buildShl(I64, Src, ShAmt);
2939 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2940 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2941 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2942 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2943 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2944 B.buildFLdexp(Dst, FVal, Scale);
2945 MI.eraseFromParent();
2965 unsigned Flags =
MI.getFlags();
2976 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2984 auto SrcInt =
B.buildBitcast(I32, Src);
2985 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2986 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2990 K0 =
B.buildFConstant(
2992 K1 =
B.buildFConstant(
2995 K0 =
B.buildFConstant(
2997 K1 =
B.buildFConstant(
3001 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
3002 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
3003 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
3005 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
3006 :
B.buildFPTOUI(I32, FloorMul);
3007 auto Lo =
B.buildFPTOUI(I32, Fma);
3011 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
3013 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
3016 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3017 MI.eraseFromParent();
3040 uint64_t
Offset =
MI.getOperand(2).getImm();
3049 unsigned StartIdx =
Offset / 32;
3053 if (DstCount == 1) {
3055 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3063 for (
unsigned I = 0;
I < DstCount; ++
I)
3064 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3065 B.buildMergeLikeInstr(DstReg, MergeVec);
3068 MI.eraseFromParent();
3078 Register InsertSrc =
MI.getOperand(2).getReg();
3079 uint64_t
Offset =
MI.getOperand(3).getImm();
3087 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3091 unsigned DstCount = DstSize / 32;
3092 unsigned InsertCount = InsertSize / 32;
3093 unsigned StartIdx =
Offset / 32;
3095 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3098 for (
unsigned I = 0;
I < StartIdx; ++
I)
3101 if (InsertCount == 1) {
3105 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3108 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3109 for (
unsigned I = 0;
I < InsertCount; ++
I)
3113 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3116 B.buildMergeLikeInstr(DstReg, MergeVec);
3118 MI.eraseFromParent();
3145 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3146 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3147 B.buildIntToPtr(Dst, IntElt);
3149 MI.eraseFromParent();
3156 std::optional<ValueAndVReg> MaybeIdxVal =
3160 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3163 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3164 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3169 MI.eraseFromParent();
3198 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3199 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3200 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3202 B.buildIntToPtr(Dst, IntVecDest);
3203 MI.eraseFromParent();
3210 std::optional<ValueAndVReg> MaybeIdxVal =
3215 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3218 if (IdxVal < NumElts) {
3220 for (
unsigned i = 0; i < NumElts; ++i)
3222 B.buildUnmerge(SrcRegs, Vec);
3224 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3225 B.buildMergeLikeInstr(Dst, SrcRegs);
3230 MI.eraseFromParent();
3241 unsigned Flags =
MI.getFlags();
3245 if (ST.hasTrigReducedRange()) {
3246 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3247 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3248 .addUse(MulVal.getReg(0))
3252 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3255 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3259 MI.eraseFromParent();
3267 unsigned GAFlags)
const {
3300 if (ST.has64BitLiterals()) {
3304 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3308 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3319 B.buildExtract(DstReg, PCReg, 0);
3321 B.buildCopy(DstReg, PCReg);
3331 if (RequiresHighHalf && ST.has64BitLiterals()) {
3334 B.buildInstr(AMDGPU::S_MOV_B64)
3337 B.buildCopy(DstReg, Addr);
3345 B.buildInstr(AMDGPU::S_MOV_B32)
3350 if (RequiresHighHalf) {
3352 "Must provide a 64-bit pointer type!");
3357 B.buildInstr(AMDGPU::S_MOV_B32)
3364 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3365 B.buildCast(DstReg, AddrDst);
3367 B.buildCast(DstReg, AddrLo);
3376 unsigned AS = Ty.getAddressSpace();
3387 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3389 B.buildUndef(DstReg);
3390 MI.eraseFromParent();
3394 B.buildConstant(DstReg,
3396 MI.eraseFromParent();
3402 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3405 Fn,
"local memory global used by non-kernel function",
3414 B.buildUndef(DstReg);
3415 MI.eraseFromParent();
3439 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3440 B.buildIntToPtr(DstReg, Sz);
3441 MI.eraseFromParent();
3447 MI.eraseFromParent();
3451 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3453 MI.eraseFromParent();
3461 MI.eraseFromParent();
3467 MI.eraseFromParent();
3483 if (Ty.getSizeInBits() == 32) {
3485 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3486 B.buildExtract(DstReg,
Load, 0);
3488 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3490 MI.eraseFromParent();
3513 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3515 MI.getOperand(1).setReg(Cast.getReg(0));
3520 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3538 const uint64_t AlignInBits = 8 * MemAlign.
value();
3546 if (WideMemSize == ValSize) {
3552 MI.setMemRefs(MF, {WideMMO});
3558 if (ValSize > WideMemSize)
3565 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3566 B.buildTrunc(ValReg, WideLoad).getReg(0);
3573 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3574 B.buildExtract(ValReg, WideLoad, 0);
3578 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3579 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3583 MI.eraseFromParent();
3596 Register DataReg =
MI.getOperand(0).getReg();
3641 "this should not have been custom lowered");
3646 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3648 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3652 .setMemRefs(
MI.memoperands());
3654 MI.eraseFromParent();
3662 switch (
DefMI->getOpcode()) {
3663 case TargetOpcode::G_INTRINSIC: {
3665 case Intrinsic::amdgcn_frexp_mant:
3666 case Intrinsic::amdgcn_log:
3667 case Intrinsic::amdgcn_log_clamp:
3668 case Intrinsic::amdgcn_exp2:
3669 case Intrinsic::amdgcn_sqrt:
3677 case TargetOpcode::G_FSQRT:
3679 case TargetOpcode::G_FFREXP: {
3680 if (
DefMI->getOperand(0).getReg() == Src)
3684 case TargetOpcode::G_FPEXT: {
3705std::pair<Register, Register>
3707 unsigned Flags)
const {
3711 auto SmallestNormal =
B.buildFConstant(
3713 auto IsLtSmallestNormal =
3716 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3717 auto One =
B.buildFConstant(
F32, 1.0);
3719 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3720 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3722 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3735 LLT Ty =
B.getMRI()->getType(Dst);
3736 unsigned Flags =
MI.getFlags();
3740 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3741 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3742 .addUse(Ext.getReg(0))
3744 B.buildFPTrunc(Dst,
Log2, Flags);
3745 MI.eraseFromParent();
3753 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3756 MI.eraseFromParent();
3760 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3761 .addUse(ScaledInput)
3764 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3765 auto Zero =
B.buildFConstant(Ty, 0.0);
3767 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3768 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3770 MI.eraseFromParent();
3776 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3777 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3782 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3783 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3788 unsigned Flags =
MI.getFlags();
3798 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3800 B.buildFPTrunc(Dst, LogVal, Flags);
3805 MI.eraseFromParent();
3814 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3817 if (ST.hasFastFMAF32()) {
3819 const float c_log10 = 0x1.344134p-2f;
3820 const float cc_log10 = 0x1.09f79ep-26f;
3823 const float c_log = 0x1.62e42ep-1f;
3824 const float cc_log = 0x1.efa39ep-25f;
3826 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3827 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3831 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3832 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3833 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3834 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3835 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3838 const float ch_log10 = 0x1.344000p-2f;
3839 const float ct_log10 = 0x1.3509f6p-18f;
3842 const float ch_log = 0x1.62e000p-1f;
3843 const float ct_log = 0x1.0bfbe8p-15f;
3845 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3846 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3849 auto YInt =
B.buildBitcast(I32,
Y);
3850 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3851 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3852 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3856 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3859 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3861 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3864 const bool IsFiniteOnly =
3867 if (!IsFiniteOnly) {
3870 auto Fabs =
B.buildFAbs(Ty,
Y);
3873 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3877 auto Zero =
B.buildFConstant(Ty, 0.0);
3879 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3880 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3881 B.buildFSub(Dst, R, Shift, Flags);
3883 B.buildCopy(Dst, R);
3886 MI.eraseFromParent();
3892 unsigned Flags)
const {
3893 const double Log2BaseInverted =
3896 LLT Ty =
B.getMRI()->getType(Dst);
3901 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3902 .addUse(ScaledInput)
3904 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3905 auto Zero =
B.buildFConstant(Ty, 0.0);
3907 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3908 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3910 if (ST.hasFastFMAF32())
3911 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3913 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3914 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3921 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3922 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3925 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3926 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3937 unsigned Flags =
MI.getFlags();
3938 LLT Ty =
B.getMRI()->getType(Dst);
3945 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3946 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3947 .addUse(Ext.getReg(0))
3949 B.buildFPTrunc(Dst,
Log2, Flags);
3950 MI.eraseFromParent();
3960 MI.eraseFromParent();
3968 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3970 RangeCheckConst, Flags);
3972 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3973 auto Zero =
B.buildFConstant(Ty, 0.0);
3974 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3975 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3977 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3978 .addUse(AddInput.getReg(0))
3981 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3982 auto One =
B.buildFConstant(Ty, 1.0);
3983 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3984 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3985 MI.eraseFromParent();
3990 const SrcOp &Src,
unsigned Flags) {
3991 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3994 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3995 .addUse(Src.getReg())
3998 return B.buildFExp2(Dst, Src, Flags);
4004 bool IsExp10)
const {
4005 LLT Ty =
B.getMRI()->getType(
X);
4009 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
4010 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4017 LLT Ty =
B.getMRI()->getType(Dst);
4023 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4026 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4027 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4028 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4031 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4033 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4034 .addUse(ExpInput.getReg(0))
4037 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4038 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4039 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4045 unsigned Flags)
const {
4046 LLT Ty =
B.getMRI()->getType(Dst);
4050 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4051 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4053 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4054 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4055 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4056 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4057 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4067 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4071 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4072 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4073 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4075 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4076 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4078 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4079 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4080 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4081 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4083 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4084 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4085 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4087 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4105 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4107 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4109 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4111 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4112 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4113 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4114 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4116 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4117 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4118 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4119 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4121 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4122 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4123 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4124 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4125 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4127 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4128 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4129 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4130 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4133 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4134 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4135 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4137 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4138 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4139 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4140 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4141 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4145 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4146 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4148 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4150 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4152 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4154 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4156 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4157 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4158 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4159 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4161 auto One =
B.buildFConstant(
F64, 1.0);
4162 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4163 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4166 auto DnInt =
B.buildFPTOSI(I32, Dn);
4167 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4174 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4181 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4183 MI.eraseFromParent();
4191 const unsigned Flags =
MI.getFlags();
4199 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4207 MI.eraseFromParent();
4218 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4221 B.buildFPTrunc(Dst, Lowered, Flags);
4222 MI.eraseFromParent();
4233 MI.eraseFromParent();
4261 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4264 if (ST.hasFastFMAF32()) {
4266 const float cc_exp = 0x1.4ae0bep-26f;
4267 const float c_exp10 = 0x1.a934f0p+1f;
4268 const float cc_exp10 = 0x1.2f346ep-24f;
4270 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4271 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4272 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4273 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4275 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4276 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4278 const float ch_exp = 0x1.714000p+0f;
4279 const float cl_exp = 0x1.47652ap-12f;
4281 const float ch_exp10 = 0x1.a92000p+1f;
4282 const float cl_exp10 = 0x1.4f0978p-11f;
4285 auto XInt =
B.buildBitcast(I32,
X);
4286 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4287 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4288 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4290 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4291 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4293 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4294 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4297 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4298 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4301 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4304 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4305 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4307 auto IntE =
B.buildFPTOSI(I32, E);
4309 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4310 .addUse(
A.getReg(0))
4312 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4314 auto UnderflowCheckConst =
4315 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4316 auto Zero =
B.buildFConstant(Ty, 0.0);
4320 R =
B.buildSelect(Ty, Underflow, Zero, R);
4323 auto OverflowCheckConst =
4324 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4329 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4332 B.buildCopy(Dst, R);
4333 MI.eraseFromParent();
4344 unsigned Flags =
MI.getFlags();
4353 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4355 .setMIFlags(CoreFlags);
4356 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4358 .addUse(Log.getReg(0))
4359 .setMIFlags(CoreFlags);
4361 MI.eraseFromParent();
4365 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4366 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4367 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4369 .addUse(Log.getReg(0))
4370 .setMIFlags(CoreFlags);
4375 .signBitIsZeroOrNaN()) {
4376 B.buildFExp2(Dst,
Mul, CoreFlags);
4377 MI.eraseFromParent();
4383 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4385 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4386 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4387 auto YIsOdd =
B.buildAnd(
4391 auto Neg =
B.buildFCopysign(
F32, R,
X);
4393 B.buildSelect(Dst, YIsOdd, Neg, R);
4394 MI.eraseFromParent();
4397 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4404 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4406 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4408 B.buildSelect(Dst, NegNonInt, NaN, R);
4410 MI.eraseFromParent();
4418 ModSrc = SrcFNeg->getOperand(1).getReg();
4420 ModSrc = SrcFAbs->getOperand(1).getReg();
4422 ModSrc = SrcFAbs->getOperand(1).getReg();
4432 Register OrigSrc =
MI.getOperand(1).getReg();
4433 unsigned Flags =
MI.getFlags();
4435 "this should not have been custom lowered");
4445 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4465 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4467 B.buildFMinNum(Min, Fract, Const, Flags);
4472 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4475 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4476 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4478 MI.eraseFromParent();
4496 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4498 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4499 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4502 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4503 B.buildBitcast(Dst,
Merge);
4505 MI.eraseFromParent();
4522 bool UsePartialMad64_32,
4523 bool SeparateOddAlignedProducts)
const {
4538 auto getZero32 = [&]() ->
Register {
4540 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4543 auto getZero64 = [&]() ->
Register {
4545 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4550 for (
unsigned i = 0; i < Src0.size(); ++i) {
4561 if (CarryIn.empty())
4564 bool HaveCarryOut =
true;
4566 if (CarryIn.size() == 1) {
4568 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4572 CarryAccum = getZero32();
4574 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4575 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4577 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4582 LocalAccum = getZero32();
4583 HaveCarryOut =
false;
4588 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4589 LocalAccum =
Add.getReg(0);
4603 auto buildMadChain =
4606 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4607 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4614 if (LocalAccum.size() == 1 &&
4615 (!UsePartialMad64_32 || !CarryIn.empty())) {
4618 unsigned j1 = DstIndex - j0;
4619 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4623 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4625 LocalAccum[0] =
Mul.getReg(0);
4627 if (CarryIn.empty()) {
4628 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4631 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4637 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4641 if (j0 <= DstIndex) {
4642 bool HaveSmallAccum =
false;
4645 if (LocalAccum[0]) {
4646 if (LocalAccum.size() == 1) {
4647 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4648 HaveSmallAccum =
true;
4649 }
else if (LocalAccum[1]) {
4650 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4651 HaveSmallAccum =
false;
4653 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4654 HaveSmallAccum =
true;
4657 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4659 HaveSmallAccum =
true;
4663 unsigned j1 = DstIndex - j0;
4664 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4668 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4669 {Src0[j0], Src1[j1], Tmp});
4670 Tmp = Mad.getReg(0);
4671 if (!HaveSmallAccum)
4672 CarryOut.push_back(Mad.getReg(1));
4673 HaveSmallAccum =
false;
4676 }
while (j0 <= DstIndex);
4678 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4679 LocalAccum[0] = Unmerge.getReg(0);
4680 if (LocalAccum.size() > 1)
4681 LocalAccum[1] = Unmerge.getReg(1);
4688 LocalAccum[0] = getZero32();
4692 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4693 "Uninitialized accumulator part");
4719 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4720 Carry OddCarryIn = std::move(OddCarry);
4721 Carry EvenCarryIn = std::move(EvenCarry);
4726 if (2 * i < Accum.
size()) {
4727 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4728 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4733 if (!SeparateOddAlignedProducts) {
4734 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4735 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4737 bool IsHighest = 2 * i >= Accum.
size();
4740 .take_front(IsHighest ? 1 : 2);
4741 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4747 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4749 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4751 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4754 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4757 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4758 Lo->getOperand(1).getReg());
4759 Accum[2 * i] =
Hi.getReg(0);
4760 SeparateOddCarry =
Hi.getReg(1);
4767 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4768 EvenCarryIn.push_back(CarryOut);
4770 if (2 * i < Accum.
size()) {
4771 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4772 OddCarry.push_back(CarryOut);
4784 assert(ST.hasMad64_32());
4785 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4797 unsigned Size = Ty.getSizeInBits();
4798 if (ST.useVMulU64Inst() &&
Size == 64)
4801 unsigned NumParts =
Size / 32;
4813 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4817 for (
unsigned i = 0; i < NumParts; ++i) {
4821 B.buildUnmerge(Src0Parts, Src0);
4822 B.buildUnmerge(Src1Parts, Src1);
4825 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4826 SeparateOddAlignedProducts);
4828 B.buildMergeLikeInstr(DstReg, AccumRegs);
4829 MI.eraseFromParent();
4844 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4845 ? AMDGPU::G_AMDGPU_FFBH_U32
4846 : AMDGPU::G_AMDGPU_FFBL_B32;
4847 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4850 MI.eraseFromParent();
4860 TypeSize NumBits = SrcTy.getSizeInBits();
4865 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4866 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4867 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4868 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4869 B.buildTrunc(Dst, Ctlz);
4870 MI.eraseFromParent();
4881 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4882 unsigned BitWidth = SrcTy.getSizeInBits();
4884 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4885 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4886 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4887 MI.eraseFromParent();
4893 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4896 return ConstVal == -1;
4903 Register CondDef =
MI.getOperand(0).getReg();
4922 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4931 UncondBrTarget = &*NextMBB;
4933 if (
Next->getOpcode() != AMDGPU::G_BR)
4952 *ArgRC,
B.getDebugLoc(), ArgTy);
4956 const unsigned Mask = Arg->
getMask();
4964 auto ShiftAmt =
B.buildConstant(I32, Shift);
4965 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4968 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4970 B.buildCopy(DstReg, LiveIn);
4980 if (!ST.hasClusters()) {
4983 MI.eraseFromParent();
5003 auto One =
B.buildConstant(I32, 1);
5004 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
5005 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
5006 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
5013 B.buildCopy(DstReg, GlobalIdXYZ);
5014 MI.eraseFromParent();
5018 B.buildCopy(DstReg, ClusterIdXYZ);
5019 MI.eraseFromParent();
5024 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5026 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5027 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5029 .addImm(ClusterIdField);
5030 auto Zero =
B.buildConstant(I32, 0);
5033 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5034 MI.eraseFromParent();
5076 auto LoadConstant = [&](
unsigned N) {
5077 B.buildConstant(DstReg,
N);
5081 if (ST.hasArchitectedSGPRs() &&
5088 Arg = &WorkGroupIDX;
5089 ArgRC = &AMDGPU::SReg_32RegClass;
5093 Arg = &WorkGroupIDY;
5094 ArgRC = &AMDGPU::SReg_32RegClass;
5098 Arg = &WorkGroupIDZ;
5099 ArgRC = &AMDGPU::SReg_32RegClass;
5103 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5104 return LoadConstant(0);
5105 Arg = &ClusterWorkGroupIDX;
5106 ArgRC = &AMDGPU::SReg_32RegClass;
5110 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5111 return LoadConstant(0);
5112 Arg = &ClusterWorkGroupIDY;
5113 ArgRC = &AMDGPU::SReg_32RegClass;
5117 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5118 return LoadConstant(0);
5119 Arg = &ClusterWorkGroupIDZ;
5120 ArgRC = &AMDGPU::SReg_32RegClass;
5125 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5126 Arg = &ClusterWorkGroupMaxIDX;
5127 ArgRC = &AMDGPU::SReg_32RegClass;
5132 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5133 Arg = &ClusterWorkGroupMaxIDY;
5134 ArgRC = &AMDGPU::SReg_32RegClass;
5139 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5140 Arg = &ClusterWorkGroupMaxIDZ;
5141 ArgRC = &AMDGPU::SReg_32RegClass;
5145 Arg = &ClusterWorkGroupMaxFlatID;
5146 ArgRC = &AMDGPU::SReg_32RegClass;
5161 return LoadConstant(0);
5166 B.buildUndef(DstReg);
5170 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5182 MI.eraseFromParent();
5188 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5189 MI.eraseFromParent();
5196 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5210 B.buildUndef(DstReg);
5211 MI.eraseFromParent();
5215 if (Arg->isMasked()) {
5229 MI.eraseFromParent();
5244 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5253 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5261 Align Alignment)
const {
5265 "unexpected kernarg parameter type");
5272 MI.eraseFromParent();
5304 auto FloatY =
B.buildUITOFP(
F32,
Y);
5305 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5307 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5308 auto Z =
B.buildFPTOUI(I32, ScaledY);
5311 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5312 auto NegYZ =
B.buildMul(I32, NegY, Z);
5313 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5316 auto Q =
B.buildUMulH(I32,
X, Z);
5317 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5320 auto One =
B.buildConstant(I32, 1);
5323 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5324 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5329 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5332 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5351 auto Unmerge =
B.buildUnmerge(I32, Val);
5353 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5354 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5356 auto Mad =
B.buildFMAD(
5360 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5361 auto Mul1 =
B.buildFMul(
5365 auto Mul2 =
B.buildFMul(
5367 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5370 auto Mad2 =
B.buildFMAD(
5374 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5375 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5377 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5392 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5394 auto Zero64 =
B.buildConstant(I64, 0);
5395 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5397 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5398 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5400 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5401 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5402 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5404 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5405 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5406 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5408 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5409 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5410 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5411 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5412 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5414 auto Zero32 =
B.buildConstant(I32, 0);
5415 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5416 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5417 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5419 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5420 Register NumerLo = UnmergeNumer.getReg(0);
5421 Register NumerHi = UnmergeNumer.getReg(1);
5423 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5424 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5425 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5426 Register Mul3_Lo = UnmergeMul3.getReg(0);
5427 Register Mul3_Hi = UnmergeMul3.getReg(1);
5428 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5429 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5430 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5431 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5433 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5434 Register DenomLo = UnmergeDenom.getReg(0);
5435 Register DenomHi = UnmergeDenom.getReg(1);
5438 auto C1 =
B.buildSExt(I32, CmpHi);
5441 auto C2 =
B.buildSExt(I32, CmpLo);
5444 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5451 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5452 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5453 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5454 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5456 auto One64 =
B.buildConstant(I64, 1);
5457 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5463 auto C6 =
B.buildSelect(
5467 auto Add4 =
B.buildAdd(I64, Add3, One64);
5468 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5470 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5471 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5472 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5478 auto Sel1 =
B.buildSelect(
5485 auto Sel2 =
B.buildSelect(
5496 switch (
MI.getOpcode()) {
5499 case AMDGPU::G_UDIV: {
5500 DstDivReg =
MI.getOperand(0).getReg();
5503 case AMDGPU::G_UREM: {
5504 DstRemReg =
MI.getOperand(0).getReg();
5507 case AMDGPU::G_UDIVREM: {
5508 DstDivReg =
MI.getOperand(0).getReg();
5509 DstRemReg =
MI.getOperand(1).getReg();
5516 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5517 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5518 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5528 MI.eraseFromParent();
5539 if (Ty != I32 && Ty != I64)
5542 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5543 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5544 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5546 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5547 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5548 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5550 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5551 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5553 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5554 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5556 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5557 switch (
MI.getOpcode()) {
5560 case AMDGPU::G_SDIV: {
5561 DstDivReg =
MI.getOperand(0).getReg();
5565 case AMDGPU::G_SREM: {
5566 DstRemReg =
MI.getOperand(0).getReg();
5570 case AMDGPU::G_SDIVREM: {
5571 DstDivReg =
MI.getOperand(0).getReg();
5572 DstRemReg =
MI.getOperand(1).getReg();
5585 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5586 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5587 B.buildSub(DstDivReg, SignXor, Sign);
5591 auto Sign = LHSign.getReg(0);
5592 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5593 B.buildSub(DstRemReg, SignXor, Sign);
5596 MI.eraseFromParent();
5606 uint16_t Flags =
MI.getFlags();
5612 if (!AllowInaccurateRcp && ResTy !=
F16)
5623 if (CLHS->isOne()) {
5624 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5628 MI.eraseFromParent();
5633 if (CLHS->isMinusOne()) {
5634 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5635 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5636 .addUse(FNeg.getReg(0))
5639 MI.eraseFromParent();
5646 if (!AllowInaccurateRcp &&
5651 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5654 B.buildFMul(Res, LHS, RCP, Flags);
5656 MI.eraseFromParent();
5666 uint16_t Flags =
MI.getFlags();
5671 if (!AllowInaccurateRcp)
5679 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5681 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5682 auto One =
B.buildFConstant(ResTy, 1.0);
5684 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5688 R =
B.buildFNeg(ResTy, R);
5690 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5691 R =
B.buildFMA(ResTy, Tmp0, R, R);
5693 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5694 R =
B.buildFMA(ResTy, Tmp1, R, R);
5697 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5698 B.buildCopy(Res, R);
5699 MI.eraseFromParent();
5703 auto Ret =
B.buildFMul(ResTy,
X, R);
5704 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5706 B.buildFMA(Res, Tmp2, R, Ret);
5707 MI.eraseFromParent();
5721 uint16_t Flags =
MI.getFlags();
5738 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5739 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5740 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5741 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5742 .addUse(RHSExt.getReg(0))
5744 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5746 if (ST.hasMadMacF32Insts()) {
5747 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5748 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5749 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5751 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5752 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5753 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5755 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5756 auto TmpInt =
B.buildBitcast(I32, Tmp);
5757 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5758 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5759 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5760 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5761 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5762 .addUse(RDst.getReg(0))
5767 MI.eraseFromParent();
5780 unsigned SPDenormMode =
5783 if (ST.hasDenormModeInst()) {
5785 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5787 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5788 B.buildInstr(AMDGPU::S_DENORM_MODE)
5789 .addImm(NewDenormModeValue);
5792 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5793 .addImm(SPDenormMode)
5810 uint16_t Flags =
MI.getFlags();
5814 auto One =
B.buildFConstant(
F32, 1.0f);
5816 auto DenominatorScaled =
5817 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5822 auto NumeratorScaled =
5823 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5829 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5830 .addUse(DenominatorScaled.getReg(0))
5832 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5835 const bool HasDynamicDenormals =
5840 if (!PreservesDenormals) {
5841 if (HasDynamicDenormals) {
5843 B.buildInstr(AMDGPU::S_GETREG_B32)
5844 .addDef(SavedSPDenormMode)
5850 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5851 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5852 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5853 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5854 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5855 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5857 if (!PreservesDenormals) {
5858 if (HasDynamicDenormals) {
5859 assert(SavedSPDenormMode);
5860 B.buildInstr(AMDGPU::S_SETREG_B32)
5861 .addReg(SavedSPDenormMode)
5867 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5868 .addUse(Fma4.getReg(0))
5869 .addUse(Fma1.getReg(0))
5870 .addUse(Fma3.getReg(0))
5871 .addUse(NumeratorScaled.getReg(1))
5874 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5875 .addUse(Fmas.getReg(0))
5880 MI.eraseFromParent();
5894 uint16_t Flags =
MI.getFlags();
5898 auto One =
B.buildFConstant(
F64, 1.0);
5900 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5906 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5908 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5909 .addUse(DivScale0.getReg(0))
5912 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5913 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5914 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5916 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5922 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5923 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5924 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5927 if (!ST.hasUsableDivScaleConditionOutput()) {
5934 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5935 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5936 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5937 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5940 Scale1Unmerge.getReg(1));
5942 Scale0Unmerge.getReg(1));
5943 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5945 Scale = DivScale1.getReg(1);
5948 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5949 .addUse(Fma4.getReg(0))
5950 .addUse(Fma3.getReg(0))
5951 .addUse(
Mul.getReg(0))
5955 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5956 .addUse(Fmas.getReg(0))
5961 MI.eraseFromParent();
5971 uint16_t Flags =
MI.getFlags();
5976 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5979 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5983 if (ST.hasFractBug()) {
5984 auto Fabs =
B.buildFAbs(Ty, Val);
5988 auto Zero =
B.buildConstant(InstrExpTy, 0);
5989 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5990 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5993 B.buildCopy(Res0, Mant);
5994 B.buildSExtOrTrunc(Res1, Exp);
5996 MI.eraseFromParent();
6006 uint16_t Flags =
MI.getFlags();
6010 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
6013 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
6014 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
6015 auto C2 =
B.buildFConstant(
F32, 1.0f);
6018 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
6020 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6022 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6023 .addUse(Mul0.getReg(0))
6026 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6028 B.buildFMul(Res, Sel, Mul1, Flags);
6030 MI.eraseFromParent();
6039 unsigned Flags =
MI.getFlags();
6040 assert(!ST.has16BitInsts());
6041 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6042 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6043 .addUse(Ext.getReg(0))
6045 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6046 MI.eraseFromParent();
6056 const unsigned Flags =
MI.getFlags();
6064 MI.eraseFromParent();
6068 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6070 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6071 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6072 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6077 .addUse(SqrtX.getReg(0))
6080 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6081 auto NegOne =
B.buildConstant(I32, -1);
6082 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6084 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6085 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6087 auto PosOne =
B.buildConstant(I32, 1);
6088 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6090 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6091 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6093 auto Zero =
B.buildFConstant(
F32, 0.0f);
6097 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6101 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6104 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6105 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6107 auto Half =
B.buildFConstant(
F32, 0.5f);
6108 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6109 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6110 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6111 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6112 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6113 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6114 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6115 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6118 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6120 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6122 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6125 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6127 MI.eraseFromParent();
6161 unsigned Flags =
MI.getFlags();
6166 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6168 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6172 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6173 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6174 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6177 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6179 auto Half =
B.buildFConstant(
F64, 0.5);
6180 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6181 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6183 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6184 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6186 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6187 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6189 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6190 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6192 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6194 Register SqrtRet = SqrtS2.getReg(0);
6196 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6197 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6198 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6201 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6202 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6203 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6208 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6211 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6217 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6219 MI.eraseFromParent();
6250 auto Flags =
MI.getFlags();
6262 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6272 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6273 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6278 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6280 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6281 MI.eraseFromParent();
6293 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6294 IID == Intrinsic::amdgcn_permlanex16;
6295 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6296 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6297 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6298 IID == Intrinsic::amdgcn_permlane_up ||
6299 IID == Intrinsic::amdgcn_permlane_down ||
6300 IID == Intrinsic::amdgcn_permlane_xor;
6304 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6306 case Intrinsic::amdgcn_readfirstlane:
6307 case Intrinsic::amdgcn_permlane64:
6308 return LaneOp.getReg(0);
6309 case Intrinsic::amdgcn_readlane:
6310 case Intrinsic::amdgcn_set_inactive:
6311 case Intrinsic::amdgcn_set_inactive_chain_arg:
6312 return LaneOp.addUse(Src1).getReg(0);
6313 case Intrinsic::amdgcn_writelane:
6314 case Intrinsic::amdgcn_permlane_bcast:
6315 case Intrinsic::amdgcn_permlane_up:
6316 case Intrinsic::amdgcn_permlane_down:
6317 case Intrinsic::amdgcn_permlane_xor:
6318 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6319 case Intrinsic::amdgcn_permlane16:
6320 case Intrinsic::amdgcn_permlanex16: {
6322 int64_t Src4 =
MI.getOperand(6).getImm();
6323 int64_t Src5 =
MI.getOperand(7).getImm();
6324 return LaneOp.addUse(Src1)
6331 case Intrinsic::amdgcn_mov_dpp8:
6332 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6333 case Intrinsic::amdgcn_update_dpp:
6334 return LaneOp.addUse(Src1)
6335 .addImm(
MI.getOperand(4).getImm())
6336 .addImm(
MI.getOperand(5).getImm())
6337 .addImm(
MI.getOperand(6).getImm())
6338 .addImm(
MI.getOperand(7).getImm())
6348 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6349 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6350 IsPermlaneShuffle) {
6351 Src1 =
MI.getOperand(3).getReg();
6352 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6353 IsPermlaneShuffle) {
6354 Src2 =
MI.getOperand(4).getReg();
6359 unsigned Size = Ty.getSizeInBits();
6361 unsigned SplitSize = 32;
6362 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6363 ST.hasDPALU_DPP() &&
6367 if (
Size == SplitSize) {
6374 bool IsFloat = Ty.getScalarType().isFloat();
6378 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6380 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6382 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6386 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6388 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6389 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6391 if (IID == Intrinsic::amdgcn_writelane)
6392 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6394 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6396 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6398 B.buildTrunc(DstReg, LaneOpDst);
6399 MI.eraseFromParent();
6403 if (
Size % SplitSize != 0)
6407 bool NeedsBitcast =
false;
6408 if (IntTy.isVector()) {
6411 if (EltSize == SplitSize) {
6412 PartialResTy = EltTy;
6413 }
else if (EltSize == 16 || EltSize == 32) {
6414 unsigned NElem = SplitSize / EltSize;
6417 NeedsBitcast =
true;
6422 unsigned NumParts =
Size / SplitSize;
6426 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6427 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6429 if (IID == Intrinsic::amdgcn_writelane)
6430 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6432 for (
unsigned i = 0; i < NumParts; ++i) {
6433 Src0 = Src0Parts.
getReg(i);
6435 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6436 Src1 = Src1Parts.
getReg(i);
6438 if (IID == Intrinsic::amdgcn_writelane)
6439 Src2 = Src2Parts.
getReg(i);
6441 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6444 if (NeedsBitcast || IsFloat)
6447 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6449 B.buildMergeLikeInstr(DstReg, PartialRes);
6451 MI.eraseFromParent();
6459 ST.getTargetLowering()->getImplicitParameterOffset(
6469 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6470 B.buildConstant(IdxTy,
Offset).getReg(0));
6481 Register Pointer =
MI.getOperand(2).getReg();
6483 Register NumRecords =
MI.getOperand(4).getReg();
6489 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6491 auto ExtStride =
B.buildAnyExt(I32, Stride);
6493 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6494 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6496 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6498 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6502 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6503 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6504 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6505 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6509 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6510 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6511 auto ExtShiftedStride =
6512 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6513 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6514 auto ExtShiftedFlags =
6515 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6516 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6518 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6519 B.buildMergeValues(Result, {LowHalf, HighHalf});
6521 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6522 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6523 auto LowHalf = Unmerge.getReg(0);
6524 auto HighHalf = Unmerge.getReg(1);
6526 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6527 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6528 auto ShiftConst =
B.buildConstant(I32, 16);
6529 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6530 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6531 Register NewHighHalfReg = NewHighHalf.getReg(0);
6532 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6535 MI.eraseFromParent();
6552 MI.eraseFromParent();
6559 unsigned AddrSpace)
const {
6561 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6565 ST.hasGloballyAddressableScratch()) {
6567 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6568 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6570 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6572 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6574 B.buildConstant(I32, 1u << 26));
6579 MI.eraseFromParent();
6589std::pair<Register, unsigned>
6601 bool CheckNUW = ST.hasGFX1250Insts();
6603 MRI, OrigOffset,
nullptr, CheckNUW);
6607 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6617 unsigned Overflow = ImmOffset & ~MaxImm;
6618 ImmOffset -= Overflow;
6619 if ((int32_t)Overflow < 0) {
6620 Overflow += ImmOffset;
6624 if (Overflow != 0) {
6626 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6628 auto OverflowVal =
B.buildConstant(I32, Overflow);
6629 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6634 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6636 return std::pair(BaseReg, ImmOffset);
6643 bool ImageStore)
const {
6651 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6653 if (ST.hasUnpackedD16VMem()) {
6654 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6657 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6658 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6666 if (ImageStore && ST.hasImageStoreD16Bug()) {
6669 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6671 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6678 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6679 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6681 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6689 auto Unmerge =
B.buildUnmerge(I32, Reg);
6690 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6692 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6702 Reg =
B.buildPadVectorWithUndefElements(
6711 bool IsFormat)
const {
6721 VData =
B.buildBitcast(Ty, VData).getReg(0);
6723 if (Ty.isFloat(16)) {
6725 VData =
B.buildBitcast(Ty, VData).getReg(0);
6732 if (Ty.isVector()) {
6733 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6745 bool IsFormat)
const {
6752 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6759 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6760 const Function &Fn =
B.getMF().getFunction();
6762 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6763 MI.eraseFromParent();
6775 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6778 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6782 VIndex =
MI.getOperand(3).getReg();
6785 VIndex =
B.buildConstant(I32, 0).getReg(0);
6788 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6789 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6793 Format =
MI.getOperand(5 + OpOffset).getImm();
6797 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6803 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6804 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6805 }
else if (IsFormat) {
6806 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6807 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6811 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6814 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6817 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6822 auto MIB =
B.buildInstr(
Opc)
6833 MIB.addImm(AuxiliaryData)
6834 .addImm(HasVIndex ? -1 : 0)
6835 .addMemOperand(MMO);
6837 MI.eraseFromParent();
6843 unsigned ImmOffset,
unsigned Format,
6846 auto MIB =
B.buildInstr(
Opc)
6857 MIB.addImm(AuxiliaryData)
6858 .addImm(HasVIndex ? -1 : 0)
6859 .addMemOperand(MMO);
6865 Register SOffset,
unsigned ImmOffset,
6866 unsigned Format,
unsigned AuxiliaryData,
6870 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6872 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6875 B.buildUnmerge(Unmerge, LoadDstReg);
6881 bool IsTyped)
const {
6895 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6896 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6898 StatusDst =
MI.getOperand(1).getReg();
6903 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6906 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6909 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6912 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6915 VIndex =
B.buildConstant(I32, 0).getReg(0);
6918 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6919 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6923 Format =
MI.getOperand(5 + OpOffset).getImm();
6927 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6937 Dst =
MI.getOperand(0).getReg();
6938 B.setInsertPt(
B.getMBB(),
MI);
6945 Dst =
MI.getOperand(0).getReg();
6946 B.setInsertPt(
B.getMBB(),
MI);
6950 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6951 const bool Unpacked = ST.hasUnpackedD16VMem();
6953 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6954 const Function &Fn =
B.getMF().getFunction();
6956 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6959 B.buildUndef(StatusDst);
6960 MI.eraseFromParent();
6964 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6965 const Function &Fn =
B.getMF().getFunction();
6967 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6970 B.buildUndef(StatusDst);
6971 MI.eraseFromParent();
6983 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6984 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6985 }
else if (IsFormat) {
6987 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
6988 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6990 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6991 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6996 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6997 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7000 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7001 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7004 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7005 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7010 if (IsTFE && IsD16 && Ty.isVector()) {
7012 const unsigned NumElts = Ty.getNumElements();
7013 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7016 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7019 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7024 R =
B.buildTrunc(EltTy, R).getReg(0);
7025 B.buildMergeLikeInstr(Dst, ValueDWords);
7034 if (PackedTy == Ty) {
7035 B.buildBitcast(Dst, Merged);
7037 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7038 B.buildDeleteTrailingVectorElements(Dst, Packed);
7042 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7050 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7052 B.buildTrunc(DstInt, ExtDst);
7053 }
else if (NumValueDWords == 1) {
7055 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7059 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7062 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7063 IsTyped, HasVIndex,
B);
7064 B.buildMergeLikeInstr(DstInt, ValueDWords);
7067 B.buildBitcast(Dst, DstInt);
7069 (IsD16 && !Ty.isVector())) {
7070 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7072 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7073 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7074 B.buildTrunc(Dst, LoadDstReg);
7075 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7077 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7079 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7080 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7082 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7084 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7085 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7086 B.buildMergeLikeInstr(Dst, Repack);
7089 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7092 MI.eraseFromParent();
7098 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7099 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7100 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7101 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7102 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7103 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7104 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7105 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7106 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7107 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7108 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7109 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7110 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7111 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7112 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7113 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7114 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7115 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7116 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7117 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7118 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7119 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7120 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7121 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7122 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7123 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7124 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7125 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7126 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7127 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7128 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7129 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7130 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7131 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7132 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7133 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7135 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7136 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7137 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7138 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7139 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7140 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7141 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7142 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7143 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7144 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7145 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7146 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7147 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7148 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7150 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7151 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7152 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7153 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7154 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7155 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7156 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7157 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7158 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7159 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7160 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7162 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7163 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7164 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7165 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7166 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7167 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7168 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7169 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7170 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7172 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7173 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7174 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7175 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7176 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7177 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7178 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7179 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7180 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7181 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7182 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7183 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7185 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7186 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7187 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7196 const bool IsCmpSwap =
7197 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7198 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7199 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7200 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7211 CmpVal =
MI.getOperand(3).getReg();
7216 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7217 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7220 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7223 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7229 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7230 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7231 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7250 .addImm(AuxiliaryData)
7251 .addImm(HasVIndex ? -1 : 0)
7252 .addMemOperand(MMO);
7254 MI.eraseFromParent();
7264 bool IsA16,
bool IsG16) {
7278 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7283 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7287 "Bias needs to be converted to 16 bit in A16 mode");
7289 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7293 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7297 if (((
I + 1) >= EndIdx) ||
7304 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7306 B.buildBuildVector(V2EltTy,
7307 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7312 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7323 int DimIdx,
int NumVAddrs) {
7325 for (
int I = 0;
I != NumVAddrs; ++
I) {
7327 if (
SrcOp.isReg()) {
7330 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7331 if (
B.getMRI()->getType(
Reg) != I32)
7332 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7337 int NumAddrRegs = AddrRegs.
size();
7338 if (NumAddrRegs != 1) {
7339 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7342 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7345 for (
int I = 1;
I != NumVAddrs; ++
I) {
7348 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7370 const unsigned NumDefs =
MI.getNumExplicitDefs();
7371 const unsigned ArgOffset = NumDefs + 1;
7372 bool IsTFE = NumDefs == 2;
7390 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7394 const bool IsAtomicPacked16Bit =
7395 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7396 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7403 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7404 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7405 const bool DataTyIs16 =
7406 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7408 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7409 const bool IsA16 = AddrTyIs16;
7410 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7413 if (!BaseOpcode->
Atomic) {
7414 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7417 }
else if (DMask != 0) {
7419 }
else if (!IsTFE && !BaseOpcode->
Store) {
7421 B.buildUndef(
MI.getOperand(0));
7422 MI.eraseFromParent();
7430 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7431 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7432 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7433 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7434 unsigned NewOpcode = LoadOpcode;
7435 if (BaseOpcode->
Store)
7436 NewOpcode = StoreOpcode;
7438 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7441 MI.setDesc(
B.getTII().get(NewOpcode));
7445 if (IsTFE && DMask == 0) {
7448 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7451 if (BaseOpcode->
Atomic) {
7456 if (Ty.isVector() && !IsAtomicPacked16Bit)
7463 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7464 MI.getOperand(2).setReg(
Concat.getReg(0));
7465 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7469 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7472 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7478 if (IsA16 && !ST.hasA16()) {
7483 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7484 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7486 if (IsA16 || IsG16) {
7494 const bool UseNSA = ST.hasNSAEncoding() &&
7495 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7496 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7497 const bool UsePartialNSA =
7498 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7500 if (UsePartialNSA) {
7504 auto Concat =
B.buildConcatVectors(
7505 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7506 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7507 PackedRegs.
resize(NSAMaxSize);
7508 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7510 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7511 PackedRegs[0] =
Concat.getReg(0);
7515 const unsigned NumPacked = PackedRegs.
size();
7518 if (!
SrcOp.isReg()) {
7528 SrcOp.setReg(AMDGPU::NoRegister);
7545 const bool UseNSA = ST.hasNSAEncoding() &&
7546 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7547 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7548 const bool UsePartialNSA =
7549 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7551 if (UsePartialNSA) {
7553 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7555 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7570 if (!Ty.isVector() || !IsD16)
7574 if (RepackedReg != VData) {
7575 MI.getOperand(1).setReg(RepackedReg);
7583 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7586 if (NumElts < DMaskLanes)
7589 if (NumElts > 4 || DMaskLanes > 4)
7600 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7601 const LLT AdjustedTy =
7617 if (IsD16 && ST.hasUnpackedD16VMem()) {
7624 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7625 unsigned RoundedSize = 32 * RoundedElts;
7629 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7634 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7640 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7644 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7645 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7649 MI.getOperand(0).setReg(NewResultReg);
7657 Dst1Reg =
MI.getOperand(1).getReg();
7658 if (MRI->
getType(Dst1Reg) != I32)
7662 MI.removeOperand(1);
7665 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7666 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7667 B.buildBitcast(DstReg, Unmerge.getReg(0));
7668 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7677 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7679 if (ResultNumRegs == 1) {
7681 ResultRegs[0] = NewResultReg;
7684 for (
int I = 0;
I != NumDataRegs; ++
I)
7686 B.buildUnmerge(ResultRegs, NewResultReg);
7691 ResultRegs.
resize(NumDataRegs);
7696 if (IsD16 && !Ty.isVector()) {
7697 B.buildTrunc(DstReg, ResultRegs[0]);
7702 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7703 !ST.hasUnpackedD16VMem()) {
7704 B.buildBitcast(DstReg, ResultRegs[0]);
7716 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7718 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7719 }
else if (ST.hasUnpackedD16VMem()) {
7721 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7725 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7729 for (
int I = 0;
I != NumElts; ++
I)
7736 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7737 B.buildBuildVector(DstReg, ResultRegs);
7741 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7742 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7747 if (Ty == V3I16 || Ty == V3F16) {
7749 if (ResultRegs.
size() == 1) {
7750 NewResultReg = ResultRegs[0];
7751 }
else if (ResultRegs.
size() == 2) {
7753 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7768 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7770 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7772 if (ResizeDst != DstReg)
7773 B.buildBitcast(DstReg, ResizeDst);
7777 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7778 B.buildConcatVectors(DstReg, ResultRegs);
7787 Register OrigDst =
MI.getOperand(0).getReg();
7789 LLT Ty =
B.getMRI()->getType(OrigDst);
7790 unsigned Size = Ty.getSizeInBits();
7792 bool HasMMO = !
MI.memoperands_empty();
7797 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7798 if (
Size % 32 != 0 && !IsSubwordLoad) {
7801 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7802 B.buildUndef(OrigDst);
7803 MI.eraseFromParent();
7808 if (IsSubwordLoad) {
7810 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7811 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7814 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7816 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7825 B.setInsertPt(
B.getMBB(),
MI);
7830 B.setInsertPt(
B.getMBB(),
MI);
7833 MI.setDesc(
B.getTII().get(
Opc));
7834 MI.removeOperand(1);
7840 const unsigned MemSize = (
Size + 7) / 8;
7841 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7848 MI.addMemOperand(MF, MMO);
7850 if (Dst != OrigDst) {
7851 MI.getOperand(0).setReg(Dst);
7852 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7853 B.buildTrunc(OrigDst, Dst);
7875 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7876 MI.removeOperand(0);
7887 if (!ST.hasTrapHandler() ||
7891 return ST.supportsGetDoorbellID() ?
7906 MI.eraseFromParent();
7918 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7927 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7929 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7933 MI.eraseFromParent();
7942 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7949 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7969 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7972 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7973 B.buildCopy(SGPR01, Temp);
7974 B.buildInstr(AMDGPU::S_TRAP)
7977 MI.eraseFromParent();
7988 B.buildCopy(SGPR01, LiveIn);
7989 B.buildInstr(AMDGPU::S_TRAP)
7993 MI.eraseFromParent();
8002 if (ST.hasPrivEnabledTrap2NopBug()) {
8003 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
8005 MI.eraseFromParent();
8009 B.buildInstr(AMDGPU::S_TRAP)
8011 MI.eraseFromParent();
8020 if (!ST.hasTrapHandler() ||
8024 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8027 B.buildInstr(AMDGPU::S_TRAP)
8031 MI.eraseFromParent();
8045 Register NodePtr =
MI.getOperand(2).getReg();
8046 Register RayExtent =
MI.getOperand(3).getReg();
8047 Register RayOrigin =
MI.getOperand(4).getReg();
8049 Register RayInvDir =
MI.getOperand(6).getReg();
8052 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8059 const unsigned NumVDataDwords = 4;
8060 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8061 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8063 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8065 const unsigned BaseOpcodes[2][2] = {
8066 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8067 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8068 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8072 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8073 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8074 : AMDGPU::MIMGEncGfx10NSA,
8075 NumVDataDwords, NumVAddrDwords);
8079 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8080 : AMDGPU::MIMGEncGfx10Default,
8081 NumVDataDwords, NumVAddrDwords);
8086 if (UseNSA && IsGFX11Plus) {
8087 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8088 auto SrcInt =
B.buildBitcast(V3I32, Src);
8089 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8090 auto Merged =
B.buildMergeLikeInstr(
8091 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8092 Ops.push_back(Merged.getReg(0));
8095 Ops.push_back(NodePtr);
8096 Ops.push_back(RayExtent);
8097 packLanes(RayOrigin);
8100 auto UnmergeRayDir =
8101 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8102 auto UnmergeRayInvDir =
8103 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8104 auto MergedDir =
B.buildMergeLikeInstr(
8107 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8108 UnmergeRayDir.getReg(0)}))
8111 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8112 UnmergeRayDir.getReg(1)}))
8115 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8116 UnmergeRayDir.getReg(2)}))
8118 Ops.push_back(MergedDir.getReg(0));
8121 packLanes(RayInvDir);
8125 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8126 Ops.push_back(Unmerge.getReg(0));
8127 Ops.push_back(Unmerge.getReg(1));
8129 Ops.push_back(NodePtr);
8131 Ops.push_back(RayExtent);
8133 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8134 auto SrcInt =
B.buildBitcast(V3I32, Src);
8135 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8136 Ops.push_back(Unmerge.getReg(0));
8137 Ops.push_back(Unmerge.getReg(1));
8138 Ops.push_back(Unmerge.getReg(2));
8141 packLanes(RayOrigin);
8143 auto UnmergeRayDir =
8144 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8145 auto UnmergeRayInvDir =
8146 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8150 B.buildMergeLikeInstr(R1,
8151 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8152 B.buildMergeLikeInstr(
8153 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8154 B.buildMergeLikeInstr(
8155 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8161 packLanes(RayInvDir);
8170 Ops.push_back(MergedOps);
8173 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8182 .addImm(IsA16 ? 1 : 0)
8185 MI.eraseFromParent();
8195 Register DstOrigin =
MI.getOperand(1).getReg();
8197 Register NodePtr =
MI.getOperand(4).getReg();
8198 Register RayExtent =
MI.getOperand(5).getReg();
8199 Register InstanceMask =
MI.getOperand(6).getReg();
8200 Register RayOrigin =
MI.getOperand(7).getReg();
8202 Register Offsets =
MI.getOperand(9).getReg();
8203 Register TDescr =
MI.getOperand(10).getReg();
8206 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8207 const unsigned NumVDataDwords = 10;
8208 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8210 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8211 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8212 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8215 auto RayExtentInstanceMaskVec =
8216 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8217 B.buildAnyExt(I32, InstanceMask)});
8219 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8220 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8226 .addUse(RayExtentInstanceMaskVec.getReg(0))
8233 MI.eraseFromParent();
8242 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8243 MI.eraseFromParent();
8250 if (!ST.hasArchitectedSGPRs())
8254 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8255 auto LSB =
B.buildConstant(I32, 25);
8256 auto Width =
B.buildConstant(I32, 5);
8257 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8258 MI.eraseFromParent();
8266 unsigned Width)
const {
8270 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8271 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8274 B.buildCopy(DstReg, Result);
8275 MI.eraseFromParent();
8295 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8299 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8302 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8303 MI.eraseFromParent();
8316 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8320 .addReg(Unmerge.getReg(0));
8324 .addReg(Unmerge.getReg(1));
8325 MI.eraseFromParent();
8337 case Intrinsic::sponentry:
8343 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8346 B.buildIntToPtr(DstReg, TmpReg);
8347 MI.eraseFromParent();
8349 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8351 B.buildFrameIndex(
MI.getOperand(0), FI);
8352 MI.eraseFromParent();
8355 case Intrinsic::amdgcn_if:
8356 case Intrinsic::amdgcn_else: {
8359 bool Negated =
false;
8376 std::swap(CondBrTarget, UncondBrTarget);
8378 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8379 B.buildCopy(NewUse,
Use);
8380 if (IntrID == Intrinsic::amdgcn_if) {
8381 B.buildInstr(AMDGPU::SI_IF)
8384 .addMBB(UncondBrTarget)
8387 B.buildInstr(AMDGPU::SI_ELSE)
8390 .addMBB(UncondBrTarget)
8400 B.buildBr(*CondBrTarget);
8403 MI.eraseFromParent();
8404 BrCond->eraseFromParent();
8415 case Intrinsic::amdgcn_loop: {
8418 bool Negated =
false;
8427 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8430 std::swap(CondBrTarget, UncondBrTarget);
8432 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8433 B.buildCopy(NewReg, Reg);
8434 B.buildInstr(AMDGPU::SI_LOOP)
8436 .addMBB(UncondBrTarget)
8442 B.buildBr(*CondBrTarget);
8444 MI.eraseFromParent();
8445 BrCond->eraseFromParent();
8451 case Intrinsic::amdgcn_wave_reduce_min:
8452 case Intrinsic::amdgcn_wave_reduce_umin:
8453 case Intrinsic::amdgcn_wave_reduce_fmin:
8454 case Intrinsic::amdgcn_wave_reduce_max:
8455 case Intrinsic::amdgcn_wave_reduce_umax:
8456 case Intrinsic::amdgcn_wave_reduce_fmax:
8457 case Intrinsic::amdgcn_wave_reduce_add:
8458 case Intrinsic::amdgcn_wave_reduce_fadd:
8459 case Intrinsic::amdgcn_wave_reduce_sub:
8460 case Intrinsic::amdgcn_wave_reduce_fsub:
8461 case Intrinsic::amdgcn_wave_reduce_and:
8462 case Intrinsic::amdgcn_wave_reduce_or:
8463 case Intrinsic::amdgcn_wave_reduce_xor: {
8468 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8469 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8470 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8471 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8472 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8473 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8474 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8475 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8476 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8483 .addUse(Ext.getReg(0))
8484 .addImm(
MI.getOperand(3).getImm());
8486 B.buildFPTrunc(DstReg, NewDst);
8488 B.buildTrunc(DstReg, NewDst);
8489 MI.eraseFromParent();
8492 case Intrinsic::amdgcn_make_buffer_rsrc:
8494 case Intrinsic::amdgcn_kernarg_segment_ptr:
8497 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8498 MI.eraseFromParent();
8504 case Intrinsic::amdgcn_implicitarg_ptr:
8506 case Intrinsic::amdgcn_workitem_id_x:
8509 case Intrinsic::amdgcn_workitem_id_y:
8512 case Intrinsic::amdgcn_workitem_id_z:
8515 case Intrinsic::amdgcn_workgroup_id_x:
8520 case Intrinsic::amdgcn_workgroup_id_y:
8525 case Intrinsic::amdgcn_workgroup_id_z:
8530 case Intrinsic::amdgcn_cluster_id_x:
8531 return ST.hasClusters() &&
8534 case Intrinsic::amdgcn_cluster_id_y:
8535 return ST.hasClusters() &&
8538 case Intrinsic::amdgcn_cluster_id_z:
8539 return ST.hasClusters() &&
8542 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8543 return ST.hasClusters() &&
8546 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8547 return ST.hasClusters() &&
8550 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8551 return ST.hasClusters() &&
8554 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8555 return ST.hasClusters() &&
8557 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8558 return ST.hasClusters() &&
8561 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8562 return ST.hasClusters() &&
8565 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8566 return ST.hasClusters() &&
8569 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8570 return ST.hasClusters() &&
8574 case Intrinsic::amdgcn_wave_id:
8576 case Intrinsic::amdgcn_lds_kernel_id:
8579 case Intrinsic::amdgcn_dispatch_ptr:
8582 case Intrinsic::amdgcn_queue_ptr:
8585 case Intrinsic::amdgcn_implicit_buffer_ptr:
8588 case Intrinsic::amdgcn_dispatch_id:
8591 case Intrinsic::r600_read_ngroups_x:
8595 case Intrinsic::r600_read_ngroups_y:
8598 case Intrinsic::r600_read_ngroups_z:
8601 case Intrinsic::r600_read_local_size_x:
8604 case Intrinsic::r600_read_local_size_y:
8608 case Intrinsic::r600_read_local_size_z:
8611 case Intrinsic::amdgcn_fdiv_fast:
8613 case Intrinsic::amdgcn_is_shared:
8615 case Intrinsic::amdgcn_is_private:
8617 case Intrinsic::amdgcn_wavefrontsize: {
8618 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8619 MI.eraseFromParent();
8622 case Intrinsic::amdgcn_s_buffer_load:
8623 case Intrinsic::amdgcn_ptr_s_buffer_load:
8625 case Intrinsic::amdgcn_raw_buffer_store:
8626 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8627 case Intrinsic::amdgcn_struct_buffer_store:
8628 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8630 case Intrinsic::amdgcn_raw_buffer_store_format:
8631 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8632 case Intrinsic::amdgcn_struct_buffer_store_format:
8633 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8635 case Intrinsic::amdgcn_raw_tbuffer_store:
8636 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8637 case Intrinsic::amdgcn_struct_tbuffer_store:
8638 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8640 case Intrinsic::amdgcn_raw_buffer_load:
8641 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8642 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8643 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8644 case Intrinsic::amdgcn_struct_buffer_load:
8645 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8646 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8647 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8649 case Intrinsic::amdgcn_raw_buffer_load_format:
8650 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8651 case Intrinsic::amdgcn_struct_buffer_load_format:
8652 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8654 case Intrinsic::amdgcn_raw_tbuffer_load:
8655 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8656 case Intrinsic::amdgcn_struct_tbuffer_load:
8657 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8659 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8660 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8661 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8662 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8663 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8664 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8665 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8666 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8667 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8668 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8669 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8670 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8671 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8672 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8673 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8674 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8675 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8676 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8677 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8678 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8679 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8680 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8681 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8682 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8683 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8684 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8685 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8686 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8687 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8688 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8689 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8690 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8691 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8692 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8693 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8694 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8695 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8696 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8697 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8698 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8699 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8700 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8701 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8702 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8703 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8704 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8705 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8706 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8707 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8708 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8709 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8710 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8711 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8712 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8713 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8714 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8715 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8716 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8717 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8718 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8719 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8720 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8721 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8722 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8723 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8724 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8725 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8726 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8727 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8728 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8729 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8730 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8732 case Intrinsic::amdgcn_rsq_clamp:
8734 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8736 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8737 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8739 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8740 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8741 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8742 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8743 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8744 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8745 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8746 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8750 if (IndexArgTy != I64) {
8751 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8752 :
B.buildAnyExt(I64, Index);
8753 MI.getOperand(5).setReg(NewIndex.getReg(0));
8757 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8758 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8759 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8760 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8761 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8762 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8763 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8764 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8767 if (MRI.
getType(Index) != I32)
8768 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8771 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8772 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8773 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8774 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8775 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8776 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8777 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8778 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8779 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8781 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8785 if (IndexArgTy != IdxTy) {
8786 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8787 :
B.buildAnyExt(IdxTy, Index);
8788 MI.getOperand(7).setReg(NewIndex.getReg(0));
8793 case Intrinsic::amdgcn_fmed3: {
8799 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8800 MI.removeOperand(1);
8804 case Intrinsic::amdgcn_readlane:
8805 case Intrinsic::amdgcn_writelane:
8806 case Intrinsic::amdgcn_readfirstlane:
8807 case Intrinsic::amdgcn_permlane16:
8808 case Intrinsic::amdgcn_permlanex16:
8809 case Intrinsic::amdgcn_permlane64:
8810 case Intrinsic::amdgcn_set_inactive:
8811 case Intrinsic::amdgcn_set_inactive_chain_arg:
8812 case Intrinsic::amdgcn_mov_dpp8:
8813 case Intrinsic::amdgcn_update_dpp:
8814 case Intrinsic::amdgcn_permlane_bcast:
8815 case Intrinsic::amdgcn_permlane_up:
8816 case Intrinsic::amdgcn_permlane_down:
8817 case Intrinsic::amdgcn_permlane_xor:
8819 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8821 case Intrinsic::amdgcn_dead: {
8825 MI.eraseFromParent();
8828 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8829 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8830 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8831 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8832 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8833 MI.eraseFromParent();
8835 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8836 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8837 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8838 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8839 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8840 MI.eraseFromParent();
8842 case Intrinsic::amdgcn_av_load_b128:
8843 case Intrinsic::amdgcn_av_store_b128: {
8844 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8845 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8846 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8848 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8849 **
MI.memoperands_begin());
8850 MI.eraseFromParent();
8853 case Intrinsic::amdgcn_flat_load_monitor_b32:
8854 case Intrinsic::amdgcn_flat_load_monitor_b64:
8855 case Intrinsic::amdgcn_flat_load_monitor_b128:
8856 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8857 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8858 .add(
MI.getOperand(0))
8859 .add(
MI.getOperand(2))
8860 .addMemOperand(*
MI.memoperands_begin());
8861 MI.eraseFromParent();
8863 case Intrinsic::amdgcn_global_load_monitor_b32:
8864 case Intrinsic::amdgcn_global_load_monitor_b64:
8865 case Intrinsic::amdgcn_global_load_monitor_b128:
8866 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8867 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8868 .add(
MI.getOperand(0))
8869 .add(
MI.getOperand(2))
8870 .addMemOperand(*
MI.memoperands_begin());
8871 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static void buildTFEBufferLoad(unsigned Opc, ArrayRef< Register > ValueDsts, Register StatusDst, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
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 scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
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 legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
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.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
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 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 push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.