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);
699 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
712 const LLT BufferStridedPtr =
715 const LLT CodePtr = FlatPtr;
717 const std::initializer_list<LLT> AddrSpaces64 = {
718 GlobalPtr, ConstantPtr, FlatPtr
721 const std::initializer_list<LLT> AddrSpaces32 = {
722 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
725 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
727 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
728 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
729 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
758 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
760 if (ST.hasAnyPackedU64Ops()) {
763 .clampMaxNumElementsStrict(0,
S16, 2)
769 }
else if (ST.hasScalarAddSub64()) {
772 .clampMaxNumElementsStrict(0,
S16, 2)
780 .clampMaxNumElementsStrict(0,
S16, 2)
787 if (ST.hasScalarSMulU64()) {
790 .clampMaxNumElementsStrict(0,
S16, 2)
798 .clampMaxNumElementsStrict(0,
S16, 2)
808 .minScalarOrElt(0,
S16)
813 }
else if (ST.has16BitInsts()) {
847 .widenScalarToNextMultipleOf(0, 32)
857 if (ST.hasMad64_32())
862 if (ST.hasIntClamp()) {
885 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
895 if (ST.hasVOP3PInsts()) {
897 .clampMaxNumElements(0,
S8, 2)
918 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
934 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
975 auto &FCanonicalizeActions =
977 auto &StrictFPOpActions =
984 if (ST.has16BitInsts()) {
985 if (ST.hasVOP3PInsts()) {
987 FCanonicalizeActions.legalFor({
F16,
V2F16});
988 StrictFPOpActions.legalFor({
F16,
V2F16});
990 FPOpActions.legalFor({
F16});
991 FCanonicalizeActions.legalFor({
F16});
992 StrictFPOpActions.legalFor({
F16});
995 TrigActions.customFor({
F16});
996 FDIVActions.customFor({
F16});
999 if (ST.hasBF16PackedInsts()) {
1000 FPOpActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1001 FCanonicalizeActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16,
1003 StrictFPOpActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1009 if (ST.hasAnyPackedFP32Ops()) {
1010 FPOpActions.legalFor({
V2F32});
1011 FCanonicalizeActions.legalFor({
V2F32});
1012 StrictFPOpActions.legalFor({
V2F32});
1013 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1014 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1015 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1018 if (ST.hasAnyPackedFP64Ops()) {
1019 FPOpActions.legalFor({
V2F64});
1020 FCanonicalizeActions.legalFor({
V2F64});
1021 StrictFPOpActions.legalFor({
V2F64});
1022 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1023 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1024 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1027 auto &MinNumMaxNumIeee =
1030 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1035 if (ST.has16BitInsts()) {
1036 MinNumMaxNumIeee.legalFor({
F16});
1037 MinNumMaxNum.customFor({
F16});
1041 if (ST.hasVOP3PInsts()) {
1042 MinNumMaxNumIeee.legalFor({
V2F16})
1045 .clampMaxNumElements(0,
F16, 2);
1046 MinNumMaxNum.customFor({
V2F16})
1049 .clampMaxNumElements(0,
F16, 2);
1053 if (ST.hasAnyPackedFP64Ops()) {
1054 MinNumMaxNum.customFor({
V2F64})
1057 .clampMaxNumElements(0,
F64, 2);
1061 if (ST.hasBF16PackedInsts()) {
1062 MinNumMaxNumIeee.legalFor({
V2BF16})
1065 .clampMaxNumElements(0,
BF16, 2);
1066 MinNumMaxNum.customFor({
V2BF16})
1069 .clampMaxNumElements(0,
BF16, 2);
1075 if (!ST.has16BitInsts()) {
1076 MinNumMaxNumIeee.minScalar(0,
F32);
1077 MinNumMaxNum.minScalar(0,
F32);
1080 if (ST.hasVOP3PInsts()) {
1081 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1082 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1083 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1091 if (!ST.has16BitInsts()) {
1102 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1105 if (ST.hasAnyPackedFP32Ops())
1109 if (ST.has16BitInsts()) {
1112 .legalFor(ST.hasBF16TransInsts(), {BF16})
1122 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1144 if (ST.hasFractBug()) {
1158 .legalFor({{
F32, I32}, {
F64, I32}})
1178 if (ST.hasCvtPkF16F32Inst()) {
1180 .clampMaxNumElements(0,
F16, 2);
1193 if (ST.has16BitInsts()) {
1207 if (ST.hasBF16PackedInsts()) {
1208 FSubActions.lowerFor({
V2BF16}).clampMaxNumElements(0,
BF16, 2);
1211 if (ST.hasAnyPackedFP32Ops())
1219 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1220 FMad.customFor({
F32,
F16});
1221 else if (ST.hasMadMacF32Insts())
1222 FMad.customFor({
F32});
1223 else if (ST.hasMadF16())
1224 FMad.customFor({
F16});
1229 if (ST.has16BitInsts()) {
1232 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1240 .clampMaxNumElements(0,
S16, 2)
1256 .legalFor({{
F32, I32}, {
F64, I32}})
1260 if (ST.has16BitInsts())
1268 .legalFor({{I32,
F32}, {I32,
F64}})
1269 .customFor({{I64,
F32}, {I64,
F64}})
1272 if (ST.has16BitInsts())
1281 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1282 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1283 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1287 if (
ST.has16BitInsts())
1290 if (
ST.hasVCvtPkIU16F32())
1300 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1301 .clampScalar(0, I16, I64)
1305 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1311 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1315 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1316 .clampScalar(0, I16, I64)
1320 auto &RoundingActions = getActionDefinitionsBuilder(
1321 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1322 if (
ST.has16BitInsts())
1330 if (!
ST.has16BitInsts())
1333 getActionDefinitionsBuilder(G_PTR_ADD)
1339 getActionDefinitionsBuilder(G_PTRMASK)
1341 .scalarSameSizeAs(1, 0)
1345 getActionDefinitionsBuilder(G_ICMP)
1357 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1358 .legalForCartesianProduct(
1359 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1360 if (
ST.has16BitInsts()) {
1361 CmpBuilder.legalFor({{
S1,
S16}});
1370 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1373 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1374 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1376 if (
ST.hasSALUFloatInsts())
1377 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1379 FCmpBuilder.widenScalarToNextPow2(1).minScalar(1,
F32).scalarize(0);
1381 getActionDefinitionsBuilder(G_FPOW)
1383 .clampScalar(0,
F32,
F32)
1386 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1388 getActionDefinitionsBuilder(G_FLOG2)
1389 .legalFor(
ST.has16BitInsts(), {F16})
1390 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1396 getActionDefinitionsBuilder(G_FEXP2)
1397 .legalFor(
ST.has16BitInsts(), {F16})
1398 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1404 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1408 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1413 getActionDefinitionsBuilder(G_CTPOP)
1415 .clampScalar(0,
S32,
S32)
1416 .widenScalarToNextPow2(1, 32)
1417 .clampScalar(1,
S32,
S64)
1419 .widenScalarToNextPow2(0, 32);
1422 if (
ST.has16BitInsts())
1423 getActionDefinitionsBuilder(G_IS_FPCLASS)
1424 .legalForCartesianProduct({
I1}, FPTypes16)
1425 .widenScalarToNextPow2(1)
1429 getActionDefinitionsBuilder(G_IS_FPCLASS)
1430 .legalForCartesianProduct({
I1}, FPTypesBase)
1431 .lowerFor({
I1,
F16})
1432 .widenScalarToNextPow2(1)
1439 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1441 .clampScalar(0,
S32,
S32)
1442 .clampScalar(1,
S32,
S64)
1443 .widenScalarToNextPow2(0, 32)
1444 .widenScalarToNextPow2(1, 32)
1448 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1451 .clampScalar(0,
S32,
S32)
1452 .clampScalar(1,
S32,
S64)
1454 .widenScalarToNextPow2(0, 32)
1455 .widenScalarToNextPow2(1, 32);
1457 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1459 .clampScalar(0,
S32,
S32)
1460 .clampScalar(1,
S32,
S64)
1462 .widenScalarToNextPow2(0, 32)
1463 .widenScalarToNextPow2(1, 32);
1465 getActionDefinitionsBuilder(G_CTLS)
1468 .clampScalar(0,
S32,
S32)
1469 .clampScalar(1,
S32,
S32);
1473 getActionDefinitionsBuilder(G_BITREVERSE)
1475 .clampScalar(0,
S32,
S64)
1477 .widenScalarToNextPow2(0);
1479 if (
ST.has16BitInsts()) {
1480 getActionDefinitionsBuilder(G_BSWAP)
1482 .clampMaxNumElementsStrict(0,
S16, 2)
1485 .widenScalarToNextPow2(0)
1486 .clampScalar(0,
S16,
S32)
1489 if (
ST.hasVOP3PInsts()) {
1490 getActionDefinitionsBuilder(G_ABS)
1492 .clampMaxNumElements(0,
S16, 2)
1494 .widenScalarToNextPow2(0)
1497 if (
ST.useMinMaxI64Insts()) {
1498 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1500 .clampMaxNumElements(0,
S16, 2)
1502 .widenScalarToNextPow2(0)
1506 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1508 .clampMaxNumElements(0,
S16, 2)
1510 .widenScalarToNextPow2(0)
1515 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1517 .widenScalarToNextPow2(0)
1524 getActionDefinitionsBuilder(G_BSWAP)
1529 .widenScalarToNextPow2(0)
1534 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1537 .widenScalarToNextPow2(0)
1542 getActionDefinitionsBuilder(G_INTTOPTR)
1544 .legalForCartesianProduct(AddrSpaces64, {
S64})
1545 .legalForCartesianProduct(AddrSpaces32, {
S32})
1558 getActionDefinitionsBuilder(G_PTRTOINT)
1560 .legalForCartesianProduct(AddrSpaces64, {
S64})
1561 .legalForCartesianProduct(AddrSpaces32, {
S32})
1574 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1578 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1579 bool IsLoad) ->
bool {
1583 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1597 unsigned NumRegs = (MemSize + 31) / 32;
1599 if (!
ST.hasDwordx3LoadStores())
1610 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1611 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1612 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1618 for (
unsigned Op : {G_LOAD, G_STORE}) {
1619 const bool IsStore =
Op == G_STORE;
1621 auto &Actions = getActionDefinitionsBuilder(
Op);
1624 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1627 {
S64, GlobalPtr,
S64, GlobalAlign32},
1630 {
S32, GlobalPtr,
S8, GlobalAlign8},
1631 {
S32, GlobalPtr,
S16, GlobalAlign16},
1633 {
S32, LocalPtr,
S32, 32},
1634 {
S64, LocalPtr,
S64, 32},
1636 {
S32, LocalPtr,
S8, 8},
1637 {
S32, LocalPtr,
S16, 16},
1640 {
S32, PrivatePtr,
S32, 32},
1641 {
S32, PrivatePtr,
S8, 8},
1642 {
S32, PrivatePtr,
S16, 16},
1645 {
S32, ConstantPtr,
S32, GlobalAlign32},
1648 {
S64, ConstantPtr,
S64, GlobalAlign32},
1649 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1651 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1652 {{S16, GlobalPtr, S8, GlobalAlign8},
1653 {S16, GlobalPtr, S16, GlobalAlign16},
1654 {S16, LocalPtr, S8, 8},
1655 {S16, LocalPtr, S16, 16},
1656 {S16, PrivatePtr, S8, 8},
1657 {S16, PrivatePtr, S16, 16}});
1667 Actions.unsupportedIf(
1668 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1682 Actions.customIf(
typeIs(1, Constant32Ptr));
1708 return !Query.
Types[0].isVector() &&
1709 needToSplitMemOp(Query,
Op == G_LOAD);
1711 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1716 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1719 if (DstSize > MemSize)
1725 if (MemSize > MaxSize)
1733 return Query.
Types[0].isVector() &&
1734 needToSplitMemOp(Query,
Op == G_LOAD);
1736 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1750 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1751 if (MemSize > MaxSize) {
1755 if (MaxSize % EltSize == 0) {
1761 unsigned NumPieces = MemSize / MaxSize;
1765 if (NumPieces == 1 || NumPieces >= NumElts ||
1766 NumElts % NumPieces != 0)
1767 return std::pair(0, EltTy);
1775 return std::pair(0, EltTy);
1790 return std::pair(0, EltTy);
1795 .widenScalarToNextPow2(0)
1802 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1803 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1804 {
S32, GlobalPtr,
S16, 2 * 8},
1805 {
S32, LocalPtr,
S8, 8},
1806 {
S32, LocalPtr,
S16, 16},
1807 {
S32, PrivatePtr,
S8, 8},
1808 {
S32, PrivatePtr,
S16, 16},
1809 {
S32, ConstantPtr,
S8, 8},
1810 {
S32, ConstantPtr,
S16, 2 * 8}})
1811 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1812 {{S16, GlobalPtr, S8, GlobalAlign8},
1813 {S16, LocalPtr, S8, GlobalAlign8},
1814 {S16, PrivatePtr, S8, GlobalAlign8},
1815 {S16, ConstantPtr, S8, GlobalAlign8}})
1820 if (
ST.hasFlatAddressSpace()) {
1821 ExtLoads.legalForTypesWithMemDesc(
1822 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1824 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1825 {{S16, FlatPtr, S8, GlobalAlign8}});
1833 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1835 ExtLoads.narrowScalarIf(
1842 ExtLoads.clampScalar(0,
S32,
S32)
1843 .widenScalarToNextPow2(0)
1846 auto &Atomics = getActionDefinitionsBuilder(
1847 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1848 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1849 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1850 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1851 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1852 {
S64, GlobalPtr}, {
S64, LocalPtr},
1853 {
S32, RegionPtr}, {
S64, RegionPtr}});
1854 if (
ST.hasFlatAddressSpace()) {
1855 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1859 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1860 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1861 if (
ST.hasFlatAddressSpace()) {
1862 Atomics32.legalFor({{
S32, FlatPtr}});
1866 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1867 if (
ST.hasLDSFPAtomicAddF32()) {
1869 if (
ST.hasLdsAtomicAddF64())
1871 if (
ST.hasAtomicDsPkAdd16Insts())
1874 if (
ST.hasAtomicFaddInsts())
1876 if (
ST.hasFlatAtomicFaddF32Inst())
1879 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1883 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1886 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1887 ST.hasAtomicBufferGlobalPkAddF16Insts())
1889 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1891 if (
ST.hasAtomicFlatPkAdd16Insts())
1897 auto &AtomicFMinFMax =
1898 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1899 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1901 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1902 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1903 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1904 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1905 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1906 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1907 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1908 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1912 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1913 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1914 {
S32, FlatPtr}, {
S64, FlatPtr}})
1915 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1916 {
S32, RegionPtr}, {
S64, RegionPtr}});
1920 getActionDefinitionsBuilder(G_SELECT)
1922 LocalPtr, FlatPtr, PrivatePtr,
1926 .clampScalar(0,
S16,
S64)
1930 .clampMaxNumElements(0,
S32, 2)
1931 .clampMaxNumElements(0, LocalPtr, 2)
1932 .clampMaxNumElements(0, PrivatePtr, 2)
1934 .widenScalarToNextPow2(0)
1939 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1941 if (
ST.has16BitInsts()) {
1942 if (
ST.hasVOP3PInsts()) {
1944 .clampMaxNumElements(0,
S16, 2);
1946 Shifts.legalFor({{
S16,
S16}});
1949 Shifts.widenScalarIf(
1954 const LLT AmountTy = Query.
Types[1];
1960 Shifts.clampScalar(1,
S32,
S32);
1961 Shifts.widenScalarToNextPow2(0, 16);
1962 Shifts.clampScalar(0,
S16,
S64);
1964 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1972 Shifts.clampScalar(1,
S32,
S32);
1973 Shifts.widenScalarToNextPow2(0, 32);
1974 Shifts.clampScalar(0,
S32,
S64);
1976 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1981 Shifts.scalarize(0);
1983 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1984 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1985 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1986 unsigned IdxTypeIdx = 2;
1988 getActionDefinitionsBuilder(
Op)
1990 const LLT EltTy = Query.
Types[EltTypeIdx];
1991 const LLT VecTy = Query.
Types[VecTypeIdx];
1992 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1994 const bool isLegalVecType =
2004 return (EltSize == 32 || EltSize == 64) &&
2020 const LLT EltTy = Query.
Types[EltTypeIdx];
2021 const LLT VecTy = Query.
Types[VecTypeIdx];
2025 const unsigned TargetEltSize =
2026 DstEltSize % 64 == 0 ? 64 : 32;
2027 return std::pair(VecTypeIdx,
2031 .clampScalar(EltTypeIdx,
S32,
S64)
2032 .clampScalar(VecTypeIdx,
S32,
S64)
2033 .clampScalar(IdxTypeIdx,
S32,
S32)
2034 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2043 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2045 const LLT &EltTy = Query.
Types[1].getElementType();
2046 return Query.
Types[0] != EltTy;
2049 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2050 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2051 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2052 getActionDefinitionsBuilder(
Op)
2055 const LLT BigTy = Query.
Types[BigTyIdx];
2061 const LLT LitTy = Query.
Types[LitTyIdx];
2066 .widenScalarToNextPow2(BigTyIdx, 32)
2074 const LLT BigTy = Query.
Types[BigTyIdx];
2075 const LLT LitTy = Query.
Types[LitTyIdx];
2083 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2093 if (
ST.hasScalarPackInsts()) {
2096 .minScalarOrElt(0,
S16)
2099 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2103 BuildVector.customFor({
V2S16,
S16});
2104 BuildVector.minScalarOrElt(0,
S32);
2106 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2114 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2116 .clampMaxNumElements(0,
S32, 32)
2117 .clampMaxNumElements(1,
S16, 2)
2118 .clampMaxNumElements(0,
S16, 64);
2120 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2123 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2124 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2125 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2127 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2128 const LLT Ty = Query.
Types[TypeIdx];
2140 getActionDefinitionsBuilder(
Op)
2144 const LLT BigTy = Query.
Types[BigTyIdx];
2150 .widenScalarToNextPow2(LitTyIdx, 16)
2159 .clampScalar(LitTyIdx,
S32,
S512)
2160 .widenScalarToNextPow2(LitTyIdx, 32)
2164 return notValidElt(Query, LitTyIdx);
2169 return notValidElt(Query, BigTyIdx);
2174 if (
Op == G_MERGE_VALUES) {
2175 Builder.widenScalarIf(
2178 const LLT Ty = Query.
Types[LitTyIdx];
2184 Builder.widenScalarIf(
2186 const LLT Ty = Query.
Types[BigTyIdx];
2192 const LLT &Ty = Query.
Types[BigTyIdx];
2194 if (NewSizeInBits >= 256) {
2196 if (RoundedTo < NewSizeInBits)
2197 NewSizeInBits = RoundedTo;
2199 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2208 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2209 .legalFor({{
S32}, {
S64}})
2210 .clampScalar(0,
S32,
S64);
2212 if (
ST.hasVOP3PInsts()) {
2213 SextInReg.lowerFor({{
V2S16}})
2217 .clampMaxNumElementsStrict(0,
S16, 2);
2218 }
else if (
ST.has16BitInsts()) {
2219 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2223 SextInReg.lowerFor({{
S32}, {
S64}});
2228 .clampScalar(0,
S32,
S64)
2231 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2235 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2236 FSHRActionDefs.legalFor({{
S32,
S32}})
2237 .clampMaxNumElementsStrict(0,
S16, 2);
2238 if (
ST.hasVOP3PInsts())
2240 FSHRActionDefs.scalarize(0).lower();
2242 if (
ST.hasVOP3PInsts()) {
2243 getActionDefinitionsBuilder(G_FSHL)
2245 .clampMaxNumElementsStrict(0,
S16, 2)
2249 getActionDefinitionsBuilder(G_FSHL)
2254 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2257 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2259 getActionDefinitionsBuilder(G_FENCE)
2262 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2267 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2269 .clampScalar(1,
S32,
S32)
2270 .clampScalar(0,
S32,
S64)
2271 .widenScalarToNextPow2(0)
2274 getActionDefinitionsBuilder(
2278 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2279 G_READ_REGISTER, G_WRITE_REGISTER,
2284 if (
ST.hasIEEEMinimumMaximumInsts()) {
2285 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2286 .legalFor(FPTypesPK16)
2287 .clampMaxNumElements(0,
F16, 2)
2289 }
else if (
ST.hasVOP3PInsts()) {
2290 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2292 .clampMaxNumElementsStrict(0,
F16, 2)
2296 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2298 .clampScalar(0,
F32,
F64)
2302 getActionDefinitionsBuilder(
2303 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2306 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2308 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2309 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2310 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2313 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2315 getActionDefinitionsBuilder(
2316 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2317 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2318 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2319 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2324 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2325 G_INTRINSIC_CONVERGENT,
2326 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2338 switch (
MI.getOpcode()) {
2339 case TargetOpcode::G_ADDRSPACE_CAST:
2341 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2343 case TargetOpcode::G_FCEIL:
2345 case TargetOpcode::G_FREM:
2347 case TargetOpcode::G_INTRINSIC_TRUNC:
2349 case TargetOpcode::G_SITOFP:
2351 case TargetOpcode::G_UITOFP:
2353 case TargetOpcode::G_FPTOSI:
2355 case TargetOpcode::G_FPTOUI:
2357 case TargetOpcode::G_FMINNUM:
2358 case TargetOpcode::G_FMAXNUM:
2359 case TargetOpcode::G_FMINIMUMNUM:
2360 case TargetOpcode::G_FMAXIMUMNUM:
2362 case TargetOpcode::G_EXTRACT:
2364 case TargetOpcode::G_INSERT:
2366 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2368 case TargetOpcode::G_INSERT_VECTOR_ELT:
2370 case TargetOpcode::G_FSIN:
2371 case TargetOpcode::G_FCOS:
2373 case TargetOpcode::G_GLOBAL_VALUE:
2375 case TargetOpcode::G_LOAD:
2376 case TargetOpcode::G_SEXTLOAD:
2377 case TargetOpcode::G_ZEXTLOAD:
2379 case TargetOpcode::G_STORE:
2381 case TargetOpcode::G_FMAD:
2383 case TargetOpcode::G_FDIV:
2385 case TargetOpcode::G_FFREXP:
2387 case TargetOpcode::G_FSQRT:
2389 case TargetOpcode::G_UDIV:
2390 case TargetOpcode::G_UREM:
2391 case TargetOpcode::G_UDIVREM:
2393 case TargetOpcode::G_SDIV:
2394 case TargetOpcode::G_SREM:
2395 case TargetOpcode::G_SDIVREM:
2397 case TargetOpcode::G_ATOMIC_CMPXCHG:
2399 case TargetOpcode::G_FLOG2:
2401 case TargetOpcode::G_FLOG:
2402 case TargetOpcode::G_FLOG10:
2404 case TargetOpcode::G_FEXP2:
2406 case TargetOpcode::G_FEXP:
2407 case TargetOpcode::G_FEXP10:
2409 case TargetOpcode::G_FPOW:
2411 case TargetOpcode::G_FFLOOR:
2413 case TargetOpcode::G_BUILD_VECTOR:
2414 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2416 case TargetOpcode::G_MUL:
2418 case TargetOpcode::G_CTLZ:
2419 case TargetOpcode::G_CTTZ:
2421 case TargetOpcode::G_CTLS:
2423 case TargetOpcode::G_CTLZ_ZERO_POISON:
2425 case TargetOpcode::G_STACKSAVE:
2427 case TargetOpcode::G_GET_FPENV:
2429 case TargetOpcode::G_SET_FPENV:
2431 case TargetOpcode::G_TRAP:
2433 case TargetOpcode::G_DEBUGTRAP:
2445 unsigned BaseAS = AS;
2450 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2454 auto Tag =
B.buildConstant(
S32, SANum);
2455 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2461Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2471 if (ST.hasApertureRegs()) {
2475 const unsigned ApertureRegNo =
2476 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2477 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2478 !ST.hasGloballyAddressableScratch()) &&
2479 "Cannot use src_private_base with globally addressable scratch!");
2482 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2483 return B.buildUnmerge(I32, Dst).getReg(1);
2498 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2514 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2517 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2531 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2539 B.buildObjectPtrOffset(
2542 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2550 switch (Def->getOpcode()) {
2551 case AMDGPU::G_FRAME_INDEX:
2552 case AMDGPU::G_GLOBAL_VALUE:
2553 case AMDGPU::G_BLOCK_ADDR:
2555 case AMDGPU::G_CONSTANT: {
2556 const ConstantInt *CI = Def->getOperand(1).getCImm();
2571 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2580 unsigned SrcAS = SrcTy.getAddressSpace();
2594 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2601 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2603 ST.hasGloballyAddressableScratch()) {
2606 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2608 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2609 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2611 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2612 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2613 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2616 return B.buildExtract(Dst, Src, 0).getReg(0);
2620 castFlatToLocalOrPrivate(Dst);
2621 MI.eraseFromParent();
2627 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2628 auto FlatNull =
B.buildConstant(SrcTy, 0);
2631 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2635 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2637 MI.eraseFromParent();
2644 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2647 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2650 ST.hasGloballyAddressableScratch()) {
2654 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2655 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2659 if (ST.isWave64()) {
2660 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2666 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2667 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2669 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2673 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2674 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2676 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2677 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2686 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2690 castLocalOrPrivateToFlat(Dst);
2691 MI.eraseFromParent();
2695 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2702 SegmentNull.getReg(0));
2704 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2706 MI.eraseFromParent();
2711 SrcTy.getSizeInBits() == 64) {
2713 B.buildExtract(Dst, Src, 0);
2714 MI.eraseFromParent();
2721 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2722 auto PtrLo =
B.buildPtrToInt(I32, Src);
2723 if (AddrHiVal == 0) {
2724 auto Zext =
B.buildZExt(I64, PtrLo);
2725 B.buildIntToPtr(Dst, Zext);
2727 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2728 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2731 MI.eraseFromParent();
2738 MI.eraseFromParent();
2747 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2752 auto C1 =
B.buildFConstant(Ty, C1Val);
2753 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2756 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2757 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2759 auto C2 =
B.buildFConstant(Ty, C2Val);
2760 auto Fabs =
B.buildFAbs(Ty, Src);
2763 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2764 MI.eraseFromParent();
2781 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2783 const auto Zero =
B.buildFConstant(
F64, 0.0);
2784 const auto One =
B.buildFConstant(
F64, 1.0);
2787 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2788 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2791 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2792 MI.eraseFromParent();
2800 Register Src0Reg =
MI.getOperand(1).getReg();
2801 Register Src1Reg =
MI.getOperand(2).getReg();
2802 auto Flags =
MI.getFlags();
2805 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2806 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2807 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2808 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2809 MI.eraseFromParent();
2815 const unsigned FractBits = 52;
2816 const unsigned ExpBits = 11;
2819 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2820 auto Const1 =
B.buildConstant(I32, ExpBits);
2822 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2824 .addUse(Const0.getReg(0))
2825 .addUse(Const1.getReg(0));
2827 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2840 auto SrcInt =
B.buildBitcast(I64, Src);
2843 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2850 const unsigned FractBits = 52;
2853 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2854 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2856 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2858 const auto Zero32 =
B.buildConstant(I32, 0);
2861 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2863 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2864 auto Not =
B.buildNot(I64, Shr);
2865 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2866 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2871 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2872 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2873 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2874 MI.eraseFromParent();
2890 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2891 auto ThirtyTwo =
B.buildConstant(I32, 32);
2894 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2895 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2897 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2898 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2901 B.buildFAdd(Dst, LdExp, CvtLo);
2902 MI.eraseFromParent();
2908 auto One =
B.buildConstant(I32, 1);
2912 auto ThirtyOne =
B.buildConstant(I32, 31);
2913 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2914 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2915 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2916 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2917 .addUse(Unmerge.getReg(1));
2918 auto LS2 =
B.buildSub(I32, LS, One);
2919 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2921 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2922 auto Norm =
B.buildShl(I64, Src, ShAmt);
2923 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2924 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2925 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2926 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2927 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2928 B.buildFLdexp(Dst, FVal, Scale);
2929 MI.eraseFromParent();
2949 unsigned Flags =
MI.getFlags();
2960 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2968 auto SrcInt =
B.buildBitcast(I32, Src);
2969 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2970 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2974 K0 =
B.buildFConstant(
2976 K1 =
B.buildFConstant(
2979 K0 =
B.buildFConstant(
2981 K1 =
B.buildFConstant(
2985 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2986 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2987 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2989 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2990 :
B.buildFPTOUI(I32, FloorMul);
2991 auto Lo =
B.buildFPTOUI(I32, Fma);
2995 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2997 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
3000 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3001 MI.eraseFromParent();
3024 uint64_t
Offset =
MI.getOperand(2).getImm();
3033 unsigned StartIdx =
Offset / 32;
3037 if (DstCount == 1) {
3039 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3047 for (
unsigned I = 0;
I < DstCount; ++
I)
3048 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3049 B.buildMergeLikeInstr(DstReg, MergeVec);
3052 MI.eraseFromParent();
3062 Register InsertSrc =
MI.getOperand(2).getReg();
3063 uint64_t
Offset =
MI.getOperand(3).getImm();
3071 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3075 unsigned DstCount = DstSize / 32;
3076 unsigned InsertCount = InsertSize / 32;
3077 unsigned StartIdx =
Offset / 32;
3079 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3082 for (
unsigned I = 0;
I < StartIdx; ++
I)
3085 if (InsertCount == 1) {
3089 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3092 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3093 for (
unsigned I = 0;
I < InsertCount; ++
I)
3097 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3100 B.buildMergeLikeInstr(DstReg, MergeVec);
3102 MI.eraseFromParent();
3129 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3130 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3131 B.buildIntToPtr(Dst, IntElt);
3133 MI.eraseFromParent();
3140 std::optional<ValueAndVReg> MaybeIdxVal =
3144 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3147 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3148 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3153 MI.eraseFromParent();
3182 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3183 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3184 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3186 B.buildIntToPtr(Dst, IntVecDest);
3187 MI.eraseFromParent();
3194 std::optional<ValueAndVReg> MaybeIdxVal =
3199 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3202 if (IdxVal < NumElts) {
3204 for (
unsigned i = 0; i < NumElts; ++i)
3206 B.buildUnmerge(SrcRegs, Vec);
3208 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3209 B.buildMergeLikeInstr(Dst, SrcRegs);
3214 MI.eraseFromParent();
3225 unsigned Flags =
MI.getFlags();
3229 if (ST.hasTrigReducedRange()) {
3230 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3231 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3232 .addUse(MulVal.getReg(0))
3236 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3239 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3243 MI.eraseFromParent();
3251 unsigned GAFlags)
const {
3284 if (ST.has64BitLiterals()) {
3288 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3292 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3302 B.buildExtract(DstReg, PCReg, 0);
3304 B.buildCopy(DstReg, PCReg);
3314 if (RequiresHighHalf && ST.has64BitLiterals()) {
3317 B.buildInstr(AMDGPU::S_MOV_B64)
3320 B.buildCopy(DstReg, Addr);
3328 B.buildInstr(AMDGPU::S_MOV_B32)
3333 if (RequiresHighHalf) {
3335 "Must provide a 64-bit pointer type!");
3340 B.buildInstr(AMDGPU::S_MOV_B32)
3347 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3348 B.buildCast(DstReg, AddrDst);
3350 B.buildCast(DstReg, AddrLo);
3359 unsigned AS = Ty.getAddressSpace();
3370 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3372 B.buildUndef(DstReg);
3373 MI.eraseFromParent();
3377 B.buildConstant(DstReg,
3379 MI.eraseFromParent();
3385 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3388 Fn,
"local memory global used by non-kernel function",
3397 B.buildUndef(DstReg);
3398 MI.eraseFromParent();
3422 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3423 B.buildIntToPtr(DstReg, Sz);
3424 MI.eraseFromParent();
3430 MI.eraseFromParent();
3434 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3436 MI.eraseFromParent();
3444 MI.eraseFromParent();
3450 MI.eraseFromParent();
3466 if (Ty.getSizeInBits() == 32) {
3468 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3469 B.buildExtract(DstReg,
Load, 0);
3471 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3473 MI.eraseFromParent();
3496 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3498 MI.getOperand(1).setReg(Cast.getReg(0));
3503 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3521 const uint64_t AlignInBits = 8 * MemAlign.
value();
3529 if (WideMemSize == ValSize) {
3535 MI.setMemRefs(MF, {WideMMO});
3541 if (ValSize > WideMemSize)
3548 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3549 B.buildTrunc(ValReg, WideLoad).getReg(0);
3556 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3557 B.buildExtract(ValReg, WideLoad, 0);
3561 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3562 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3566 MI.eraseFromParent();
3579 Register DataReg =
MI.getOperand(0).getReg();
3624 "this should not have been custom lowered");
3629 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3631 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3635 .setMemRefs(
MI.memoperands());
3637 MI.eraseFromParent();
3645 switch (
DefMI->getOpcode()) {
3646 case TargetOpcode::G_INTRINSIC: {
3648 case Intrinsic::amdgcn_frexp_mant:
3649 case Intrinsic::amdgcn_log:
3650 case Intrinsic::amdgcn_log_clamp:
3651 case Intrinsic::amdgcn_exp2:
3652 case Intrinsic::amdgcn_sqrt:
3660 case TargetOpcode::G_FSQRT:
3662 case TargetOpcode::G_FFREXP: {
3663 if (
DefMI->getOperand(0).getReg() == Src)
3667 case TargetOpcode::G_FPEXT: {
3688std::pair<Register, Register>
3690 unsigned Flags)
const {
3694 auto SmallestNormal =
B.buildFConstant(
3696 auto IsLtSmallestNormal =
3699 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3700 auto One =
B.buildFConstant(
F32, 1.0);
3702 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3703 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3705 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3718 LLT Ty =
B.getMRI()->getType(Dst);
3719 unsigned Flags =
MI.getFlags();
3723 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3724 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3725 .addUse(Ext.getReg(0))
3727 B.buildFPTrunc(Dst,
Log2, Flags);
3728 MI.eraseFromParent();
3736 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3739 MI.eraseFromParent();
3743 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3744 .addUse(ScaledInput)
3747 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3748 auto Zero =
B.buildFConstant(Ty, 0.0);
3750 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3751 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3753 MI.eraseFromParent();
3759 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3760 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3765 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3766 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3771 unsigned Flags =
MI.getFlags();
3781 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3783 B.buildFPTrunc(Dst, LogVal, Flags);
3788 MI.eraseFromParent();
3797 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3800 if (ST.hasFastFMAF32()) {
3802 const float c_log10 = 0x1.344134p-2f;
3803 const float cc_log10 = 0x1.09f79ep-26f;
3806 const float c_log = 0x1.62e42ep-1f;
3807 const float cc_log = 0x1.efa39ep-25f;
3809 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3810 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3814 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3815 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3816 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3817 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3818 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3821 const float ch_log10 = 0x1.344000p-2f;
3822 const float ct_log10 = 0x1.3509f6p-18f;
3825 const float ch_log = 0x1.62e000p-1f;
3826 const float ct_log = 0x1.0bfbe8p-15f;
3828 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3829 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3832 auto YInt =
B.buildBitcast(I32,
Y);
3833 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3834 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3835 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3839 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3842 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3844 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3847 const bool IsFiniteOnly =
3850 if (!IsFiniteOnly) {
3853 auto Fabs =
B.buildFAbs(Ty,
Y);
3856 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3860 auto Zero =
B.buildFConstant(Ty, 0.0);
3862 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3863 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3864 B.buildFSub(Dst, R, Shift, Flags);
3866 B.buildCopy(Dst, R);
3869 MI.eraseFromParent();
3875 unsigned Flags)
const {
3876 const double Log2BaseInverted =
3879 LLT Ty =
B.getMRI()->getType(Dst);
3884 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3885 .addUse(ScaledInput)
3887 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3888 auto Zero =
B.buildFConstant(Ty, 0.0);
3890 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3891 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3893 if (ST.hasFastFMAF32())
3894 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3896 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3897 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3904 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3905 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3908 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3909 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3920 unsigned Flags =
MI.getFlags();
3921 LLT Ty =
B.getMRI()->getType(Dst);
3928 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3929 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3930 .addUse(Ext.getReg(0))
3932 B.buildFPTrunc(Dst,
Log2, Flags);
3933 MI.eraseFromParent();
3943 MI.eraseFromParent();
3951 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3953 RangeCheckConst, Flags);
3955 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3956 auto Zero =
B.buildFConstant(Ty, 0.0);
3957 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3958 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3960 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3961 .addUse(AddInput.getReg(0))
3964 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3965 auto One =
B.buildFConstant(Ty, 1.0);
3966 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3967 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3968 MI.eraseFromParent();
3973 const SrcOp &Src,
unsigned Flags) {
3974 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3977 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3978 .addUse(Src.getReg())
3981 return B.buildFExp2(Dst, Src, Flags);
3987 bool IsExp10)
const {
3988 LLT Ty =
B.getMRI()->getType(
X);
3992 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3993 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4000 LLT Ty =
B.getMRI()->getType(Dst);
4006 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4009 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4010 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4011 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4014 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4016 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4017 .addUse(ExpInput.getReg(0))
4020 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4021 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4022 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4028 unsigned Flags)
const {
4029 LLT Ty =
B.getMRI()->getType(Dst);
4033 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4034 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4036 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4037 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4038 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4039 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4040 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4050 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4054 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4055 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4056 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4058 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4059 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4061 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4062 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4063 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4064 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4066 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4067 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4068 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4070 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4088 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4090 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4092 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4094 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4095 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4096 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4097 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4099 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4100 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4101 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4102 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4104 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4105 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4106 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4107 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4108 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4110 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4111 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4112 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4113 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4116 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4117 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4118 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4120 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4121 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4122 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4123 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4124 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4128 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4129 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4131 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4133 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4135 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4137 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4139 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4140 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4141 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4142 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4144 auto One =
B.buildFConstant(
F64, 1.0);
4145 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4146 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4149 auto DnInt =
B.buildFPTOSI(I32, Dn);
4150 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4157 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4164 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4166 MI.eraseFromParent();
4174 const unsigned Flags =
MI.getFlags();
4182 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4190 MI.eraseFromParent();
4201 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4204 B.buildFPTrunc(Dst, Lowered, Flags);
4205 MI.eraseFromParent();
4216 MI.eraseFromParent();
4244 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4247 if (ST.hasFastFMAF32()) {
4249 const float cc_exp = 0x1.4ae0bep-26f;
4250 const float c_exp10 = 0x1.a934f0p+1f;
4251 const float cc_exp10 = 0x1.2f346ep-24f;
4253 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4254 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4255 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4256 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4258 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4259 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4261 const float ch_exp = 0x1.714000p+0f;
4262 const float cl_exp = 0x1.47652ap-12f;
4264 const float ch_exp10 = 0x1.a92000p+1f;
4265 const float cl_exp10 = 0x1.4f0978p-11f;
4268 auto XInt =
B.buildBitcast(I32,
X);
4269 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4270 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4271 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4273 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4274 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4276 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4277 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4280 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4281 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4284 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4287 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4288 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4290 auto IntE =
B.buildFPTOSI(I32, E);
4292 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4293 .addUse(
A.getReg(0))
4295 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4297 auto UnderflowCheckConst =
4298 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4299 auto Zero =
B.buildFConstant(Ty, 0.0);
4303 R =
B.buildSelect(Ty, Underflow, Zero, R);
4306 auto OverflowCheckConst =
4307 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4312 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4315 B.buildCopy(Dst, R);
4316 MI.eraseFromParent();
4327 unsigned Flags =
MI.getFlags();
4336 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4338 .setMIFlags(CoreFlags);
4339 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4341 .addUse(Log.getReg(0))
4342 .setMIFlags(CoreFlags);
4344 MI.eraseFromParent();
4348 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4349 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4350 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4352 .addUse(Log.getReg(0))
4353 .setMIFlags(CoreFlags);
4358 .signBitIsZeroOrNaN()) {
4359 B.buildFExp2(Dst,
Mul, CoreFlags);
4360 MI.eraseFromParent();
4366 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4368 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4369 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4370 auto YIsOdd =
B.buildAnd(
4374 auto Neg =
B.buildFCopysign(
F32, R,
X);
4376 B.buildSelect(Dst, YIsOdd, Neg, R);
4377 MI.eraseFromParent();
4380 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4387 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4389 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4391 B.buildSelect(Dst, NegNonInt, NaN, R);
4393 MI.eraseFromParent();
4401 ModSrc = SrcFNeg->getOperand(1).getReg();
4403 ModSrc = SrcFAbs->getOperand(1).getReg();
4405 ModSrc = SrcFAbs->getOperand(1).getReg();
4415 Register OrigSrc =
MI.getOperand(1).getReg();
4416 unsigned Flags =
MI.getFlags();
4418 "this should not have been custom lowered");
4428 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4448 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4450 B.buildFMinNum(Min, Fract, Const, Flags);
4455 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4458 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4459 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4461 MI.eraseFromParent();
4479 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4481 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4482 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4485 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4486 B.buildBitcast(Dst,
Merge);
4488 MI.eraseFromParent();
4505 bool UsePartialMad64_32,
4506 bool SeparateOddAlignedProducts)
const {
4521 auto getZero32 = [&]() ->
Register {
4523 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4526 auto getZero64 = [&]() ->
Register {
4528 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4533 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4544 if (CarryIn.empty())
4547 bool HaveCarryOut =
true;
4549 if (CarryIn.size() == 1) {
4551 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4555 CarryAccum = getZero32();
4557 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4558 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4560 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4565 LocalAccum = getZero32();
4566 HaveCarryOut =
false;
4571 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4572 LocalAccum =
Add.getReg(0);
4586 auto buildMadChain =
4589 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4590 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4597 if (LocalAccum.size() == 1 &&
4598 (!UsePartialMad64_32 || !CarryIn.empty())) {
4601 unsigned j1 = DstIndex - j0;
4602 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4606 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4608 LocalAccum[0] =
Mul.getReg(0);
4610 if (CarryIn.empty()) {
4611 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4614 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4620 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4624 if (j0 <= DstIndex) {
4625 bool HaveSmallAccum =
false;
4628 if (LocalAccum[0]) {
4629 if (LocalAccum.size() == 1) {
4630 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4631 HaveSmallAccum =
true;
4632 }
else if (LocalAccum[1]) {
4633 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4634 HaveSmallAccum =
false;
4636 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4637 HaveSmallAccum =
true;
4640 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4642 HaveSmallAccum =
true;
4646 unsigned j1 = DstIndex - j0;
4647 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4651 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4652 {Src0[j0], Src1[j1], Tmp});
4653 Tmp = Mad.getReg(0);
4654 if (!HaveSmallAccum)
4655 CarryOut.push_back(Mad.getReg(1));
4656 HaveSmallAccum =
false;
4659 }
while (j0 <= DstIndex);
4661 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4662 LocalAccum[0] = Unmerge.getReg(0);
4663 if (LocalAccum.size() > 1)
4664 LocalAccum[1] = Unmerge.getReg(1);
4671 LocalAccum[0] = getZero32();
4675 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4676 "Uninitialized accumulator part");
4702 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4703 Carry OddCarryIn = std::move(OddCarry);
4704 Carry EvenCarryIn = std::move(EvenCarry);
4709 if (2 * i < Accum.
size()) {
4710 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4711 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4716 if (!SeparateOddAlignedProducts) {
4717 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4718 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4720 bool IsHighest = 2 * i >= Accum.
size();
4723 .take_front(IsHighest ? 1 : 2);
4724 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4730 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4732 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4734 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4737 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4740 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4741 Lo->getOperand(1).getReg());
4742 Accum[2 * i] =
Hi.getReg(0);
4743 SeparateOddCarry =
Hi.getReg(1);
4750 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4751 EvenCarryIn.push_back(CarryOut);
4753 if (2 * i < Accum.
size()) {
4754 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4755 OddCarry.push_back(CarryOut);
4767 assert(ST.hasMad64_32());
4768 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4780 unsigned Size = Ty.getSizeInBits();
4781 if (ST.useVMulU64Inst() &&
Size == 64)
4784 unsigned NumParts =
Size / 32;
4796 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4800 for (
unsigned i = 0; i < NumParts; ++i) {
4804 B.buildUnmerge(Src0Parts, Src0);
4805 B.buildUnmerge(Src1Parts, Src1);
4808 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4809 SeparateOddAlignedProducts);
4811 B.buildMergeLikeInstr(DstReg, AccumRegs);
4812 MI.eraseFromParent();
4827 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4828 ? AMDGPU::G_AMDGPU_FFBH_U32
4829 : AMDGPU::G_AMDGPU_FFBL_B32;
4830 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4833 MI.eraseFromParent();
4843 TypeSize NumBits = SrcTy.getSizeInBits();
4848 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4849 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4850 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4851 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4852 B.buildTrunc(Dst, Ctlz);
4853 MI.eraseFromParent();
4864 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4865 unsigned BitWidth = SrcTy.getSizeInBits();
4867 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4868 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4869 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4870 MI.eraseFromParent();
4876 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4879 return ConstVal == -1;
4886 Register CondDef =
MI.getOperand(0).getReg();
4905 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4914 UncondBrTarget = &*NextMBB;
4916 if (
Next->getOpcode() != AMDGPU::G_BR)
4935 *ArgRC,
B.getDebugLoc(), ArgTy);
4939 const unsigned Mask = Arg->
getMask();
4947 auto ShiftAmt =
B.buildConstant(I32, Shift);
4948 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4951 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4953 B.buildCopy(DstReg, LiveIn);
4963 if (!ST.hasClusters()) {
4966 MI.eraseFromParent();
4986 auto One =
B.buildConstant(I32, 1);
4987 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4988 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4989 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4996 B.buildCopy(DstReg, GlobalIdXYZ);
4997 MI.eraseFromParent();
5001 B.buildCopy(DstReg, ClusterIdXYZ);
5002 MI.eraseFromParent();
5007 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5009 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5010 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5012 .addImm(ClusterIdField);
5013 auto Zero =
B.buildConstant(I32, 0);
5016 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5017 MI.eraseFromParent();
5059 auto LoadConstant = [&](
unsigned N) {
5060 B.buildConstant(DstReg,
N);
5064 if (ST.hasArchitectedSGPRs() &&
5071 Arg = &WorkGroupIDX;
5072 ArgRC = &AMDGPU::SReg_32RegClass;
5076 Arg = &WorkGroupIDY;
5077 ArgRC = &AMDGPU::SReg_32RegClass;
5081 Arg = &WorkGroupIDZ;
5082 ArgRC = &AMDGPU::SReg_32RegClass;
5086 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5087 return LoadConstant(0);
5088 Arg = &ClusterWorkGroupIDX;
5089 ArgRC = &AMDGPU::SReg_32RegClass;
5093 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5094 return LoadConstant(0);
5095 Arg = &ClusterWorkGroupIDY;
5096 ArgRC = &AMDGPU::SReg_32RegClass;
5100 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5101 return LoadConstant(0);
5102 Arg = &ClusterWorkGroupIDZ;
5103 ArgRC = &AMDGPU::SReg_32RegClass;
5108 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5109 Arg = &ClusterWorkGroupMaxIDX;
5110 ArgRC = &AMDGPU::SReg_32RegClass;
5115 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5116 Arg = &ClusterWorkGroupMaxIDY;
5117 ArgRC = &AMDGPU::SReg_32RegClass;
5122 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5123 Arg = &ClusterWorkGroupMaxIDZ;
5124 ArgRC = &AMDGPU::SReg_32RegClass;
5128 Arg = &ClusterWorkGroupMaxFlatID;
5129 ArgRC = &AMDGPU::SReg_32RegClass;
5144 return LoadConstant(0);
5149 B.buildUndef(DstReg);
5153 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5165 MI.eraseFromParent();
5171 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5172 MI.eraseFromParent();
5179 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5193 B.buildUndef(DstReg);
5194 MI.eraseFromParent();
5198 if (Arg->isMasked()) {
5212 MI.eraseFromParent();
5227 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5236 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5244 Align Alignment)
const {
5248 "unexpected kernarg parameter type");
5255 MI.eraseFromParent();
5287 auto FloatY =
B.buildUITOFP(
F32,
Y);
5288 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5290 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5291 auto Z =
B.buildFPTOUI(I32, ScaledY);
5294 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5295 auto NegYZ =
B.buildMul(I32, NegY, Z);
5296 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5299 auto Q =
B.buildUMulH(I32,
X, Z);
5300 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5303 auto One =
B.buildConstant(I32, 1);
5306 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5307 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5312 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5315 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5334 auto Unmerge =
B.buildUnmerge(I32, Val);
5336 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5337 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5339 auto Mad =
B.buildFMAD(
5343 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5344 auto Mul1 =
B.buildFMul(
5348 auto Mul2 =
B.buildFMul(
5350 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5353 auto Mad2 =
B.buildFMAD(
5357 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5358 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5360 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5375 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5377 auto Zero64 =
B.buildConstant(I64, 0);
5378 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5380 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5381 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5383 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5384 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5385 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5387 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5388 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5389 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5391 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5392 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5393 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5394 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5395 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5397 auto Zero32 =
B.buildConstant(I32, 0);
5398 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5399 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5400 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5402 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5403 Register NumerLo = UnmergeNumer.getReg(0);
5404 Register NumerHi = UnmergeNumer.getReg(1);
5406 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5407 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5408 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5409 Register Mul3_Lo = UnmergeMul3.getReg(0);
5410 Register Mul3_Hi = UnmergeMul3.getReg(1);
5411 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5412 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5413 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5414 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5416 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5417 Register DenomLo = UnmergeDenom.getReg(0);
5418 Register DenomHi = UnmergeDenom.getReg(1);
5421 auto C1 =
B.buildSExt(I32, CmpHi);
5424 auto C2 =
B.buildSExt(I32, CmpLo);
5427 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5434 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5435 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5436 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5437 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5439 auto One64 =
B.buildConstant(I64, 1);
5440 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5446 auto C6 =
B.buildSelect(
5450 auto Add4 =
B.buildAdd(I64, Add3, One64);
5451 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5453 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5454 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5455 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5461 auto Sel1 =
B.buildSelect(
5468 auto Sel2 =
B.buildSelect(
5479 switch (
MI.getOpcode()) {
5482 case AMDGPU::G_UDIV: {
5483 DstDivReg =
MI.getOperand(0).getReg();
5486 case AMDGPU::G_UREM: {
5487 DstRemReg =
MI.getOperand(0).getReg();
5490 case AMDGPU::G_UDIVREM: {
5491 DstDivReg =
MI.getOperand(0).getReg();
5492 DstRemReg =
MI.getOperand(1).getReg();
5499 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5500 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5501 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5511 MI.eraseFromParent();
5522 if (Ty != I32 && Ty != I64)
5525 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5526 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5527 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5529 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5530 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5531 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5533 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5534 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5536 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5537 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5539 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5540 switch (
MI.getOpcode()) {
5543 case AMDGPU::G_SDIV: {
5544 DstDivReg =
MI.getOperand(0).getReg();
5548 case AMDGPU::G_SREM: {
5549 DstRemReg =
MI.getOperand(0).getReg();
5553 case AMDGPU::G_SDIVREM: {
5554 DstDivReg =
MI.getOperand(0).getReg();
5555 DstRemReg =
MI.getOperand(1).getReg();
5568 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5569 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5570 B.buildSub(DstDivReg, SignXor, Sign);
5574 auto Sign = LHSign.getReg(0);
5575 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5576 B.buildSub(DstRemReg, SignXor, Sign);
5579 MI.eraseFromParent();
5589 uint16_t Flags =
MI.getFlags();
5595 if (!AllowInaccurateRcp && ResTy !=
F16)
5606 if (CLHS->isOne()) {
5607 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5611 MI.eraseFromParent();
5616 if (CLHS->isMinusOne()) {
5617 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5618 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5619 .addUse(FNeg.getReg(0))
5622 MI.eraseFromParent();
5629 if (!AllowInaccurateRcp &&
5634 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5637 B.buildFMul(Res, LHS, RCP, Flags);
5639 MI.eraseFromParent();
5649 uint16_t Flags =
MI.getFlags();
5654 if (!AllowInaccurateRcp)
5662 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5664 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5665 auto One =
B.buildFConstant(ResTy, 1.0);
5667 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5671 R =
B.buildFNeg(ResTy, R);
5673 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5674 R =
B.buildFMA(ResTy, Tmp0, R, R);
5676 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5677 R =
B.buildFMA(ResTy, Tmp1, R, R);
5680 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5681 B.buildCopy(Res, R);
5682 MI.eraseFromParent();
5686 auto Ret =
B.buildFMul(ResTy,
X, R);
5687 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5689 B.buildFMA(Res, Tmp2, R, Ret);
5690 MI.eraseFromParent();
5704 uint16_t Flags =
MI.getFlags();
5721 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5722 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5723 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5724 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5725 .addUse(RHSExt.getReg(0))
5727 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5729 if (ST.hasMadMacF32Insts()) {
5730 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5731 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5732 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5734 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5735 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5736 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5738 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5739 auto TmpInt =
B.buildBitcast(I32, Tmp);
5740 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5741 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5742 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5743 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5744 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5745 .addUse(RDst.getReg(0))
5750 MI.eraseFromParent();
5763 unsigned SPDenormMode =
5766 if (ST.hasDenormModeInst()) {
5768 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5770 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5771 B.buildInstr(AMDGPU::S_DENORM_MODE)
5772 .addImm(NewDenormModeValue);
5775 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5776 .addImm(SPDenormMode)
5793 uint16_t Flags =
MI.getFlags();
5797 auto One =
B.buildFConstant(
F32, 1.0f);
5799 auto DenominatorScaled =
5800 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5805 auto NumeratorScaled =
5806 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5812 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5813 .addUse(DenominatorScaled.getReg(0))
5815 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5818 const bool HasDynamicDenormals =
5823 if (!PreservesDenormals) {
5824 if (HasDynamicDenormals) {
5826 B.buildInstr(AMDGPU::S_GETREG_B32)
5827 .addDef(SavedSPDenormMode)
5833 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5834 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5835 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5836 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5837 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5838 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5840 if (!PreservesDenormals) {
5841 if (HasDynamicDenormals) {
5842 assert(SavedSPDenormMode);
5843 B.buildInstr(AMDGPU::S_SETREG_B32)
5844 .addReg(SavedSPDenormMode)
5850 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5851 .addUse(Fma4.getReg(0))
5852 .addUse(Fma1.getReg(0))
5853 .addUse(Fma3.getReg(0))
5854 .addUse(NumeratorScaled.getReg(1))
5857 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5858 .addUse(Fmas.getReg(0))
5863 MI.eraseFromParent();
5877 uint16_t Flags =
MI.getFlags();
5881 auto One =
B.buildFConstant(
F64, 1.0);
5883 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5889 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5891 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5892 .addUse(DivScale0.getReg(0))
5895 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5896 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5897 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5899 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5905 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5906 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5907 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5910 if (!ST.hasUsableDivScaleConditionOutput()) {
5917 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5918 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5919 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5920 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5923 Scale1Unmerge.getReg(1));
5925 Scale0Unmerge.getReg(1));
5926 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5928 Scale = DivScale1.getReg(1);
5931 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5932 .addUse(Fma4.getReg(0))
5933 .addUse(Fma3.getReg(0))
5934 .addUse(
Mul.getReg(0))
5938 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5939 .addUse(Fmas.getReg(0))
5944 MI.eraseFromParent();
5954 uint16_t Flags =
MI.getFlags();
5959 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5962 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5966 if (ST.hasFractBug()) {
5967 auto Fabs =
B.buildFAbs(Ty, Val);
5971 auto Zero =
B.buildConstant(InstrExpTy, 0);
5972 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5973 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5976 B.buildCopy(Res0, Mant);
5977 B.buildSExtOrTrunc(Res1, Exp);
5979 MI.eraseFromParent();
5989 uint16_t Flags =
MI.getFlags();
5993 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5996 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5997 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5998 auto C2 =
B.buildFConstant(
F32, 1.0f);
6001 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
6003 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6005 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6006 .addUse(Mul0.getReg(0))
6009 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6011 B.buildFMul(Res, Sel, Mul1, Flags);
6013 MI.eraseFromParent();
6022 unsigned Flags =
MI.getFlags();
6023 assert(!ST.has16BitInsts());
6024 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6025 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6026 .addUse(Ext.getReg(0))
6028 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6029 MI.eraseFromParent();
6039 const unsigned Flags =
MI.getFlags();
6047 MI.eraseFromParent();
6051 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6053 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6054 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6055 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6060 .addUse(SqrtX.getReg(0))
6063 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6064 auto NegOne =
B.buildConstant(I32, -1);
6065 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6067 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6068 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6070 auto PosOne =
B.buildConstant(I32, 1);
6071 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6073 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6074 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6076 auto Zero =
B.buildFConstant(
F32, 0.0f);
6080 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6084 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6087 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6088 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6090 auto Half =
B.buildFConstant(
F32, 0.5f);
6091 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6092 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6093 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6094 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6095 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6096 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6097 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6098 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6101 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6103 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6105 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6108 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6110 MI.eraseFromParent();
6144 unsigned Flags =
MI.getFlags();
6149 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6151 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6155 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6156 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6157 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6160 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6162 auto Half =
B.buildFConstant(
F64, 0.5);
6163 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6164 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6166 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6167 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6169 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6170 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6172 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6173 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6175 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6177 Register SqrtRet = SqrtS2.getReg(0);
6179 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6180 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6181 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6184 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6185 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6186 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6191 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6194 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6200 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6202 MI.eraseFromParent();
6233 auto Flags =
MI.getFlags();
6245 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6255 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6256 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6261 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6263 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6264 MI.eraseFromParent();
6276 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6277 IID == Intrinsic::amdgcn_permlanex16;
6278 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6279 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6280 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6281 IID == Intrinsic::amdgcn_permlane_up ||
6282 IID == Intrinsic::amdgcn_permlane_down ||
6283 IID == Intrinsic::amdgcn_permlane_xor;
6287 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6289 case Intrinsic::amdgcn_readfirstlane:
6290 case Intrinsic::amdgcn_permlane64:
6291 return LaneOp.getReg(0);
6292 case Intrinsic::amdgcn_readlane:
6293 case Intrinsic::amdgcn_set_inactive:
6294 case Intrinsic::amdgcn_set_inactive_chain_arg:
6295 return LaneOp.addUse(Src1).getReg(0);
6296 case Intrinsic::amdgcn_writelane:
6297 case Intrinsic::amdgcn_permlane_bcast:
6298 case Intrinsic::amdgcn_permlane_up:
6299 case Intrinsic::amdgcn_permlane_down:
6300 case Intrinsic::amdgcn_permlane_xor:
6301 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6302 case Intrinsic::amdgcn_permlane16:
6303 case Intrinsic::amdgcn_permlanex16: {
6305 int64_t Src4 =
MI.getOperand(6).getImm();
6306 int64_t Src5 =
MI.getOperand(7).getImm();
6307 return LaneOp.addUse(Src1)
6314 case Intrinsic::amdgcn_mov_dpp8:
6315 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6316 case Intrinsic::amdgcn_update_dpp:
6317 return LaneOp.addUse(Src1)
6318 .addImm(
MI.getOperand(4).getImm())
6319 .addImm(
MI.getOperand(5).getImm())
6320 .addImm(
MI.getOperand(6).getImm())
6321 .addImm(
MI.getOperand(7).getImm())
6331 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6332 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6333 IsPermlaneShuffle) {
6334 Src1 =
MI.getOperand(3).getReg();
6335 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6336 IsPermlaneShuffle) {
6337 Src2 =
MI.getOperand(4).getReg();
6342 unsigned Size = Ty.getSizeInBits();
6344 unsigned SplitSize = 32;
6345 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6346 ST.hasDPALU_DPP() &&
6350 if (
Size == SplitSize) {
6357 bool IsFloat = Ty.getScalarType().isFloat();
6361 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6363 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6365 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6369 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6371 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6372 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6374 if (IID == Intrinsic::amdgcn_writelane)
6375 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6377 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6379 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6381 B.buildTrunc(DstReg, LaneOpDst);
6382 MI.eraseFromParent();
6386 if (
Size % SplitSize != 0)
6390 bool NeedsBitcast =
false;
6391 if (IntTy.isVector()) {
6394 if (EltSize == SplitSize) {
6395 PartialResTy = EltTy;
6396 }
else if (EltSize == 16 || EltSize == 32) {
6397 unsigned NElem = SplitSize / EltSize;
6400 NeedsBitcast =
true;
6405 unsigned NumParts =
Size / SplitSize;
6409 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6410 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6412 if (IID == Intrinsic::amdgcn_writelane)
6413 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6415 for (
unsigned i = 0; i < NumParts; ++i) {
6416 Src0 = Src0Parts.
getReg(i);
6418 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6419 Src1 = Src1Parts.
getReg(i);
6421 if (IID == Intrinsic::amdgcn_writelane)
6422 Src2 = Src2Parts.
getReg(i);
6424 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6427 if (NeedsBitcast || IsFloat)
6430 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6432 B.buildMergeLikeInstr(DstReg, PartialRes);
6434 MI.eraseFromParent();
6442 ST.getTargetLowering()->getImplicitParameterOffset(
6452 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6453 B.buildConstant(IdxTy,
Offset).getReg(0));
6464 Register Pointer =
MI.getOperand(2).getReg();
6466 Register NumRecords =
MI.getOperand(4).getReg();
6472 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6474 auto ExtStride =
B.buildAnyExt(I32, Stride);
6476 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6477 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6479 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6481 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6485 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6486 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6487 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6488 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6492 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6493 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6494 auto ExtShiftedStride =
6495 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6496 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6497 auto ExtShiftedFlags =
6498 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6499 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6501 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6502 B.buildMergeValues(Result, {LowHalf, HighHalf});
6504 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6505 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6506 auto LowHalf = Unmerge.getReg(0);
6507 auto HighHalf = Unmerge.getReg(1);
6509 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6510 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6511 auto ShiftConst =
B.buildConstant(I32, 16);
6512 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6513 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6514 Register NewHighHalfReg = NewHighHalf.getReg(0);
6515 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6518 MI.eraseFromParent();
6535 MI.eraseFromParent();
6543 std::optional<uint32_t> KnownSize =
6545 if (KnownSize.has_value())
6546 B.buildConstant(DstReg, *KnownSize);
6564 MI.eraseFromParent();
6571 unsigned AddrSpace)
const {
6573 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6577 ST.hasGloballyAddressableScratch()) {
6579 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6580 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6582 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6584 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6586 B.buildConstant(I32, 1u << 26));
6591 MI.eraseFromParent();
6601std::pair<Register, unsigned>
6613 bool CheckNUW = ST.hasGFX1250Insts();
6615 MRI, OrigOffset,
nullptr, CheckNUW);
6619 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6629 unsigned Overflow = ImmOffset & ~MaxImm;
6630 ImmOffset -= Overflow;
6631 if ((int32_t)Overflow < 0) {
6632 Overflow += ImmOffset;
6636 if (Overflow != 0) {
6638 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6640 auto OverflowVal =
B.buildConstant(I32, Overflow);
6641 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6646 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6648 return std::pair(BaseReg, ImmOffset);
6655 bool ImageStore)
const {
6663 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6665 if (ST.hasUnpackedD16VMem()) {
6666 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6669 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6670 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6678 if (ImageStore && ST.hasImageStoreD16Bug()) {
6681 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6683 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6690 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6691 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6693 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6701 auto Unmerge =
B.buildUnmerge(I32, Reg);
6702 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6704 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6714 Reg =
B.buildPadVectorWithUndefElements(
6723 bool IsFormat)
const {
6733 VData =
B.buildBitcast(Ty, VData).getReg(0);
6741 if (Ty.isVector()) {
6742 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6754 bool IsFormat)
const {
6761 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6768 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6769 const Function &Fn =
B.getMF().getFunction();
6771 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6772 MI.eraseFromParent();
6784 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6787 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6791 VIndex =
MI.getOperand(3).getReg();
6794 VIndex =
B.buildConstant(I32, 0).getReg(0);
6797 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6798 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6802 Format =
MI.getOperand(5 + OpOffset).getImm();
6806 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6812 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6813 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6814 }
else if (IsFormat) {
6815 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6816 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6820 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6823 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6826 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6831 auto MIB =
B.buildInstr(
Opc)
6842 MIB.addImm(AuxiliaryData)
6843 .addImm(HasVIndex ? -1 : 0)
6844 .addMemOperand(MMO);
6846 MI.eraseFromParent();
6852 unsigned ImmOffset,
unsigned Format,
6855 auto MIB =
B.buildInstr(
Opc)
6866 MIB.addImm(AuxiliaryData)
6867 .addImm(HasVIndex ? -1 : 0)
6868 .addMemOperand(MMO);
6874 Register SOffset,
unsigned ImmOffset,
6875 unsigned Format,
unsigned AuxiliaryData,
6879 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6881 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6884 B.buildUnmerge(Unmerge, LoadDstReg);
6890 bool IsTyped)
const {
6904 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6905 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6907 StatusDst =
MI.getOperand(1).getReg();
6912 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6915 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6918 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6921 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6924 VIndex =
B.buildConstant(I32, 0).getReg(0);
6927 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6928 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6932 Format =
MI.getOperand(5 + OpOffset).getImm();
6936 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6946 Dst =
MI.getOperand(0).getReg();
6947 B.setInsertPt(
B.getMBB(),
MI);
6954 Dst =
MI.getOperand(0).getReg();
6955 B.setInsertPt(
B.getMBB(),
MI);
6959 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6960 const bool Unpacked = ST.hasUnpackedD16VMem();
6962 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6963 const Function &Fn =
B.getMF().getFunction();
6965 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6968 B.buildUndef(StatusDst);
6969 MI.eraseFromParent();
6973 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6974 const Function &Fn =
B.getMF().getFunction();
6976 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6979 B.buildUndef(StatusDst);
6980 MI.eraseFromParent();
6992 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6993 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6994 }
else if (IsFormat) {
6996 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
6997 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6999 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
7000 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
7005 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
7006 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7009 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7010 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7013 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7014 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7019 if (IsTFE && IsD16 && Ty.isVector()) {
7021 const unsigned NumElts = Ty.getNumElements();
7022 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7025 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7028 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7033 R =
B.buildTrunc(EltTy, R).getReg(0);
7034 B.buildMergeLikeInstr(Dst, ValueDWords);
7043 if (PackedTy == Ty) {
7044 B.buildBitcast(Dst, Merged);
7046 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7047 B.buildDeleteTrailingVectorElements(Dst, Packed);
7051 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7059 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7061 B.buildTrunc(DstInt, ExtDst);
7062 }
else if (NumValueDWords == 1) {
7064 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7068 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7071 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7072 IsTyped, HasVIndex,
B);
7073 B.buildMergeLikeInstr(DstInt, ValueDWords);
7076 B.buildBitcast(Dst, DstInt);
7078 (IsD16 && !Ty.isVector())) {
7079 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7081 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7082 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7083 B.buildTrunc(Dst, LoadDstReg);
7084 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7086 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7088 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7089 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7091 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7093 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7094 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7095 B.buildMergeLikeInstr(Dst, Repack);
7098 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7101 MI.eraseFromParent();
7107 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7108 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7109 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7110 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7111 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7112 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7113 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7114 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7115 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7116 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7117 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7118 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7119 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7120 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7121 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7122 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7123 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7124 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7125 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7126 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7127 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7129 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7130 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7131 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7132 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7133 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7134 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7135 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7136 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7137 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7138 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7139 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7140 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7141 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7142 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7144 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7145 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7146 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7147 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7148 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7149 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7150 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7151 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7152 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7153 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7154 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7155 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7156 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7157 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7158 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7159 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7160 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7161 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7162 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7163 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7164 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7166 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7167 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7168 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7169 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7170 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7171 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7172 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7173 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7174 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7175 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7176 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7177 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7179 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7180 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7181 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7182 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7183 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7184 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7185 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7186 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7187 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7188 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7189 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7190 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7191 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7192 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7193 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7194 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7195 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7196 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7205 const bool IsCmpSwap =
7206 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7207 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7208 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7209 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7220 CmpVal =
MI.getOperand(3).getReg();
7225 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7226 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7229 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7232 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7238 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7239 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7240 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7259 .addImm(AuxiliaryData)
7260 .addImm(HasVIndex ? -1 : 0)
7261 .addMemOperand(MMO);
7263 MI.eraseFromParent();
7273 bool IsA16,
bool IsG16) {
7287 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7292 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7296 "Bias needs to be converted to 16 bit in A16 mode");
7298 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7302 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7306 if (((
I + 1) >= EndIdx) ||
7313 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7315 B.buildBuildVector(V2EltTy,
7316 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7321 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7332 int DimIdx,
int NumVAddrs) {
7334 for (
int I = 0;
I != NumVAddrs; ++
I) {
7336 if (
SrcOp.isReg()) {
7339 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7340 if (
B.getMRI()->getType(
Reg) != I32)
7341 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7346 int NumAddrRegs = AddrRegs.
size();
7347 if (NumAddrRegs != 1) {
7348 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7351 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7354 for (
int I = 1;
I != NumVAddrs; ++
I) {
7357 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7379 const unsigned NumDefs =
MI.getNumExplicitDefs();
7380 const unsigned ArgOffset = NumDefs + 1;
7381 bool IsTFE = NumDefs == 2;
7399 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7403 const bool IsAtomicPacked16Bit =
7404 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7405 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7412 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7413 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7414 const bool DataTyIs16 =
7415 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7417 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7418 const bool IsA16 = AddrTyIs16;
7419 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7422 if (!BaseOpcode->
Atomic) {
7423 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7426 }
else if (DMask != 0) {
7428 }
else if (!IsTFE && !BaseOpcode->
Store) {
7430 B.buildUndef(
MI.getOperand(0));
7431 MI.eraseFromParent();
7439 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7440 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7441 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7442 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7443 unsigned NewOpcode = LoadOpcode;
7444 if (BaseOpcode->
Store)
7445 NewOpcode = StoreOpcode;
7447 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7450 MI.setDesc(
B.getTII().get(NewOpcode));
7454 if (IsTFE && DMask == 0) {
7457 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7460 if (BaseOpcode->
Atomic) {
7465 if (Ty.isVector() && !IsAtomicPacked16Bit)
7472 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7473 MI.getOperand(2).setReg(
Concat.getReg(0));
7474 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7478 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7481 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7487 if (IsA16 && !ST.hasA16()) {
7492 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7493 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7495 if (IsA16 || IsG16) {
7503 const bool UseNSA = ST.hasNSAEncoding() &&
7504 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7505 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7506 const bool UsePartialNSA =
7507 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7509 if (UsePartialNSA) {
7513 auto Concat =
B.buildConcatVectors(
7514 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7515 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7516 PackedRegs.
resize(NSAMaxSize);
7517 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7519 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7520 PackedRegs[0] =
Concat.getReg(0);
7524 const unsigned NumPacked = PackedRegs.
size();
7527 if (!
SrcOp.isReg()) {
7537 SrcOp.setReg(AMDGPU::NoRegister);
7554 const bool UseNSA = ST.hasNSAEncoding() &&
7555 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7556 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7557 const bool UsePartialNSA =
7558 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7560 if (UsePartialNSA) {
7562 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7564 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7579 if (!Ty.isVector() || !IsD16)
7583 if (RepackedReg != VData) {
7584 MI.getOperand(1).setReg(RepackedReg);
7592 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7595 if (NumElts < DMaskLanes)
7598 if (NumElts > 4 || DMaskLanes > 4)
7609 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7610 const LLT AdjustedTy =
7626 if (IsD16 && ST.hasUnpackedD16VMem()) {
7633 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7634 unsigned RoundedSize = 32 * RoundedElts;
7638 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7643 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7649 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7653 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7654 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7658 MI.getOperand(0).setReg(NewResultReg);
7666 Dst1Reg =
MI.getOperand(1).getReg();
7667 if (MRI->
getType(Dst1Reg) != I32)
7671 MI.removeOperand(1);
7674 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7675 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7676 B.buildBitcast(DstReg, Unmerge.getReg(0));
7677 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7686 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7688 if (ResultNumRegs == 1) {
7690 ResultRegs[0] = NewResultReg;
7693 for (
int I = 0;
I != NumDataRegs; ++
I)
7695 B.buildUnmerge(ResultRegs, NewResultReg);
7700 ResultRegs.
resize(NumDataRegs);
7705 if (IsD16 && !Ty.isVector()) {
7706 B.buildTrunc(DstReg, ResultRegs[0]);
7711 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7712 !ST.hasUnpackedD16VMem()) {
7713 B.buildBitcast(DstReg, ResultRegs[0]);
7725 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7727 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7728 }
else if (ST.hasUnpackedD16VMem()) {
7730 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7734 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7738 for (
int I = 0;
I != NumElts; ++
I)
7745 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7746 B.buildBuildVector(DstReg, ResultRegs);
7750 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7751 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7756 if (Ty == V3I16 || Ty == V3F16) {
7758 if (ResultRegs.
size() == 1) {
7759 NewResultReg = ResultRegs[0];
7760 }
else if (ResultRegs.
size() == 2) {
7762 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7777 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7779 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7781 if (ResizeDst != DstReg)
7782 B.buildBitcast(DstReg, ResizeDst);
7786 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7787 B.buildConcatVectors(DstReg, ResultRegs);
7796 Register OrigDst =
MI.getOperand(0).getReg();
7798 LLT Ty =
B.getMRI()->getType(OrigDst);
7799 unsigned Size = Ty.getSizeInBits();
7801 bool HasMMO = !
MI.memoperands_empty();
7806 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7807 if (
Size % 32 != 0 && !IsSubwordLoad) {
7810 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7811 B.buildUndef(OrigDst);
7812 MI.eraseFromParent();
7817 if (IsSubwordLoad) {
7819 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7820 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7823 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7825 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7834 B.setInsertPt(
B.getMBB(),
MI);
7839 B.setInsertPt(
B.getMBB(),
MI);
7842 MI.setDesc(
B.getTII().get(
Opc));
7843 MI.removeOperand(1);
7849 const unsigned MemSize = (
Size + 7) / 8;
7850 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7857 MI.addMemOperand(MF, MMO);
7859 if (Dst != OrigDst) {
7860 MI.getOperand(0).setReg(Dst);
7861 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7862 B.buildTrunc(OrigDst, Dst);
7884 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7885 MI.removeOperand(0);
7896 if (!ST.hasTrapHandler() ||
7900 return ST.supportsGetDoorbellID() ?
7915 MI.eraseFromParent();
7927 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7936 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7938 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7942 MI.eraseFromParent();
7951 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7958 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7978 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7981 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7982 B.buildCopy(SGPR01, Temp);
7983 B.buildInstr(AMDGPU::S_TRAP)
7986 MI.eraseFromParent();
7997 B.buildCopy(SGPR01, LiveIn);
7998 B.buildInstr(AMDGPU::S_TRAP)
8002 MI.eraseFromParent();
8011 if (ST.hasPrivEnabledTrap2NopBug()) {
8012 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
8014 MI.eraseFromParent();
8018 B.buildInstr(AMDGPU::S_TRAP)
8020 MI.eraseFromParent();
8029 if (!ST.hasTrapHandler() ||
8033 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8036 B.buildInstr(AMDGPU::S_TRAP)
8040 MI.eraseFromParent();
8054 Register NodePtr =
MI.getOperand(2).getReg();
8055 Register RayExtent =
MI.getOperand(3).getReg();
8056 Register RayOrigin =
MI.getOperand(4).getReg();
8058 Register RayInvDir =
MI.getOperand(6).getReg();
8061 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8068 const unsigned NumVDataDwords = 4;
8069 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8070 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8072 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8074 const unsigned BaseOpcodes[2][2] = {
8075 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8076 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8077 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8081 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8082 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8083 : AMDGPU::MIMGEncGfx10NSA,
8084 NumVDataDwords, NumVAddrDwords);
8088 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8089 : AMDGPU::MIMGEncGfx10Default,
8090 NumVDataDwords, NumVAddrDwords);
8095 if (UseNSA && IsGFX11Plus) {
8096 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8097 auto SrcInt =
B.buildBitcast(V3I32, Src);
8098 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8099 auto Merged =
B.buildMergeLikeInstr(
8100 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8101 Ops.push_back(Merged.getReg(0));
8104 Ops.push_back(NodePtr);
8105 Ops.push_back(RayExtent);
8106 packLanes(RayOrigin);
8109 auto UnmergeRayDir =
8110 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8111 auto UnmergeRayInvDir =
8112 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8113 auto MergedDir =
B.buildMergeLikeInstr(
8116 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8117 UnmergeRayDir.getReg(0)}))
8120 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8121 UnmergeRayDir.getReg(1)}))
8124 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8125 UnmergeRayDir.getReg(2)}))
8127 Ops.push_back(MergedDir.getReg(0));
8130 packLanes(RayInvDir);
8134 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8135 Ops.push_back(Unmerge.getReg(0));
8136 Ops.push_back(Unmerge.getReg(1));
8138 Ops.push_back(NodePtr);
8140 Ops.push_back(RayExtent);
8142 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8143 auto SrcInt =
B.buildBitcast(V3I32, Src);
8144 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8145 Ops.push_back(Unmerge.getReg(0));
8146 Ops.push_back(Unmerge.getReg(1));
8147 Ops.push_back(Unmerge.getReg(2));
8150 packLanes(RayOrigin);
8152 auto UnmergeRayDir =
8153 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8154 auto UnmergeRayInvDir =
8155 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8159 B.buildMergeLikeInstr(R1,
8160 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8161 B.buildMergeLikeInstr(
8162 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8163 B.buildMergeLikeInstr(
8164 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8170 packLanes(RayInvDir);
8179 Ops.push_back(MergedOps);
8182 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8191 .addImm(IsA16 ? 1 : 0)
8194 MI.eraseFromParent();
8204 Register DstOrigin =
MI.getOperand(1).getReg();
8206 Register NodePtr =
MI.getOperand(4).getReg();
8207 Register RayExtent =
MI.getOperand(5).getReg();
8208 Register InstanceMask =
MI.getOperand(6).getReg();
8209 Register RayOrigin =
MI.getOperand(7).getReg();
8211 Register Offsets =
MI.getOperand(9).getReg();
8212 Register TDescr =
MI.getOperand(10).getReg();
8215 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8216 const unsigned NumVDataDwords = 10;
8217 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8219 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8220 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8221 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8224 auto RayExtentInstanceMaskVec =
8225 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8226 B.buildAnyExt(I32, InstanceMask)});
8228 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8229 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8235 .addUse(RayExtentInstanceMaskVec.getReg(0))
8242 MI.eraseFromParent();
8251 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8252 MI.eraseFromParent();
8259 if (!ST.hasArchitectedSGPRs())
8263 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8264 auto LSB =
B.buildConstant(I32, 25);
8265 auto Width =
B.buildConstant(I32, 5);
8266 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8267 MI.eraseFromParent();
8275 unsigned Width)
const {
8279 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8280 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8283 B.buildCopy(DstReg, Result);
8284 MI.eraseFromParent();
8304 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8308 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8311 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8312 MI.eraseFromParent();
8325 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8329 .addReg(Unmerge.getReg(0));
8333 .addReg(Unmerge.getReg(1));
8334 MI.eraseFromParent();
8346 case Intrinsic::sponentry:
8352 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8355 B.buildIntToPtr(DstReg, TmpReg);
8356 MI.eraseFromParent();
8358 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8360 B.buildFrameIndex(
MI.getOperand(0), FI);
8361 MI.eraseFromParent();
8364 case Intrinsic::amdgcn_if:
8365 case Intrinsic::amdgcn_else: {
8368 bool Negated =
false;
8385 std::swap(CondBrTarget, UncondBrTarget);
8387 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8388 B.buildCopy(NewUse,
Use);
8389 if (IntrID == Intrinsic::amdgcn_if) {
8390 B.buildInstr(AMDGPU::SI_IF)
8393 .addMBB(UncondBrTarget);
8395 B.buildInstr(AMDGPU::SI_ELSE)
8398 .addMBB(UncondBrTarget);
8407 B.buildBr(*CondBrTarget);
8410 MI.eraseFromParent();
8411 BrCond->eraseFromParent();
8422 case Intrinsic::amdgcn_loop: {
8425 bool Negated =
false;
8434 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8437 std::swap(CondBrTarget, UncondBrTarget);
8439 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8440 B.buildCopy(NewReg, Reg);
8441 B.buildInstr(AMDGPU::SI_LOOP).addUse(NewReg).addMBB(UncondBrTarget);
8446 B.buildBr(*CondBrTarget);
8448 MI.eraseFromParent();
8449 BrCond->eraseFromParent();
8455 case Intrinsic::amdgcn_wave_reduce_min:
8456 case Intrinsic::amdgcn_wave_reduce_umin:
8457 case Intrinsic::amdgcn_wave_reduce_fmin:
8458 case Intrinsic::amdgcn_wave_reduce_max:
8459 case Intrinsic::amdgcn_wave_reduce_umax:
8460 case Intrinsic::amdgcn_wave_reduce_fmax:
8461 case Intrinsic::amdgcn_wave_reduce_add:
8462 case Intrinsic::amdgcn_wave_reduce_fadd:
8463 case Intrinsic::amdgcn_wave_reduce_sub:
8464 case Intrinsic::amdgcn_wave_reduce_fsub:
8465 case Intrinsic::amdgcn_wave_reduce_and:
8466 case Intrinsic::amdgcn_wave_reduce_or:
8467 case Intrinsic::amdgcn_wave_reduce_xor: {
8472 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8473 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8474 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8475 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8476 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8477 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8478 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8479 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8480 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8487 .addUse(Ext.getReg(0))
8488 .addImm(
MI.getOperand(3).getImm());
8490 B.buildFPTrunc(DstReg, NewDst);
8492 B.buildTrunc(DstReg, NewDst);
8493 MI.eraseFromParent();
8496 case Intrinsic::amdgcn_make_buffer_rsrc:
8498 case Intrinsic::amdgcn_kernarg_segment_ptr:
8501 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8502 MI.eraseFromParent();
8508 case Intrinsic::amdgcn_implicitarg_ptr:
8510 case Intrinsic::amdgcn_workitem_id_x:
8513 case Intrinsic::amdgcn_workitem_id_y:
8516 case Intrinsic::amdgcn_workitem_id_z:
8519 case Intrinsic::amdgcn_workgroup_id_x:
8524 case Intrinsic::amdgcn_workgroup_id_y:
8529 case Intrinsic::amdgcn_workgroup_id_z:
8534 case Intrinsic::amdgcn_cluster_id_x:
8535 return ST.hasClusters() &&
8538 case Intrinsic::amdgcn_cluster_id_y:
8539 return ST.hasClusters() &&
8542 case Intrinsic::amdgcn_cluster_id_z:
8543 return ST.hasClusters() &&
8546 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8547 return ST.hasClusters() &&
8550 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8551 return ST.hasClusters() &&
8554 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8555 return ST.hasClusters() &&
8558 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8559 return ST.hasClusters() &&
8561 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8562 return ST.hasClusters() &&
8565 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8566 return ST.hasClusters() &&
8569 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8570 return ST.hasClusters() &&
8573 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8574 return ST.hasClusters() &&
8578 case Intrinsic::amdgcn_wave_id:
8580 case Intrinsic::amdgcn_lds_kernel_id:
8583 case Intrinsic::amdgcn_dispatch_ptr:
8586 case Intrinsic::amdgcn_queue_ptr:
8589 case Intrinsic::amdgcn_implicit_buffer_ptr:
8592 case Intrinsic::amdgcn_dispatch_id:
8595 case Intrinsic::r600_read_ngroups_x:
8599 case Intrinsic::r600_read_ngroups_y:
8602 case Intrinsic::r600_read_ngroups_z:
8605 case Intrinsic::r600_read_local_size_x:
8608 case Intrinsic::r600_read_local_size_y:
8612 case Intrinsic::r600_read_local_size_z:
8615 case Intrinsic::amdgcn_fdiv_fast:
8617 case Intrinsic::amdgcn_is_shared:
8619 case Intrinsic::amdgcn_is_private:
8621 case Intrinsic::amdgcn_wavefrontsize: {
8622 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8623 MI.eraseFromParent();
8626 case Intrinsic::amdgcn_s_buffer_load:
8627 case Intrinsic::amdgcn_ptr_s_buffer_load:
8629 case Intrinsic::amdgcn_raw_buffer_store:
8630 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8631 case Intrinsic::amdgcn_struct_buffer_store:
8632 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8634 case Intrinsic::amdgcn_raw_buffer_store_format:
8635 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8636 case Intrinsic::amdgcn_struct_buffer_store_format:
8637 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8639 case Intrinsic::amdgcn_raw_tbuffer_store:
8640 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8641 case Intrinsic::amdgcn_struct_tbuffer_store:
8642 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8644 case Intrinsic::amdgcn_raw_buffer_load:
8645 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8646 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8647 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8648 case Intrinsic::amdgcn_struct_buffer_load:
8649 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8650 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8651 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8653 case Intrinsic::amdgcn_raw_buffer_load_format:
8654 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8655 case Intrinsic::amdgcn_struct_buffer_load_format:
8656 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8658 case Intrinsic::amdgcn_raw_tbuffer_load:
8659 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8660 case Intrinsic::amdgcn_struct_tbuffer_load:
8661 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8663 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8664 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8665 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8666 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8667 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8668 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8669 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8670 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8671 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8672 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8673 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8674 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8675 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8676 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8677 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8678 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8679 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8680 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8681 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8682 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8683 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8684 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8685 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8686 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8687 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8688 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8689 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8690 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8691 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8692 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8693 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8694 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8695 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8696 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8697 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8698 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8699 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8700 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8701 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8702 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8703 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8704 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8705 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8706 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8707 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8708 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8709 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8710 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8711 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8712 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8713 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8714 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8715 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8716 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8717 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8718 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8719 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8720 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8721 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8722 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8723 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8724 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8725 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8726 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8727 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8728 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8729 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8730 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8731 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8732 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8733 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8734 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8736 case Intrinsic::amdgcn_rsq_clamp:
8738 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8740 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8741 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8743 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8744 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8745 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8746 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8747 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8748 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8749 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8750 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8754 if (IndexArgTy != I64) {
8755 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8756 :
B.buildAnyExt(I64, Index);
8757 MI.getOperand(5).setReg(NewIndex.getReg(0));
8761 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8762 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8763 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8764 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8765 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8766 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8767 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8768 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8771 if (MRI.
getType(Index) != I32)
8772 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8775 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8776 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8777 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8778 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8779 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8780 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8781 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8782 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8783 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8785 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8789 if (IndexArgTy != IdxTy) {
8790 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8791 :
B.buildAnyExt(IdxTy, Index);
8792 MI.getOperand(7).setReg(NewIndex.getReg(0));
8797 case Intrinsic::amdgcn_fmed3: {
8803 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8804 MI.removeOperand(1);
8808 case Intrinsic::amdgcn_readlane:
8809 case Intrinsic::amdgcn_writelane:
8810 case Intrinsic::amdgcn_readfirstlane:
8811 case Intrinsic::amdgcn_permlane16:
8812 case Intrinsic::amdgcn_permlanex16:
8813 case Intrinsic::amdgcn_permlane64:
8814 case Intrinsic::amdgcn_set_inactive:
8815 case Intrinsic::amdgcn_set_inactive_chain_arg:
8816 case Intrinsic::amdgcn_mov_dpp8:
8817 case Intrinsic::amdgcn_update_dpp:
8818 case Intrinsic::amdgcn_permlane_bcast:
8819 case Intrinsic::amdgcn_permlane_up:
8820 case Intrinsic::amdgcn_permlane_down:
8821 case Intrinsic::amdgcn_permlane_xor:
8823 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8825 case Intrinsic::amdgcn_dead: {
8829 MI.eraseFromParent();
8832 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8833 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8834 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8835 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8836 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8837 MI.eraseFromParent();
8839 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8840 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8841 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8842 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8843 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8844 MI.eraseFromParent();
8846 case Intrinsic::amdgcn_av_load_b128:
8847 case Intrinsic::amdgcn_av_store_b128: {
8848 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8849 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8850 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8852 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8853 **
MI.memoperands_begin());
8854 MI.eraseFromParent();
8857 case Intrinsic::amdgcn_flat_load_monitor_b32:
8858 case Intrinsic::amdgcn_flat_load_monitor_b64:
8859 case Intrinsic::amdgcn_flat_load_monitor_b128:
8860 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8861 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8862 .add(
MI.getOperand(0))
8863 .add(
MI.getOperand(2))
8864 .addMemOperand(*
MI.memoperands_begin());
8865 MI.eraseFromParent();
8867 case Intrinsic::amdgcn_global_load_monitor_b32:
8868 case Intrinsic::amdgcn_global_load_monitor_b64:
8869 case Intrinsic::amdgcn_global_load_monitor_b128:
8870 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8871 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8872 .add(
MI.getOperand(0))
8873 .add(
MI.getOperand(2))
8874 .addMemOperand(*
MI.memoperands_begin());
8875 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 getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, 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 legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool 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)
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat 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.
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 & 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...
unsigned getPointerSizeInBits(unsigned AS) const
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ 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.