37#include "llvm/IR/IntrinsicsAMDGPU.h"
38#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
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};
730 const std::initializer_list<LLT> FPTypesPK16_64 = {
F32,
F64,
F16,
V2F16,
733 const LLT MinExtendedFPTy = ST.has16BitInsts() ?
F16 :
F32;
761 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
763 if (ST.hasAnyPackedU64Ops()) {
766 .clampMaxNumElementsStrict(0,
S16, 2)
772 }
else if (ST.hasScalarAddSub64()) {
775 .clampMaxNumElementsStrict(0,
S16, 2)
783 .clampMaxNumElementsStrict(0,
S16, 2)
790 if (ST.hasScalarSMulU64()) {
793 .clampMaxNumElementsStrict(0,
S16, 2)
801 .clampMaxNumElementsStrict(0,
S16, 2)
811 .minScalarOrElt(0,
S16)
816 }
else if (ST.has16BitInsts()) {
850 .widenScalarToNextMultipleOf(0, 32)
860 if (ST.hasMad64_32())
865 if (ST.hasIntClamp()) {
888 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
898 if (ST.hasVOP3PInsts()) {
900 .clampMaxNumElements(0,
S8, 2)
921 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
937 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
978 auto &FCanonicalizeActions =
980 auto &StrictFPOpActions =
987 if (ST.has16BitInsts()) {
988 if (ST.hasVOP3PInsts()) {
990 FCanonicalizeActions.legalFor({
F16,
V2F16});
991 StrictFPOpActions.legalFor({
F16,
V2F16});
993 FPOpActions.legalFor({
F16});
994 FCanonicalizeActions.legalFor({
F16});
995 StrictFPOpActions.legalFor({
F16});
998 TrigActions.customFor({
F16});
999 FDIVActions.customFor({
F16});
1005 if (ST.hasAnyPackedFP32Ops()) {
1006 FPOpActions.legalFor({
V2F32});
1007 FCanonicalizeActions.legalFor({
V2F32});
1008 StrictFPOpActions.legalFor({
V2F32});
1009 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1010 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1011 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1014 if (ST.hasAnyPackedFP64Ops()) {
1015 FPOpActions.legalFor({
V2F64});
1016 FCanonicalizeActions.legalFor({
V2F64});
1017 StrictFPOpActions.legalFor({
V2F64});
1018 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1019 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1020 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1023 auto &MinNumMaxNumIeee =
1026 if (ST.hasVOP3PInsts()) {
1027 MinNumMaxNumIeee.legalFor(FPTypesPK16)
1029 .clampMaxNumElements(0,
F16, 2)
1031 }
else if (ST.has16BitInsts()) {
1032 MinNumMaxNumIeee.legalFor(FPTypes16).scalarize(0);
1034 MinNumMaxNumIeee.legalFor(FPTypesBase).scalarize(0);
1038 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1040 if (ST.hasAnyPackedFP64Ops()) {
1041 MinNumMaxNum.customFor(FPTypesPK16_64)
1043 .clampMaxNumElements(0,
F16, 2)
1044 .clampMaxNumElements(0,
F64, 2)
1046 }
else if (ST.hasVOP3PInsts()) {
1047 MinNumMaxNum.customFor(FPTypesPK16)
1049 .clampMaxNumElements(0,
F16, 2)
1051 }
else if (ST.has16BitInsts()) {
1052 MinNumMaxNum.customFor(FPTypes16).scalarize(0);
1054 MinNumMaxNum.customFor(FPTypesBase).scalarize(0);
1057 if (!ST.has16BitInsts()) {
1058 MinNumMaxNumIeee.minScalar(0,
F32);
1059 MinNumMaxNum.minScalar(0,
F32);
1062 if (ST.hasVOP3PInsts()) {
1063 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1064 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1065 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1073 if (!ST.has16BitInsts()) {
1084 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1087 if (ST.hasAnyPackedFP32Ops())
1091 if (ST.has16BitInsts()) {
1094 .legalFor(ST.hasBF16TransInsts(), {BF16})
1104 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1126 if (ST.hasFractBug()) {
1140 .legalFor({{
F32, I32}, {
F64, I32}})
1160 if (ST.hasCvtPkF16F32Inst()) {
1162 .clampMaxNumElements(0,
F16, 2);
1175 if (ST.has16BitInsts()) {
1189 if (ST.hasAnyPackedFP32Ops())
1197 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1198 FMad.customFor({
F32,
F16});
1199 else if (ST.hasMadMacF32Insts())
1200 FMad.customFor({
F32});
1201 else if (ST.hasMadF16())
1202 FMad.customFor({
F16});
1207 if (ST.has16BitInsts()) {
1210 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1218 .clampMaxNumElements(0,
S16, 2)
1234 .legalFor({{
F32, I32}, {
F64, I32}})
1238 if (ST.has16BitInsts())
1246 .legalFor({{I32,
F32}, {I32,
F64}})
1247 .customFor({{I64,
F32}, {I64,
F64}})
1250 if (ST.has16BitInsts())
1259 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1260 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1261 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1265 if (
ST.has16BitInsts())
1268 if (
ST.hasVCvtPkIU16F32())
1278 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1279 .clampScalar(0, I16, I64)
1283 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1289 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1293 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1294 .clampScalar(0, I16, I64)
1298 auto &RoundingActions = getActionDefinitionsBuilder(
1299 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1300 if (
ST.has16BitInsts())
1308 if (!
ST.has16BitInsts())
1311 getActionDefinitionsBuilder(G_PTR_ADD)
1317 getActionDefinitionsBuilder(G_PTRMASK)
1319 .scalarSameSizeAs(1, 0)
1323 getActionDefinitionsBuilder(G_ICMP)
1335 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1336 .legalForCartesianProduct(
1337 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1338 if (
ST.has16BitInsts()) {
1339 CmpBuilder.legalFor({{
S1,
S16}});
1348 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1351 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1352 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1354 if (
ST.hasSALUFloatInsts())
1355 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1357 FCmpBuilder.widenScalarToNextPow2(1).minScalar(1,
F32).scalarize(0);
1360 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1361 if (
ST.has16BitInsts())
1362 ExpOps.customFor({{
F32}, {
F16}});
1364 ExpOps.customFor({
F32});
1365 ExpOps.clampScalar(0, MinExtendedFPTy,
F32).scalarize(0);
1367 getActionDefinitionsBuilder(G_FPOWI)
1368 .clampScalar(0, MinExtendedFPTy,
F32)
1371 getActionDefinitionsBuilder(G_FLOG2)
1372 .legalFor(
ST.has16BitInsts(), {F16})
1373 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1379 getActionDefinitionsBuilder(G_FEXP2)
1380 .legalFor(
ST.has16BitInsts(), {F16})
1381 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1387 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1391 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1396 getActionDefinitionsBuilder(G_CTPOP)
1398 .clampScalar(0,
S32,
S32)
1399 .widenScalarToNextPow2(1, 32)
1400 .clampScalar(1,
S32,
S64)
1402 .widenScalarToNextPow2(0, 32);
1405 if (
ST.has16BitInsts())
1406 getActionDefinitionsBuilder(G_IS_FPCLASS)
1407 .legalForCartesianProduct({
I1}, FPTypes16)
1408 .widenScalarToNextPow2(1)
1412 getActionDefinitionsBuilder(G_IS_FPCLASS)
1413 .legalForCartesianProduct({
I1}, FPTypesBase)
1414 .lowerFor({
I1,
F16})
1415 .widenScalarToNextPow2(1)
1422 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1424 .clampScalar(0,
S32,
S32)
1425 .clampScalar(1,
S32,
S64)
1426 .widenScalarToNextPow2(0, 32)
1427 .widenScalarToNextPow2(1, 32)
1431 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1434 .clampScalar(0,
S32,
S32)
1435 .clampScalar(1,
S32,
S64)
1437 .widenScalarToNextPow2(0, 32)
1438 .widenScalarToNextPow2(1, 32);
1440 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1442 .clampScalar(0,
S32,
S32)
1443 .clampScalar(1,
S32,
S64)
1445 .widenScalarToNextPow2(0, 32)
1446 .widenScalarToNextPow2(1, 32);
1448 getActionDefinitionsBuilder(G_CTLS)
1451 .clampScalar(0,
S32,
S32)
1452 .clampScalar(1,
S32,
S32);
1456 getActionDefinitionsBuilder(G_BITREVERSE)
1458 .clampScalar(0,
S32,
S64)
1460 .widenScalarToNextPow2(0);
1462 if (
ST.has16BitInsts()) {
1463 getActionDefinitionsBuilder(G_BSWAP)
1465 .clampMaxNumElementsStrict(0,
S16, 2)
1468 .widenScalarToNextPow2(0)
1469 .clampScalar(0,
S16,
S32)
1472 if (
ST.hasVOP3PInsts()) {
1473 getActionDefinitionsBuilder(G_ABS)
1475 .clampMaxNumElements(0,
S16, 2)
1477 .widenScalarToNextPow2(0)
1480 if (
ST.hasMinMaxI64Insts()) {
1481 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1483 .clampMaxNumElements(0,
S16, 2)
1485 .widenScalarToNextPow2(0)
1489 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1491 .clampMaxNumElements(0,
S16, 2)
1493 .widenScalarToNextPow2(0)
1498 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1500 .widenScalarToNextPow2(0)
1507 getActionDefinitionsBuilder(G_BSWAP)
1512 .widenScalarToNextPow2(0)
1517 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1520 .widenScalarToNextPow2(0)
1525 getActionDefinitionsBuilder(G_INTTOPTR)
1527 .legalForCartesianProduct(AddrSpaces64, {
S64})
1528 .legalForCartesianProduct(AddrSpaces32, {
S32})
1541 getActionDefinitionsBuilder(G_PTRTOINT)
1543 .legalForCartesianProduct(AddrSpaces64, {
S64})
1544 .legalForCartesianProduct(AddrSpaces32, {
S32})
1557 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1561 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1562 bool IsLoad) ->
bool {
1566 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1580 unsigned NumRegs = (MemSize + 31) / 32;
1582 if (!
ST.hasDwordx3LoadStores())
1593 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1594 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1595 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1601 for (
unsigned Op : {G_LOAD, G_STORE}) {
1602 const bool IsStore =
Op == G_STORE;
1604 auto &Actions = getActionDefinitionsBuilder(
Op);
1607 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1610 {
S64, GlobalPtr,
S64, GlobalAlign32},
1613 {
S32, GlobalPtr,
S8, GlobalAlign8},
1614 {
S32, GlobalPtr,
S16, GlobalAlign16},
1616 {
S32, LocalPtr,
S32, 32},
1617 {
S64, LocalPtr,
S64, 32},
1619 {
S32, LocalPtr,
S8, 8},
1620 {
S32, LocalPtr,
S16, 16},
1623 {
S32, PrivatePtr,
S32, 32},
1624 {
S32, PrivatePtr,
S8, 8},
1625 {
S32, PrivatePtr,
S16, 16},
1628 {
S32, ConstantPtr,
S32, GlobalAlign32},
1631 {
S64, ConstantPtr,
S64, GlobalAlign32},
1632 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1634 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1635 {{S16, GlobalPtr, S8, GlobalAlign8},
1636 {S16, GlobalPtr, S16, GlobalAlign16},
1637 {S16, LocalPtr, S8, 8},
1638 {S16, LocalPtr, S16, 16},
1639 {S16, PrivatePtr, S8, 8},
1640 {S16, PrivatePtr, S16, 16}});
1650 Actions.unsupportedIf(
1651 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1665 Actions.customIf(
typeIs(1, Constant32Ptr));
1691 return !Query.
Types[0].isVector() &&
1692 needToSplitMemOp(Query,
Op == G_LOAD);
1694 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1699 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1702 if (DstSize > MemSize)
1708 if (MemSize > MaxSize)
1716 return Query.
Types[0].isVector() &&
1717 needToSplitMemOp(Query,
Op == G_LOAD);
1719 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1733 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1734 if (MemSize > MaxSize) {
1738 if (MaxSize % EltSize == 0) {
1744 unsigned NumPieces = MemSize / MaxSize;
1748 if (NumPieces == 1 || NumPieces >= NumElts ||
1749 NumElts % NumPieces != 0)
1750 return std::pair(0, EltTy);
1758 return std::pair(0, EltTy);
1773 return std::pair(0, EltTy);
1778 .widenScalarToNextPow2(0)
1785 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1786 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1787 {
S32, GlobalPtr,
S16, 2 * 8},
1788 {
S32, LocalPtr,
S8, 8},
1789 {
S32, LocalPtr,
S16, 16},
1790 {
S32, PrivatePtr,
S8, 8},
1791 {
S32, PrivatePtr,
S16, 16},
1792 {
S32, ConstantPtr,
S8, 8},
1793 {
S32, ConstantPtr,
S16, 2 * 8}})
1794 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1795 {{S16, GlobalPtr, S8, GlobalAlign8},
1796 {S16, LocalPtr, S8, GlobalAlign8},
1797 {S16, PrivatePtr, S8, GlobalAlign8},
1798 {S16, ConstantPtr, S8, GlobalAlign8}})
1803 if (
ST.hasFlatAddressSpace()) {
1804 ExtLoads.legalForTypesWithMemDesc(
1805 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1807 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1808 {{S16, FlatPtr, S8, GlobalAlign8}});
1816 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1818 ExtLoads.narrowScalarIf(
1825 ExtLoads.clampScalar(0,
S32,
S32)
1826 .widenScalarToNextPow2(0)
1829 auto &Atomics = getActionDefinitionsBuilder(
1830 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1831 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1832 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1833 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1834 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1835 {
S64, GlobalPtr}, {
S64, LocalPtr},
1836 {
S32, RegionPtr}, {
S64, RegionPtr}});
1837 if (
ST.hasFlatAddressSpace()) {
1838 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1842 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1843 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1844 if (
ST.hasFlatAddressSpace()) {
1845 Atomics32.legalFor({{
S32, FlatPtr}});
1849 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1850 if (
ST.hasLDSFPAtomicAddF32()) {
1851 Atomic.legalFor({{
F32, LocalPtr}, {
F32, RegionPtr}});
1852 if (
ST.hasLdsAtomicAddF64())
1853 Atomic.legalFor({{
F64, LocalPtr}});
1854 if (
ST.hasAtomicDsPkAdd16Insts())
1855 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1857 if (
ST.hasAtomicFaddInsts())
1858 Atomic.legalFor({{
F32, GlobalPtr}});
1859 if (
ST.hasFlatAtomicFaddF32Inst())
1860 Atomic.legalFor({{
F32, FlatPtr}});
1862 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1866 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1869 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1870 ST.hasAtomicBufferGlobalPkAddF16Insts())
1871 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1872 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1873 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1874 if (
ST.hasAtomicFlatPkAdd16Insts())
1875 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1880 auto &AtomicFMinFMax =
1881 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1882 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1884 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1885 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1886 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1887 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1888 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1889 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1890 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1891 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1895 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1896 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1897 {
S32, FlatPtr}, {
S64, FlatPtr}})
1898 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1899 {
S32, RegionPtr}, {
S64, RegionPtr}});
1903 getActionDefinitionsBuilder(G_SELECT)
1905 LocalPtr, FlatPtr, PrivatePtr,
1909 .clampScalar(0,
S16,
S64)
1913 .clampMaxNumElements(0,
S32, 2)
1914 .clampMaxNumElements(0, LocalPtr, 2)
1915 .clampMaxNumElements(0, PrivatePtr, 2)
1917 .widenScalarToNextPow2(0)
1922 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1924 if (
ST.has16BitInsts()) {
1925 if (
ST.hasVOP3PInsts()) {
1927 .clampMaxNumElements(0,
S16, 2);
1929 Shifts.legalFor({{
S16,
S16}});
1932 Shifts.widenScalarIf(
1937 const LLT AmountTy = Query.
Types[1];
1943 Shifts.clampScalar(1,
S32,
S32);
1944 Shifts.widenScalarToNextPow2(0, 16);
1945 Shifts.clampScalar(0,
S16,
S64);
1947 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1955 Shifts.clampScalar(1,
S32,
S32);
1956 Shifts.widenScalarToNextPow2(0, 32);
1957 Shifts.clampScalar(0,
S32,
S64);
1959 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1964 Shifts.scalarize(0);
1966 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1967 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1968 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1969 unsigned IdxTypeIdx = 2;
1971 getActionDefinitionsBuilder(
Op)
1973 const LLT EltTy = Query.
Types[EltTypeIdx];
1974 const LLT VecTy = Query.
Types[VecTypeIdx];
1975 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1977 const bool isLegalVecType =
1987 return (EltSize == 32 || EltSize == 64) &&
2003 const LLT EltTy = Query.
Types[EltTypeIdx];
2004 const LLT VecTy = Query.
Types[VecTypeIdx];
2008 const unsigned TargetEltSize =
2009 DstEltSize % 64 == 0 ? 64 : 32;
2010 return std::pair(VecTypeIdx,
2014 .clampScalar(EltTypeIdx,
S32,
S64)
2015 .clampScalar(VecTypeIdx,
S32,
S64)
2016 .clampScalar(IdxTypeIdx,
S32,
S32)
2017 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2026 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2028 const LLT &EltTy = Query.
Types[1].getElementType();
2029 return Query.
Types[0] != EltTy;
2032 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2033 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2034 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2035 getActionDefinitionsBuilder(
Op)
2038 const LLT BigTy = Query.
Types[BigTyIdx];
2044 const LLT LitTy = Query.
Types[LitTyIdx];
2049 .widenScalarToNextPow2(BigTyIdx, 32)
2057 const LLT BigTy = Query.
Types[BigTyIdx];
2058 const LLT LitTy = Query.
Types[LitTyIdx];
2066 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2076 if (
ST.hasScalarPackInsts()) {
2079 .minScalarOrElt(0,
S16)
2082 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2086 BuildVector.customFor({
V2S16,
S16});
2087 BuildVector.minScalarOrElt(0,
S32);
2089 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2097 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2099 .clampMaxNumElements(0,
S32, 32)
2100 .clampMaxNumElements(1,
S16, 2)
2101 .clampMaxNumElements(0,
S16, 64);
2103 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2106 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2107 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2108 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2110 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2111 const LLT Ty = Query.
Types[TypeIdx];
2123 getActionDefinitionsBuilder(
Op)
2127 const LLT BigTy = Query.
Types[BigTyIdx];
2133 .widenScalarToNextPow2(LitTyIdx, 16)
2142 .clampScalar(LitTyIdx,
S32,
S512)
2143 .widenScalarToNextPow2(LitTyIdx, 32)
2147 return notValidElt(Query, LitTyIdx);
2152 return notValidElt(Query, BigTyIdx);
2157 if (
Op == G_MERGE_VALUES) {
2158 Builder.widenScalarIf(
2161 const LLT Ty = Query.
Types[LitTyIdx];
2167 Builder.widenScalarIf(
2169 const LLT Ty = Query.
Types[BigTyIdx];
2175 const LLT &Ty = Query.
Types[BigTyIdx];
2177 if (NewSizeInBits >= 256) {
2179 if (RoundedTo < NewSizeInBits)
2180 NewSizeInBits = RoundedTo;
2182 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2191 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2192 .legalFor({{
S32}, {
S64}})
2193 .clampScalar(0,
S32,
S64);
2195 if (
ST.hasVOP3PInsts()) {
2196 SextInReg.lowerFor({{
V2S16}})
2200 .clampMaxNumElementsStrict(0,
S16, 2);
2201 }
else if (
ST.has16BitInsts()) {
2202 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2206 SextInReg.lowerFor({{
S32}, {
S64}});
2211 .clampScalar(0,
S32,
S64)
2214 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2218 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2219 FSHRActionDefs.legalFor({{
S32,
S32}})
2220 .clampMaxNumElementsStrict(0,
S16, 2);
2221 if (
ST.hasVOP3PInsts())
2223 FSHRActionDefs.scalarize(0).lower();
2225 if (
ST.hasVOP3PInsts()) {
2226 getActionDefinitionsBuilder(G_FSHL)
2228 .clampMaxNumElementsStrict(0,
S16, 2)
2232 getActionDefinitionsBuilder(G_FSHL)
2237 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2240 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2242 getActionDefinitionsBuilder(G_FENCE)
2245 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2250 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2252 .clampScalar(1,
S32,
S32)
2253 .clampScalar(0,
S32,
S64)
2254 .widenScalarToNextPow2(0)
2257 getActionDefinitionsBuilder(
2261 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2262 G_READ_REGISTER, G_WRITE_REGISTER,
2267 if (
ST.hasIEEEMinimumMaximumInsts()) {
2268 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2269 .legalFor(FPTypesPK16)
2270 .clampMaxNumElements(0,
F16, 2)
2272 }
else if (
ST.hasVOP3PInsts()) {
2273 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2275 .clampMaxNumElementsStrict(0,
F16, 2)
2279 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2281 .clampScalar(0,
F32,
F64)
2285 getActionDefinitionsBuilder(
2286 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2289 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2291 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2292 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2293 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2296 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2298 getActionDefinitionsBuilder(
2299 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2300 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2301 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2302 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2307 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2308 G_INTRINSIC_CONVERGENT,
2309 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2321 switch (
MI.getOpcode()) {
2322 case TargetOpcode::G_ADDRSPACE_CAST:
2324 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2326 case TargetOpcode::G_FCEIL:
2328 case TargetOpcode::G_FREM:
2330 case TargetOpcode::G_INTRINSIC_TRUNC:
2332 case TargetOpcode::G_SITOFP:
2334 case TargetOpcode::G_UITOFP:
2336 case TargetOpcode::G_FPTOSI:
2338 case TargetOpcode::G_FPTOUI:
2340 case TargetOpcode::G_FMINNUM:
2341 case TargetOpcode::G_FMAXNUM:
2342 case TargetOpcode::G_FMINIMUMNUM:
2343 case TargetOpcode::G_FMAXIMUMNUM:
2345 case TargetOpcode::G_EXTRACT:
2347 case TargetOpcode::G_INSERT:
2349 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2351 case TargetOpcode::G_INSERT_VECTOR_ELT:
2353 case TargetOpcode::G_FSIN:
2354 case TargetOpcode::G_FCOS:
2356 case TargetOpcode::G_GLOBAL_VALUE:
2358 case TargetOpcode::G_LOAD:
2359 case TargetOpcode::G_SEXTLOAD:
2360 case TargetOpcode::G_ZEXTLOAD:
2362 case TargetOpcode::G_STORE:
2364 case TargetOpcode::G_FMAD:
2366 case TargetOpcode::G_FDIV:
2368 case TargetOpcode::G_FFREXP:
2370 case TargetOpcode::G_FSQRT:
2372 case TargetOpcode::G_UDIV:
2373 case TargetOpcode::G_UREM:
2374 case TargetOpcode::G_UDIVREM:
2376 case TargetOpcode::G_SDIV:
2377 case TargetOpcode::G_SREM:
2378 case TargetOpcode::G_SDIVREM:
2380 case TargetOpcode::G_ATOMIC_CMPXCHG:
2382 case TargetOpcode::G_FLOG2:
2384 case TargetOpcode::G_FLOG:
2385 case TargetOpcode::G_FLOG10:
2387 case TargetOpcode::G_FEXP2:
2389 case TargetOpcode::G_FEXP:
2390 case TargetOpcode::G_FEXP10:
2392 case TargetOpcode::G_FPOW:
2394 case TargetOpcode::G_FFLOOR:
2396 case TargetOpcode::G_BUILD_VECTOR:
2397 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2399 case TargetOpcode::G_MUL:
2401 case TargetOpcode::G_CTLZ:
2402 case TargetOpcode::G_CTTZ:
2404 case TargetOpcode::G_CTLS:
2406 case TargetOpcode::G_CTLZ_ZERO_POISON:
2408 case TargetOpcode::G_STACKSAVE:
2410 case TargetOpcode::G_GET_FPENV:
2412 case TargetOpcode::G_SET_FPENV:
2414 case TargetOpcode::G_TRAP:
2416 case TargetOpcode::G_DEBUGTRAP:
2436 if (ST.hasApertureRegs()) {
2441 ? AMDGPU::SRC_SHARED_BASE
2442 : AMDGPU::SRC_PRIVATE_BASE;
2443 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2444 !ST.hasGloballyAddressableScratch()) &&
2445 "Cannot use src_private_base with globally addressable scratch!");
2448 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2449 return B.buildUnmerge(I32, Dst).getReg(1);
2464 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2480 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2483 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2505 B.buildObjectPtrOffset(
2508 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2516 switch (Def->getOpcode()) {
2517 case AMDGPU::G_FRAME_INDEX:
2518 case AMDGPU::G_GLOBAL_VALUE:
2519 case AMDGPU::G_BLOCK_ADDR:
2521 case AMDGPU::G_CONSTANT: {
2522 const ConstantInt *CI = Def->getOperand(1).getCImm();
2539 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2541 Intrinsic::amdgcn_addrspacecast_nonnull));
2547 :
MI.getOperand(1).getReg();
2551 unsigned SrcAS = SrcTy.getAddressSpace();
2561 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2568 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2570 ST.hasGloballyAddressableScratch()) {
2573 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2575 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2576 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2578 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2579 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2580 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2584 return B.buildExtract(Dst, Src, 0).getReg(0);
2590 castFlatToLocalOrPrivate(Dst);
2591 MI.eraseFromParent();
2597 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2598 auto FlatNull =
B.buildConstant(SrcTy, 0);
2601 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2605 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2607 MI.eraseFromParent();
2614 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2617 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2620 ST.hasGloballyAddressableScratch()) {
2624 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2625 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2629 if (ST.isWave64()) {
2630 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2636 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2637 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2639 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2643 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2644 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2646 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2647 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2656 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2662 castLocalOrPrivateToFlat(Dst);
2663 MI.eraseFromParent();
2667 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2674 SegmentNull.getReg(0));
2676 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2678 MI.eraseFromParent();
2683 SrcTy.getSizeInBits() == 64) {
2685 B.buildExtract(Dst, Src, 0);
2686 MI.eraseFromParent();
2693 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2694 auto PtrLo =
B.buildPtrToInt(I32, Src);
2695 if (AddrHiVal == 0) {
2696 auto Zext =
B.buildZExt(I64, PtrLo);
2697 B.buildIntToPtr(Dst, Zext);
2699 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2700 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2703 MI.eraseFromParent();
2710 MI.eraseFromParent();
2719 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2724 auto C1 =
B.buildFConstant(Ty, C1Val);
2725 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2728 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2729 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2731 auto C2 =
B.buildFConstant(Ty, C2Val);
2732 auto Fabs =
B.buildFAbs(Ty, Src);
2735 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2736 MI.eraseFromParent();
2753 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2755 const auto Zero =
B.buildFConstant(
F64, 0.0);
2756 const auto One =
B.buildFConstant(
F64, 1.0);
2759 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2760 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2763 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2764 MI.eraseFromParent();
2772 Register Src0Reg =
MI.getOperand(1).getReg();
2773 Register Src1Reg =
MI.getOperand(2).getReg();
2774 auto Flags =
MI.getFlags();
2777 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2778 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2779 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2780 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2781 MI.eraseFromParent();
2787 const unsigned FractBits = 52;
2788 const unsigned ExpBits = 11;
2791 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2792 auto Const1 =
B.buildConstant(I32, ExpBits);
2794 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2796 .addUse(Const0.getReg(0))
2797 .addUse(Const1.getReg(0));
2799 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2812 auto SrcInt =
B.buildBitcast(I64, Src);
2815 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2822 const unsigned FractBits = 52;
2825 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2826 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2828 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2830 const auto Zero32 =
B.buildConstant(I32, 0);
2833 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2835 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2836 auto Not =
B.buildNot(I64, Shr);
2837 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2838 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2843 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2844 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2845 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2846 MI.eraseFromParent();
2862 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2863 auto ThirtyTwo =
B.buildConstant(I32, 32);
2866 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2867 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2869 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2870 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2873 B.buildFAdd(Dst, LdExp, CvtLo);
2874 MI.eraseFromParent();
2880 auto One =
B.buildConstant(I32, 1);
2884 auto ThirtyOne =
B.buildConstant(I32, 31);
2885 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2886 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2887 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2888 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2889 .addUse(Unmerge.getReg(1));
2890 auto LS2 =
B.buildSub(I32, LS, One);
2891 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2893 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2894 auto Norm =
B.buildShl(I64, Src, ShAmt);
2895 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2896 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2897 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2898 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2899 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2900 B.buildFLdexp(Dst, FVal, Scale);
2901 MI.eraseFromParent();
2921 unsigned Flags =
MI.getFlags();
2932 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2940 auto SrcInt =
B.buildBitcast(I32, Src);
2941 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2942 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2946 K0 =
B.buildFConstant(
2948 K1 =
B.buildFConstant(
2951 K0 =
B.buildFConstant(
2953 K1 =
B.buildFConstant(
2957 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2958 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2959 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2961 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2962 :
B.buildFPTOUI(I32, FloorMul);
2963 auto Lo =
B.buildFPTOUI(I32, Fma);
2967 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2969 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2972 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2973 MI.eraseFromParent();
3005 unsigned StartIdx =
Offset / 32;
3009 if (DstCount == 1) {
3011 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3016 for (
unsigned I = 0;
I < DstCount; ++
I)
3017 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3018 B.buildMergeLikeInstr(DstReg, MergeVec);
3021 MI.eraseFromParent();
3031 Register InsertSrc =
MI.getOperand(2).getReg();
3040 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3044 unsigned DstCount = DstSize / 32;
3045 unsigned InsertCount = InsertSize / 32;
3046 unsigned StartIdx =
Offset / 32;
3048 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3051 for (
unsigned I = 0;
I < StartIdx; ++
I)
3054 if (InsertCount == 1) {
3058 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3061 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3062 for (
unsigned I = 0;
I < InsertCount; ++
I)
3066 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3069 B.buildMergeLikeInstr(DstReg, MergeVec);
3071 MI.eraseFromParent();
3098 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3099 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3100 B.buildIntToPtr(Dst, IntElt);
3102 MI.eraseFromParent();
3109 std::optional<ValueAndVReg> MaybeIdxVal =
3113 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3116 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3117 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3122 MI.eraseFromParent();
3151 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3152 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3153 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3155 B.buildIntToPtr(Dst, IntVecDest);
3156 MI.eraseFromParent();
3163 std::optional<ValueAndVReg> MaybeIdxVal =
3168 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3171 if (IdxVal < NumElts) {
3173 for (
unsigned i = 0; i < NumElts; ++i)
3175 B.buildUnmerge(SrcRegs, Vec);
3177 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3178 B.buildMergeLikeInstr(Dst, SrcRegs);
3183 MI.eraseFromParent();
3194 unsigned Flags =
MI.getFlags();
3198 if (ST.hasTrigReducedRange()) {
3199 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3200 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3201 .addUse(MulVal.getReg(0))
3205 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3208 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3212 MI.eraseFromParent();
3220 unsigned GAFlags)
const {
3249 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3251 if (ST.has64BitLiterals()) {
3255 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3259 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3268 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3269 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3272 B.buildExtract(DstReg, PCReg, 0);
3282 if (RequiresHighHalf && ST.has64BitLiterals()) {
3284 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3285 B.buildInstr(AMDGPU::S_MOV_B64)
3300 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3303 B.buildInstr(AMDGPU::S_MOV_B32)
3308 if (RequiresHighHalf) {
3310 "Must provide a 64-bit pointer type!");
3313 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3315 B.buildInstr(AMDGPU::S_MOV_B32)
3326 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3328 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3332 if (AddrDst != DstReg)
3333 B.buildCast(DstReg, AddrDst);
3334 }
else if (AddrLo != DstReg) {
3337 B.buildCast(DstReg, AddrLo);
3346 unsigned AS = Ty.getAddressSpace();
3354 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3358 Fn,
"local memory global used by non-kernel function",
3367 B.buildUndef(DstReg);
3368 MI.eraseFromParent();
3392 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3393 B.buildIntToPtr(DstReg, Sz);
3394 MI.eraseFromParent();
3400 MI.eraseFromParent();
3404 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3406 MI.eraseFromParent();
3414 MI.eraseFromParent();
3420 MI.eraseFromParent();
3436 if (Ty.getSizeInBits() == 32) {
3438 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3439 B.buildExtract(DstReg,
Load, 0);
3441 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3443 MI.eraseFromParent();
3466 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3468 MI.getOperand(1).setReg(Cast.getReg(0));
3473 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3499 if (WideMemSize == ValSize) {
3505 MI.setMemRefs(MF, {WideMMO});
3511 if (ValSize > WideMemSize)
3518 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3519 B.buildTrunc(ValReg, WideLoad).getReg(0);
3526 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3527 B.buildExtract(ValReg, WideLoad, 0);
3531 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3532 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3536 MI.eraseFromParent();
3549 Register DataReg =
MI.getOperand(0).getReg();
3594 "this should not have been custom lowered");
3599 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3601 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3605 .setMemRefs(
MI.memoperands());
3607 MI.eraseFromParent();
3615 switch (
DefMI->getOpcode()) {
3616 case TargetOpcode::G_INTRINSIC: {
3618 case Intrinsic::amdgcn_frexp_mant:
3619 case Intrinsic::amdgcn_log:
3620 case Intrinsic::amdgcn_log_clamp:
3621 case Intrinsic::amdgcn_exp2:
3622 case Intrinsic::amdgcn_sqrt:
3630 case TargetOpcode::G_FSQRT:
3632 case TargetOpcode::G_FFREXP: {
3633 if (
DefMI->getOperand(0).getReg() == Src)
3637 case TargetOpcode::G_FPEXT: {
3658std::pair<Register, Register>
3660 unsigned Flags)
const {
3664 auto SmallestNormal =
B.buildFConstant(
3666 auto IsLtSmallestNormal =
3669 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3670 auto One =
B.buildFConstant(
F32, 1.0);
3672 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3673 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3675 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3688 LLT Ty =
B.getMRI()->getType(Dst);
3689 unsigned Flags =
MI.getFlags();
3693 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3694 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3695 .addUse(Ext.getReg(0))
3697 B.buildFPTrunc(Dst,
Log2, Flags);
3698 MI.eraseFromParent();
3706 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3709 MI.eraseFromParent();
3713 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3714 .addUse(ScaledInput)
3717 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3718 auto Zero =
B.buildFConstant(Ty, 0.0);
3720 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3721 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3723 MI.eraseFromParent();
3729 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3730 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3735 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3736 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3741 unsigned Flags =
MI.getFlags();
3751 auto PromoteSrc =
B.buildFPExt(
F32,
X);
3753 B.buildFPTrunc(Dst, LogVal);
3758 MI.eraseFromParent();
3767 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3770 if (ST.hasFastFMAF32()) {
3772 const float c_log10 = 0x1.344134p-2f;
3773 const float cc_log10 = 0x1.09f79ep-26f;
3776 const float c_log = 0x1.62e42ep-1f;
3777 const float cc_log = 0x1.efa39ep-25f;
3779 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3780 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3784 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3785 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3786 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3787 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3788 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3791 const float ch_log10 = 0x1.344000p-2f;
3792 const float ct_log10 = 0x1.3509f6p-18f;
3795 const float ch_log = 0x1.62e000p-1f;
3796 const float ct_log = 0x1.0bfbe8p-15f;
3798 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3799 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3802 auto YInt =
B.buildBitcast(I32,
Y);
3803 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3804 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3805 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3809 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3812 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3814 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3817 const bool IsFiniteOnly =
3820 if (!IsFiniteOnly) {
3823 auto Fabs =
B.buildFAbs(Ty,
Y);
3826 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3830 auto Zero =
B.buildFConstant(Ty, 0.0);
3832 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3833 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3834 B.buildFSub(Dst, R, Shift, Flags);
3836 B.buildCopy(Dst, R);
3839 MI.eraseFromParent();
3845 unsigned Flags)
const {
3846 const double Log2BaseInverted =
3849 LLT Ty =
B.getMRI()->getType(Dst);
3854 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3857 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3858 auto Zero =
B.buildFConstant(Ty, 0.0);
3860 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3861 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3863 if (ST.hasFastFMAF32())
3864 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3866 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3867 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3874 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3875 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3878 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3879 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3890 unsigned Flags =
MI.getFlags();
3891 LLT Ty =
B.getMRI()->getType(Dst);
3898 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3899 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3900 .addUse(Ext.getReg(0))
3902 B.buildFPTrunc(Dst,
Log2, Flags);
3903 MI.eraseFromParent();
3913 MI.eraseFromParent();
3921 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3923 RangeCheckConst, Flags);
3925 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3926 auto Zero =
B.buildFConstant(Ty, 0.0);
3927 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3928 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3930 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3931 .addUse(AddInput.getReg(0))
3934 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3935 auto One =
B.buildFConstant(Ty, 1.0);
3936 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3937 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3938 MI.eraseFromParent();
3943 const SrcOp &Src,
unsigned Flags) {
3944 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3947 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3948 .addUse(Src.getReg())
3951 return B.buildFExp2(Dst, Src, Flags);
3957 bool IsExp10)
const {
3958 LLT Ty =
B.getMRI()->getType(
X);
3962 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3963 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3970 LLT Ty =
B.getMRI()->getType(Dst);
3976 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3979 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3980 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3981 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3984 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3986 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3987 .addUse(ExpInput.getReg(0))
3990 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3991 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3992 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3998 unsigned Flags)
const {
3999 LLT Ty =
B.getMRI()->getType(Dst);
4003 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4004 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4006 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4007 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4008 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4009 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4010 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4020 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4024 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4025 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4026 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4028 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4029 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4031 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4032 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4033 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4034 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4036 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4037 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4038 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4040 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4058 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4060 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4062 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4064 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4065 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4066 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4067 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4069 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4070 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4071 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4072 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4074 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4075 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4076 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4077 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4078 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4080 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4081 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4082 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4083 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4086 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4087 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4088 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4090 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4091 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4092 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4093 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4094 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4098 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4099 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4101 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4103 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4105 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4107 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4109 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4110 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4111 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4112 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4114 auto One =
B.buildFConstant(
F64, 1.0);
4115 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4116 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4119 auto DnInt =
B.buildFPTOSI(I32, Dn);
4120 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4127 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4134 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4136 MI.eraseFromParent();
4144 const unsigned Flags =
MI.getFlags();
4152 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4160 MI.eraseFromParent();
4171 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4174 B.buildFPTrunc(Dst, Lowered, Flags);
4175 MI.eraseFromParent();
4186 MI.eraseFromParent();
4214 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4217 if (ST.hasFastFMAF32()) {
4219 const float cc_exp = 0x1.4ae0bep-26f;
4220 const float c_exp10 = 0x1.a934f0p+1f;
4221 const float cc_exp10 = 0x1.2f346ep-24f;
4223 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4224 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4225 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4226 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4228 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4229 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4231 const float ch_exp = 0x1.714000p+0f;
4232 const float cl_exp = 0x1.47652ap-12f;
4234 const float ch_exp10 = 0x1.a92000p+1f;
4235 const float cl_exp10 = 0x1.4f0978p-11f;
4238 auto XInt =
B.buildBitcast(I32,
X);
4239 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4240 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4241 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4243 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4244 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4246 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4247 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4250 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4251 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4254 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4257 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4258 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4260 auto IntE =
B.buildFPTOSI(I32, E);
4262 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4263 .addUse(
A.getReg(0))
4265 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4267 auto UnderflowCheckConst =
4268 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4269 auto Zero =
B.buildFConstant(Ty, 0.0);
4273 R =
B.buildSelect(Ty, Underflow, Zero, R);
4276 auto OverflowCheckConst =
4277 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4282 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4285 B.buildCopy(Dst, R);
4286 MI.eraseFromParent();
4295 unsigned Flags =
MI.getFlags();
4296 LLT Ty =
B.getMRI()->getType(Dst);
4299 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4300 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4301 .addUse(Log.getReg(0))
4304 B.buildFExp2(Dst,
Mul, Flags);
4305 }
else if (Ty ==
F16) {
4307 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4308 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4309 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4310 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4311 .addUse(Ext0.getReg(0))
4312 .addUse(Ext1.getReg(0))
4314 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul), Flags);
4318 MI.eraseFromParent();
4326 ModSrc = SrcFNeg->getOperand(1).getReg();
4328 ModSrc = SrcFAbs->getOperand(1).getReg();
4330 ModSrc = SrcFAbs->getOperand(1).getReg();
4340 Register OrigSrc =
MI.getOperand(1).getReg();
4341 unsigned Flags =
MI.getFlags();
4343 "this should not have been custom lowered");
4353 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4373 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4375 B.buildFMinNum(Min, Fract, Const, Flags);
4380 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4383 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4384 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4386 MI.eraseFromParent();
4404 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4406 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4407 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4410 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4411 B.buildBitcast(Dst,
Merge);
4413 MI.eraseFromParent();
4430 bool UsePartialMad64_32,
4431 bool SeparateOddAlignedProducts)
const {
4446 auto getZero32 = [&]() ->
Register {
4448 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4451 auto getZero64 = [&]() ->
Register {
4453 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4458 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4469 if (CarryIn.empty())
4472 bool HaveCarryOut =
true;
4474 if (CarryIn.size() == 1) {
4476 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4480 CarryAccum = getZero32();
4482 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4483 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4485 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4490 LocalAccum = getZero32();
4491 HaveCarryOut =
false;
4496 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4497 LocalAccum =
Add.getReg(0);
4511 auto buildMadChain =
4514 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4515 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4522 if (LocalAccum.size() == 1 &&
4523 (!UsePartialMad64_32 || !CarryIn.empty())) {
4526 unsigned j1 = DstIndex - j0;
4527 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4531 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4533 LocalAccum[0] =
Mul.getReg(0);
4535 if (CarryIn.empty()) {
4536 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4539 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4545 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4549 if (j0 <= DstIndex) {
4550 bool HaveSmallAccum =
false;
4553 if (LocalAccum[0]) {
4554 if (LocalAccum.size() == 1) {
4555 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4556 HaveSmallAccum =
true;
4557 }
else if (LocalAccum[1]) {
4558 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4559 HaveSmallAccum =
false;
4561 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4562 HaveSmallAccum =
true;
4565 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4567 HaveSmallAccum =
true;
4571 unsigned j1 = DstIndex - j0;
4572 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4576 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4577 {Src0[j0], Src1[j1], Tmp});
4578 Tmp = Mad.getReg(0);
4579 if (!HaveSmallAccum)
4580 CarryOut.push_back(Mad.getReg(1));
4581 HaveSmallAccum =
false;
4584 }
while (j0 <= DstIndex);
4586 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4587 LocalAccum[0] = Unmerge.getReg(0);
4588 if (LocalAccum.size() > 1)
4589 LocalAccum[1] = Unmerge.getReg(1);
4596 LocalAccum[0] = getZero32();
4600 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4601 "Uninitialized accumulator part");
4627 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4628 Carry OddCarryIn = std::move(OddCarry);
4629 Carry EvenCarryIn = std::move(EvenCarry);
4634 if (2 * i < Accum.
size()) {
4635 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4636 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4641 if (!SeparateOddAlignedProducts) {
4642 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4643 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4645 bool IsHighest = 2 * i >= Accum.
size();
4648 .take_front(IsHighest ? 1 : 2);
4649 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4655 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4657 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4659 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4662 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4665 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4666 Lo->getOperand(1).getReg());
4667 Accum[2 * i] =
Hi.getReg(0);
4668 SeparateOddCarry =
Hi.getReg(1);
4675 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4676 EvenCarryIn.push_back(CarryOut);
4678 if (2 * i < Accum.
size()) {
4679 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4680 OddCarry.push_back(CarryOut);
4692 assert(ST.hasMad64_32());
4693 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4705 unsigned Size = Ty.getSizeInBits();
4706 if (ST.hasVMulU64Inst() &&
Size == 64)
4709 unsigned NumParts =
Size / 32;
4721 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4725 for (
unsigned i = 0; i < NumParts; ++i) {
4729 B.buildUnmerge(Src0Parts, Src0);
4730 B.buildUnmerge(Src1Parts, Src1);
4733 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4734 SeparateOddAlignedProducts);
4736 B.buildMergeLikeInstr(DstReg, AccumRegs);
4737 MI.eraseFromParent();
4752 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4753 ? AMDGPU::G_AMDGPU_FFBH_U32
4754 : AMDGPU::G_AMDGPU_FFBL_B32;
4755 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4758 MI.eraseFromParent();
4768 TypeSize NumBits = SrcTy.getSizeInBits();
4773 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4774 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4775 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4776 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4777 B.buildTrunc(Dst, Ctlz);
4778 MI.eraseFromParent();
4789 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4790 unsigned BitWidth = SrcTy.getSizeInBits();
4792 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4793 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4794 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4795 MI.eraseFromParent();
4801 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4804 return ConstVal == -1;
4811 Register CondDef =
MI.getOperand(0).getReg();
4830 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4839 UncondBrTarget = &*NextMBB;
4841 if (
Next->getOpcode() != AMDGPU::G_BR)
4860 *ArgRC,
B.getDebugLoc(), ArgTy);
4864 const unsigned Mask = Arg->
getMask();
4872 auto ShiftAmt =
B.buildConstant(I32, Shift);
4873 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4876 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4878 B.buildCopy(DstReg, LiveIn);
4888 if (!ST.hasClusters()) {
4891 MI.eraseFromParent();
4911 auto One =
B.buildConstant(I32, 1);
4912 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4913 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4914 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4921 B.buildCopy(DstReg, GlobalIdXYZ);
4922 MI.eraseFromParent();
4926 B.buildCopy(DstReg, ClusterIdXYZ);
4927 MI.eraseFromParent();
4932 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4934 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4935 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4937 .addImm(ClusterIdField);
4938 auto Zero =
B.buildConstant(I32, 0);
4941 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4942 MI.eraseFromParent();
4984 auto LoadConstant = [&](
unsigned N) {
4985 B.buildConstant(DstReg,
N);
4989 if (ST.hasArchitectedSGPRs() &&
4996 Arg = &WorkGroupIDX;
4997 ArgRC = &AMDGPU::SReg_32RegClass;
5001 Arg = &WorkGroupIDY;
5002 ArgRC = &AMDGPU::SReg_32RegClass;
5006 Arg = &WorkGroupIDZ;
5007 ArgRC = &AMDGPU::SReg_32RegClass;
5011 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5012 return LoadConstant(0);
5013 Arg = &ClusterWorkGroupIDX;
5014 ArgRC = &AMDGPU::SReg_32RegClass;
5018 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5019 return LoadConstant(0);
5020 Arg = &ClusterWorkGroupIDY;
5021 ArgRC = &AMDGPU::SReg_32RegClass;
5025 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5026 return LoadConstant(0);
5027 Arg = &ClusterWorkGroupIDZ;
5028 ArgRC = &AMDGPU::SReg_32RegClass;
5033 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5034 Arg = &ClusterWorkGroupMaxIDX;
5035 ArgRC = &AMDGPU::SReg_32RegClass;
5040 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5041 Arg = &ClusterWorkGroupMaxIDY;
5042 ArgRC = &AMDGPU::SReg_32RegClass;
5047 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5048 Arg = &ClusterWorkGroupMaxIDZ;
5049 ArgRC = &AMDGPU::SReg_32RegClass;
5053 Arg = &ClusterWorkGroupMaxFlatID;
5054 ArgRC = &AMDGPU::SReg_32RegClass;
5069 return LoadConstant(0);
5074 B.buildUndef(DstReg);
5078 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5090 MI.eraseFromParent();
5096 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5097 MI.eraseFromParent();
5104 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5118 B.buildUndef(DstReg);
5119 MI.eraseFromParent();
5123 if (Arg->isMasked()) {
5137 MI.eraseFromParent();
5152 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5161 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5169 Align Alignment)
const {
5173 "unexpected kernarg parameter type");
5180 MI.eraseFromParent();
5212 auto FloatY =
B.buildUITOFP(
F32,
Y);
5213 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5215 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5216 auto Z =
B.buildFPTOUI(I32, ScaledY);
5219 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5220 auto NegYZ =
B.buildMul(I32, NegY, Z);
5221 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5224 auto Q =
B.buildUMulH(I32,
X, Z);
5225 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5228 auto One =
B.buildConstant(I32, 1);
5231 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5232 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5237 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5240 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5259 auto Unmerge =
B.buildUnmerge(I32, Val);
5261 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5262 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5264 auto Mad =
B.buildFMAD(
5268 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5269 auto Mul1 =
B.buildFMul(
5273 auto Mul2 =
B.buildFMul(
5275 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5278 auto Mad2 =
B.buildFMAD(
5282 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5283 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5285 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5300 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5302 auto Zero64 =
B.buildConstant(I64, 0);
5303 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5305 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5306 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5308 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5309 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5310 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5312 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5313 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5314 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5316 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5317 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5318 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5319 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5320 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5322 auto Zero32 =
B.buildConstant(I32, 0);
5323 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5324 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5325 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5327 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5328 Register NumerLo = UnmergeNumer.getReg(0);
5329 Register NumerHi = UnmergeNumer.getReg(1);
5331 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5332 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5333 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5334 Register Mul3_Lo = UnmergeMul3.getReg(0);
5335 Register Mul3_Hi = UnmergeMul3.getReg(1);
5336 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5337 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5338 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5339 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5341 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5342 Register DenomLo = UnmergeDenom.getReg(0);
5343 Register DenomHi = UnmergeDenom.getReg(1);
5346 auto C1 =
B.buildSExt(I32, CmpHi);
5349 auto C2 =
B.buildSExt(I32, CmpLo);
5352 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5359 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5360 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5361 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5362 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5364 auto One64 =
B.buildConstant(I64, 1);
5365 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5371 auto C6 =
B.buildSelect(
5375 auto Add4 =
B.buildAdd(I64, Add3, One64);
5376 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5378 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5379 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5380 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5386 auto Sel1 =
B.buildSelect(
5393 auto Sel2 =
B.buildSelect(
5404 switch (
MI.getOpcode()) {
5407 case AMDGPU::G_UDIV: {
5408 DstDivReg =
MI.getOperand(0).getReg();
5411 case AMDGPU::G_UREM: {
5412 DstRemReg =
MI.getOperand(0).getReg();
5415 case AMDGPU::G_UDIVREM: {
5416 DstDivReg =
MI.getOperand(0).getReg();
5417 DstRemReg =
MI.getOperand(1).getReg();
5424 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5425 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5426 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5436 MI.eraseFromParent();
5447 if (Ty != I32 && Ty != I64)
5450 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5451 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5452 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5454 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5455 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5456 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5458 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5459 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5461 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5462 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5464 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5465 switch (
MI.getOpcode()) {
5468 case AMDGPU::G_SDIV: {
5469 DstDivReg =
MI.getOperand(0).getReg();
5473 case AMDGPU::G_SREM: {
5474 DstRemReg =
MI.getOperand(0).getReg();
5478 case AMDGPU::G_SDIVREM: {
5479 DstDivReg =
MI.getOperand(0).getReg();
5480 DstRemReg =
MI.getOperand(1).getReg();
5493 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5494 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5495 B.buildSub(DstDivReg, SignXor, Sign);
5499 auto Sign = LHSign.getReg(0);
5500 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5501 B.buildSub(DstRemReg, SignXor, Sign);
5504 MI.eraseFromParent();
5520 if (!AllowInaccurateRcp && ResTy !=
F16)
5531 if (CLHS->isOne()) {
5532 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5536 MI.eraseFromParent();
5541 if (CLHS->isMinusOne()) {
5542 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5543 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5544 .addUse(FNeg.getReg(0))
5547 MI.eraseFromParent();
5554 if (!AllowInaccurateRcp &&
5559 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5562 B.buildFMul(Res, LHS, RCP, Flags);
5564 MI.eraseFromParent();
5579 if (!AllowInaccurateRcp)
5587 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5589 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5590 auto One =
B.buildFConstant(ResTy, 1.0);
5592 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5596 R =
B.buildFNeg(ResTy, R);
5598 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5599 R =
B.buildFMA(ResTy, Tmp0, R, R);
5601 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5602 R =
B.buildFMA(ResTy, Tmp1, R, R);
5605 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5606 B.buildCopy(Res, R);
5607 MI.eraseFromParent();
5611 auto Ret =
B.buildFMul(ResTy,
X, R);
5612 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5614 B.buildFMA(Res, Tmp2, R, Ret);
5615 MI.eraseFromParent();
5646 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5647 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5648 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5649 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5650 .addUse(RHSExt.getReg(0))
5652 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5654 if (ST.hasMadMacF32Insts()) {
5655 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5656 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5657 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5659 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5660 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5661 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5663 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5664 auto TmpInt =
B.buildBitcast(I32, Tmp);
5665 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5666 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5667 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5668 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5669 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5670 .addUse(RDst.getReg(0))
5675 MI.eraseFromParent();
5688 unsigned SPDenormMode =
5691 if (ST.hasDenormModeInst()) {
5693 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5695 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5696 B.buildInstr(AMDGPU::S_DENORM_MODE)
5697 .addImm(NewDenormModeValue);
5700 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5701 .addImm(SPDenormMode)
5722 auto One =
B.buildFConstant(
F32, 1.0f);
5724 auto DenominatorScaled =
5725 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5730 auto NumeratorScaled =
5731 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5737 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5738 .addUse(DenominatorScaled.getReg(0))
5740 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5743 const bool HasDynamicDenormals =
5748 if (!PreservesDenormals) {
5749 if (HasDynamicDenormals) {
5751 B.buildInstr(AMDGPU::S_GETREG_B32)
5752 .addDef(SavedSPDenormMode)
5758 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5759 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5760 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5761 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5762 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5763 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5765 if (!PreservesDenormals) {
5766 if (HasDynamicDenormals) {
5767 assert(SavedSPDenormMode);
5768 B.buildInstr(AMDGPU::S_SETREG_B32)
5769 .addReg(SavedSPDenormMode)
5775 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5776 .addUse(Fma4.getReg(0))
5777 .addUse(Fma1.getReg(0))
5778 .addUse(Fma3.getReg(0))
5779 .addUse(NumeratorScaled.getReg(1))
5782 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5783 .addUse(Fmas.getReg(0))
5788 MI.eraseFromParent();
5806 auto One =
B.buildFConstant(
F64, 1.0);
5808 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5814 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5816 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5817 .addUse(DivScale0.getReg(0))
5820 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5821 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5822 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5824 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5830 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5831 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5832 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5835 if (!ST.hasUsableDivScaleConditionOutput()) {
5842 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5843 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5844 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5845 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5848 Scale1Unmerge.getReg(1));
5850 Scale0Unmerge.getReg(1));
5851 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5853 Scale = DivScale1.getReg(1);
5856 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5857 .addUse(Fma4.getReg(0))
5858 .addUse(Fma3.getReg(0))
5859 .addUse(
Mul.getReg(0))
5863 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5864 .addUse(Fmas.getReg(0))
5869 MI.eraseFromParent();
5884 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5887 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5891 if (ST.hasFractBug()) {
5892 auto Fabs =
B.buildFAbs(Ty, Val);
5896 auto Zero =
B.buildConstant(InstrExpTy, 0);
5897 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5898 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5901 B.buildCopy(Res0, Mant);
5902 B.buildSExtOrTrunc(Res1, Exp);
5904 MI.eraseFromParent();
5918 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5921 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5922 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5923 auto C2 =
B.buildFConstant(
F32, 1.0f);
5926 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5928 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5930 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5931 .addUse(Mul0.getReg(0))
5934 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5936 B.buildFMul(Res, Sel, Mul1, Flags);
5938 MI.eraseFromParent();
5947 unsigned Flags =
MI.getFlags();
5948 assert(!ST.has16BitInsts());
5949 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5950 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5951 .addUse(Ext.getReg(0))
5953 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5954 MI.eraseFromParent();
5964 const unsigned Flags =
MI.getFlags();
5972 MI.eraseFromParent();
5976 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5978 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5979 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5980 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5985 .addUse(SqrtX.getReg(0))
5988 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5989 auto NegOne =
B.buildConstant(I32, -1);
5990 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5992 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5993 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5995 auto PosOne =
B.buildConstant(I32, 1);
5996 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5998 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5999 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6001 auto Zero =
B.buildFConstant(
F32, 0.0f);
6005 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6009 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6012 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6013 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6015 auto Half =
B.buildFConstant(
F32, 0.5f);
6016 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6017 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6018 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6019 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6020 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6021 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6022 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6023 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6026 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6028 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6030 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6033 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6035 MI.eraseFromParent();
6069 unsigned Flags =
MI.getFlags();
6074 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6076 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6080 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6081 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6082 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6085 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6087 auto Half =
B.buildFConstant(
F64, 0.5);
6088 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6089 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6091 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6092 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6094 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6095 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6097 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6098 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6100 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6102 Register SqrtRet = SqrtS2.getReg(0);
6104 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6105 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6106 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6109 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6110 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6111 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6116 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6119 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6125 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6127 MI.eraseFromParent();
6158 auto Flags =
MI.getFlags();
6170 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6180 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6181 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6186 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6188 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6189 MI.eraseFromParent();
6201 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6202 IID == Intrinsic::amdgcn_permlanex16;
6203 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6204 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6205 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6206 IID == Intrinsic::amdgcn_permlane_up ||
6207 IID == Intrinsic::amdgcn_permlane_down ||
6208 IID == Intrinsic::amdgcn_permlane_xor;
6212 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6214 case Intrinsic::amdgcn_readfirstlane:
6215 case Intrinsic::amdgcn_permlane64:
6216 return LaneOp.getReg(0);
6217 case Intrinsic::amdgcn_readlane:
6218 case Intrinsic::amdgcn_set_inactive:
6219 case Intrinsic::amdgcn_set_inactive_chain_arg:
6220 return LaneOp.addUse(Src1).getReg(0);
6221 case Intrinsic::amdgcn_writelane:
6222 case Intrinsic::amdgcn_permlane_bcast:
6223 case Intrinsic::amdgcn_permlane_up:
6224 case Intrinsic::amdgcn_permlane_down:
6225 case Intrinsic::amdgcn_permlane_xor:
6226 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6227 case Intrinsic::amdgcn_permlane16:
6228 case Intrinsic::amdgcn_permlanex16: {
6230 int64_t Src4 =
MI.getOperand(6).getImm();
6231 int64_t Src5 =
MI.getOperand(7).getImm();
6232 return LaneOp.addUse(Src1)
6239 case Intrinsic::amdgcn_mov_dpp8:
6240 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6241 case Intrinsic::amdgcn_update_dpp:
6242 return LaneOp.addUse(Src1)
6243 .addImm(
MI.getOperand(4).getImm())
6244 .addImm(
MI.getOperand(5).getImm())
6245 .addImm(
MI.getOperand(6).getImm())
6246 .addImm(
MI.getOperand(7).getImm())
6256 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6257 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6258 IsPermlaneShuffle) {
6259 Src1 =
MI.getOperand(3).getReg();
6260 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6261 IsPermlaneShuffle) {
6262 Src2 =
MI.getOperand(4).getReg();
6267 unsigned Size = Ty.getSizeInBits();
6269 unsigned SplitSize = 32;
6270 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6271 ST.hasDPALU_DPP() &&
6275 if (
Size == SplitSize) {
6282 bool IsFloat = Ty.getScalarType().isFloat();
6286 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6288 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6290 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6294 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6296 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6297 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6299 if (IID == Intrinsic::amdgcn_writelane)
6300 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6302 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6304 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6306 B.buildTrunc(DstReg, LaneOpDst);
6307 MI.eraseFromParent();
6311 if (
Size % SplitSize != 0)
6315 bool NeedsBitcast =
false;
6316 if (IntTy.isVector()) {
6319 if (EltSize == SplitSize) {
6320 PartialResTy = EltTy;
6321 }
else if (EltSize == 16 || EltSize == 32) {
6322 unsigned NElem = SplitSize / EltSize;
6325 NeedsBitcast =
true;
6330 unsigned NumParts =
Size / SplitSize;
6334 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6335 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6337 if (IID == Intrinsic::amdgcn_writelane)
6338 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6340 for (
unsigned i = 0; i < NumParts; ++i) {
6341 Src0 = Src0Parts.
getReg(i);
6343 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6344 Src1 = Src1Parts.
getReg(i);
6346 if (IID == Intrinsic::amdgcn_writelane)
6347 Src2 = Src2Parts.
getReg(i);
6349 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6352 if (NeedsBitcast || IsFloat)
6355 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6357 B.buildMergeLikeInstr(DstReg, PartialRes);
6359 MI.eraseFromParent();
6367 ST.getTargetLowering()->getImplicitParameterOffset(
6377 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6378 B.buildConstant(IdxTy,
Offset).getReg(0));
6389 Register Pointer =
MI.getOperand(2).getReg();
6391 Register NumRecords =
MI.getOperand(4).getReg();
6397 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6399 auto ExtStride =
B.buildAnyExt(I32, Stride);
6401 if (ST.has45BitNumRecordsBufferResource()) {
6402 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6404 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6406 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6410 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6411 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6412 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6413 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6417 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6418 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6419 auto ExtShiftedStride =
6420 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6421 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6422 auto ExtShiftedFlags =
6423 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6424 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6426 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6427 B.buildMergeValues(Result, {LowHalf, HighHalf});
6429 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6430 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6431 auto LowHalf = Unmerge.getReg(0);
6432 auto HighHalf = Unmerge.getReg(1);
6434 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6435 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6436 auto ShiftConst =
B.buildConstant(I32, 16);
6437 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6438 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6439 Register NewHighHalfReg = NewHighHalf.getReg(0);
6440 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6443 MI.eraseFromParent();
6460 MI.eraseFromParent();
6468 std::optional<uint32_t> KnownSize =
6470 if (KnownSize.has_value())
6471 B.buildConstant(DstReg, *KnownSize);
6489 MI.eraseFromParent();
6496 unsigned AddrSpace)
const {
6498 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6502 ST.hasGloballyAddressableScratch()) {
6504 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6505 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6507 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6509 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6511 B.buildConstant(I32, 1u << 26));
6516 MI.eraseFromParent();
6526std::pair<Register, unsigned>
6538 bool CheckNUW = ST.hasGFX1250Insts();
6540 MRI, OrigOffset,
nullptr, CheckNUW);
6544 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6554 unsigned Overflow = ImmOffset & ~MaxImm;
6555 ImmOffset -= Overflow;
6556 if ((int32_t)Overflow < 0) {
6557 Overflow += ImmOffset;
6561 if (Overflow != 0) {
6563 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6565 auto OverflowVal =
B.buildConstant(I32, Overflow);
6566 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6571 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6573 return std::pair(BaseReg, ImmOffset);
6580 bool ImageStore)
const {
6588 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6590 if (ST.hasUnpackedD16VMem()) {
6591 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6594 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6595 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6603 if (ImageStore && ST.hasImageStoreD16Bug()) {
6606 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6608 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6615 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6616 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6618 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6626 auto Unmerge =
B.buildUnmerge(I32, Reg);
6627 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6629 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6639 Reg =
B.buildPadVectorWithUndefElements(
6648 bool IsFormat)
const {
6658 VData =
B.buildBitcast(Ty, VData).getReg(0);
6666 if (Ty.isVector()) {
6667 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6679 bool IsFormat)
const {
6686 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6693 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6694 const Function &Fn =
B.getMF().getFunction();
6696 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6697 MI.eraseFromParent();
6709 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6712 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6716 VIndex =
MI.getOperand(3).getReg();
6719 VIndex =
B.buildConstant(I32, 0).getReg(0);
6722 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6723 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6727 Format =
MI.getOperand(5 + OpOffset).getImm();
6731 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6737 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6738 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6739 }
else if (IsFormat) {
6740 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6741 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6745 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6748 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6751 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6756 auto MIB =
B.buildInstr(
Opc)
6767 MIB.addImm(AuxiliaryData)
6768 .addImm(HasVIndex ? -1 : 0)
6769 .addMemOperand(MMO);
6771 MI.eraseFromParent();
6777 unsigned ImmOffset,
unsigned Format,
6780 auto MIB =
B.buildInstr(
Opc)
6791 MIB.addImm(AuxiliaryData)
6792 .addImm(HasVIndex ? -1 : 0)
6793 .addMemOperand(MMO);
6799 bool IsTyped)
const {
6813 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6814 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6816 StatusDst =
MI.getOperand(1).getReg();
6821 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6824 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6827 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6830 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6833 VIndex =
B.buildConstant(I32, 0).getReg(0);
6836 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6837 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6841 Format =
MI.getOperand(5 + OpOffset).getImm();
6845 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6855 Dst =
MI.getOperand(0).getReg();
6856 B.setInsertPt(
B.getMBB(),
MI);
6863 Dst =
MI.getOperand(0).getReg();
6864 B.setInsertPt(
B.getMBB(),
MI);
6868 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6869 const bool Unpacked = ST.hasUnpackedD16VMem();
6871 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6872 const Function &Fn =
B.getMF().getFunction();
6874 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6877 B.buildUndef(StatusDst);
6878 MI.eraseFromParent();
6890 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6891 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6892 }
else if (IsFormat) {
6896 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6898 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6899 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6904 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6905 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6908 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6909 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6912 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6913 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6919 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6920 unsigned NumLoadDWords = NumValueDWords + 1;
6922 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6924 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6925 bool IsFloat = Ty.getScalarType().isFloat();
6930 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6932 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6933 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6934 B.buildTrunc(DstInt, ExtDst);
6935 }
else if (NumValueDWords == 1) {
6936 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6939 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6940 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6942 B.buildUnmerge(LoadElts, LoadDstReg);
6944 B.buildMergeLikeInstr(DstInt, LoadElts);
6947 B.buildBitcast(Dst, DstInt);
6949 (IsD16 && !Ty.isVector())) {
6950 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6952 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6953 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6954 B.buildTrunc(Dst, LoadDstReg);
6955 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6957 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6959 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6960 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6962 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6964 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6965 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6966 B.buildMergeLikeInstr(Dst, Repack);
6969 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6972 MI.eraseFromParent();
6978 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6979 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6980 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6981 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6982 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6983 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6984 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6985 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6986 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6987 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6988 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6989 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6990 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6991 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6992 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6993 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6994 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6995 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6996 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6997 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6998 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6999 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7000 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7001 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7002 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7003 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7004 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7005 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7006 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7007 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7008 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7009 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7010 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7011 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7012 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7013 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7014 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7015 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7016 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7017 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7018 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7019 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7020 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7021 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7022 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7023 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7024 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7025 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7026 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7027 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7028 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7029 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7030 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7031 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7032 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7033 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7034 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7035 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7036 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7037 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7038 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7039 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7040 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7041 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7042 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7043 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7044 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7045 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7046 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7047 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7048 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7049 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7050 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7051 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7052 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7053 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7054 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7055 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7056 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7057 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7058 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7059 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7060 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7061 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7062 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7063 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7064 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7065 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7066 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7067 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7076 const bool IsCmpSwap =
7077 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7078 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7079 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7080 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7091 CmpVal =
MI.getOperand(3).getReg();
7096 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7097 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7100 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7103 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7109 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7110 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7111 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7130 .addImm(AuxiliaryData)
7131 .addImm(HasVIndex ? -1 : 0)
7132 .addMemOperand(MMO);
7134 MI.eraseFromParent();
7144 bool IsA16,
bool IsG16) {
7158 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7163 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7167 "Bias needs to be converted to 16 bit in A16 mode");
7169 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7173 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7177 if (((
I + 1) >= EndIdx) ||
7184 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7186 B.buildBuildVector(V2EltTy,
7187 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7192 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7203 int DimIdx,
int NumVAddrs) {
7205 for (
int I = 0;
I != NumVAddrs; ++
I) {
7207 if (
SrcOp.isReg()) {
7210 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7211 if (
B.getMRI()->getType(
Reg) != I32)
7212 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7217 int NumAddrRegs = AddrRegs.
size();
7218 if (NumAddrRegs != 1) {
7219 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7222 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7225 for (
int I = 1;
I != NumVAddrs; ++
I) {
7228 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7250 const unsigned NumDefs =
MI.getNumExplicitDefs();
7251 const unsigned ArgOffset = NumDefs + 1;
7252 bool IsTFE = NumDefs == 2;
7270 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7274 const bool IsAtomicPacked16Bit =
7275 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7276 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7283 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7284 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7285 const bool DataTyIs16 =
7286 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7288 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7289 const bool IsA16 = AddrTyIs16;
7290 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7293 if (!BaseOpcode->
Atomic) {
7294 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7297 }
else if (DMask != 0) {
7299 }
else if (!IsTFE && !BaseOpcode->
Store) {
7301 B.buildUndef(
MI.getOperand(0));
7302 MI.eraseFromParent();
7310 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7311 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7312 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7313 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7314 unsigned NewOpcode = LoadOpcode;
7315 if (BaseOpcode->
Store)
7316 NewOpcode = StoreOpcode;
7318 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7321 MI.setDesc(
B.getTII().get(NewOpcode));
7325 if (IsTFE && DMask == 0) {
7328 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7331 if (BaseOpcode->
Atomic) {
7336 if (Ty.isVector() && !IsAtomicPacked16Bit)
7343 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7344 MI.getOperand(2).setReg(
Concat.getReg(0));
7345 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7349 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7352 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7358 if (IsA16 && !ST.hasA16()) {
7363 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7364 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7366 if (IsA16 || IsG16) {
7374 const bool UseNSA = ST.hasNSAEncoding() &&
7375 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7376 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7377 const bool UsePartialNSA =
7378 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7380 if (UsePartialNSA) {
7384 auto Concat =
B.buildConcatVectors(
7385 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7386 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7387 PackedRegs.
resize(NSAMaxSize);
7388 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7390 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7391 PackedRegs[0] =
Concat.getReg(0);
7395 const unsigned NumPacked = PackedRegs.
size();
7398 if (!
SrcOp.isReg()) {
7408 SrcOp.setReg(AMDGPU::NoRegister);
7425 const bool UseNSA = ST.hasNSAEncoding() &&
7426 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7427 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7428 const bool UsePartialNSA =
7429 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7431 if (UsePartialNSA) {
7433 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7435 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7450 if (!Ty.isVector() || !IsD16)
7454 if (RepackedReg != VData) {
7455 MI.getOperand(1).setReg(RepackedReg);
7463 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7466 if (NumElts < DMaskLanes)
7469 if (NumElts > 4 || DMaskLanes > 4)
7480 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7481 const LLT AdjustedTy =
7497 if (IsD16 && ST.hasUnpackedD16VMem()) {
7504 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7505 unsigned RoundedSize = 32 * RoundedElts;
7509 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7514 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7520 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7524 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7525 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7529 MI.getOperand(0).setReg(NewResultReg);
7537 Dst1Reg =
MI.getOperand(1).getReg();
7538 if (MRI->
getType(Dst1Reg) != I32)
7542 MI.removeOperand(1);
7545 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7546 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7547 B.buildBitcast(DstReg, Unmerge.getReg(0));
7548 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7557 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7559 if (ResultNumRegs == 1) {
7561 ResultRegs[0] = NewResultReg;
7564 for (
int I = 0;
I != NumDataRegs; ++
I)
7566 B.buildUnmerge(ResultRegs, NewResultReg);
7571 ResultRegs.
resize(NumDataRegs);
7576 if (IsD16 && !Ty.isVector()) {
7577 B.buildTrunc(DstReg, ResultRegs[0]);
7582 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7583 !ST.hasUnpackedD16VMem()) {
7584 B.buildBitcast(DstReg, ResultRegs[0]);
7596 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7598 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7599 }
else if (ST.hasUnpackedD16VMem()) {
7601 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7605 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7609 for (
int I = 0;
I != NumElts; ++
I)
7616 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7617 B.buildBuildVector(DstReg, ResultRegs);
7621 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7622 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7627 if (Ty == V3I16 || Ty == V3F16) {
7629 if (ResultRegs.
size() == 1) {
7630 NewResultReg = ResultRegs[0];
7631 }
else if (ResultRegs.
size() == 2) {
7633 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7648 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7650 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7652 if (ResizeDst != DstReg)
7653 B.buildBitcast(DstReg, ResizeDst);
7657 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7658 B.buildConcatVectors(DstReg, ResultRegs);
7667 Register OrigDst =
MI.getOperand(0).getReg();
7669 LLT Ty =
B.getMRI()->getType(OrigDst);
7670 unsigned Size = Ty.getSizeInBits();
7672 bool HasMMO = !
MI.memoperands_empty();
7674 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7676 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7677 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7680 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7682 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7691 B.setInsertPt(
B.getMBB(),
MI);
7696 B.setInsertPt(
B.getMBB(),
MI);
7699 MI.setDesc(
B.getTII().get(
Opc));
7700 MI.removeOperand(1);
7706 const unsigned MemSize = (
Size + 7) / 8;
7707 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7714 MI.addMemOperand(MF, MMO);
7716 if (Dst != OrigDst) {
7717 MI.getOperand(0).setReg(Dst);
7718 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7719 B.buildTrunc(OrigDst, Dst);
7741 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7742 MI.removeOperand(0);
7752 if (!ST.hasTrapHandler() ||
7756 return ST.supportsGetDoorbellID() ?
7769 MI.eraseFromParent();
7779 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7781 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7785 MI.eraseFromParent();
7794 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7801 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7821 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7824 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7825 B.buildCopy(SGPR01, Temp);
7826 B.buildInstr(AMDGPU::S_TRAP)
7829 MI.eraseFromParent();
7840 B.buildCopy(SGPR01, LiveIn);
7841 B.buildInstr(AMDGPU::S_TRAP)
7845 MI.eraseFromParent();
7854 if (ST.hasPrivEnabledTrap2NopBug()) {
7855 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7857 MI.eraseFromParent();
7861 B.buildInstr(AMDGPU::S_TRAP)
7863 MI.eraseFromParent();
7872 if (!ST.hasTrapHandler() ||
7876 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7879 B.buildInstr(AMDGPU::S_TRAP)
7883 MI.eraseFromParent();
7897 Register NodePtr =
MI.getOperand(2).getReg();
7898 Register RayExtent =
MI.getOperand(3).getReg();
7899 Register RayOrigin =
MI.getOperand(4).getReg();
7901 Register RayInvDir =
MI.getOperand(6).getReg();
7904 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7911 const unsigned NumVDataDwords = 4;
7912 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7913 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7915 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7917 const unsigned BaseOpcodes[2][2] = {
7918 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7919 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7920 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7924 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7925 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7926 : AMDGPU::MIMGEncGfx10NSA,
7927 NumVDataDwords, NumVAddrDwords);
7931 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7932 : AMDGPU::MIMGEncGfx10Default,
7933 NumVDataDwords, NumVAddrDwords);
7938 if (UseNSA && IsGFX11Plus) {
7939 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7940 auto SrcInt =
B.buildBitcast(V3I32, Src);
7941 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7942 auto Merged =
B.buildMergeLikeInstr(
7943 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7944 Ops.push_back(Merged.getReg(0));
7947 Ops.push_back(NodePtr);
7948 Ops.push_back(RayExtent);
7949 packLanes(RayOrigin);
7952 auto UnmergeRayDir =
7953 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7954 auto UnmergeRayInvDir =
7955 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7956 auto MergedDir =
B.buildMergeLikeInstr(
7959 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7960 UnmergeRayDir.getReg(0)}))
7963 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7964 UnmergeRayDir.getReg(1)}))
7967 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7968 UnmergeRayDir.getReg(2)}))
7970 Ops.push_back(MergedDir.getReg(0));
7973 packLanes(RayInvDir);
7977 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7978 Ops.push_back(Unmerge.getReg(0));
7979 Ops.push_back(Unmerge.getReg(1));
7981 Ops.push_back(NodePtr);
7983 Ops.push_back(RayExtent);
7985 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7986 auto SrcInt =
B.buildBitcast(V3I32, Src);
7987 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7988 Ops.push_back(Unmerge.getReg(0));
7989 Ops.push_back(Unmerge.getReg(1));
7990 Ops.push_back(Unmerge.getReg(2));
7993 packLanes(RayOrigin);
7995 auto UnmergeRayDir =
7996 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7997 auto UnmergeRayInvDir =
7998 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8002 B.buildMergeLikeInstr(R1,
8003 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8004 B.buildMergeLikeInstr(
8005 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8006 B.buildMergeLikeInstr(
8007 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8013 packLanes(RayInvDir);
8022 Ops.push_back(MergedOps);
8025 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8034 .addImm(IsA16 ? 1 : 0)
8037 MI.eraseFromParent();
8047 Register DstOrigin =
MI.getOperand(1).getReg();
8049 Register NodePtr =
MI.getOperand(4).getReg();
8050 Register RayExtent =
MI.getOperand(5).getReg();
8051 Register InstanceMask =
MI.getOperand(6).getReg();
8052 Register RayOrigin =
MI.getOperand(7).getReg();
8054 Register Offsets =
MI.getOperand(9).getReg();
8055 Register TDescr =
MI.getOperand(10).getReg();
8058 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8059 const unsigned NumVDataDwords = 10;
8060 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8062 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8063 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8064 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8067 auto RayExtentInstanceMaskVec =
8068 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8069 B.buildAnyExt(I32, InstanceMask)});
8071 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8072 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8078 .addUse(RayExtentInstanceMaskVec.getReg(0))
8085 MI.eraseFromParent();
8094 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8095 MI.eraseFromParent();
8102 if (!ST.hasArchitectedSGPRs())
8106 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8107 auto LSB =
B.buildConstant(I32, 25);
8108 auto Width =
B.buildConstant(I32, 5);
8109 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8110 MI.eraseFromParent();
8118 unsigned Width)
const {
8122 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8123 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8126 MI.eraseFromParent();
8146 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8150 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8153 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8154 MI.eraseFromParent();
8167 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8171 .addReg(Unmerge.getReg(0));
8175 .addReg(Unmerge.getReg(1));
8176 MI.eraseFromParent();
8188 case Intrinsic::amdgcn_icmp: {
8199 if (!Src1Const || Src1Const->Value != 0)
8203 int64_t Pred =
MI.getOperand(4).getImm();
8209 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8210 MI.eraseFromParent();
8213 case Intrinsic::sponentry:
8219 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8222 B.buildIntToPtr(DstReg, TmpReg);
8223 MI.eraseFromParent();
8225 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8227 B.buildFrameIndex(
MI.getOperand(0), FI);
8228 MI.eraseFromParent();
8231 case Intrinsic::amdgcn_if:
8232 case Intrinsic::amdgcn_else: {
8235 bool Negated =
false;
8247 std::swap(CondBrTarget, UncondBrTarget);
8249 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8250 if (IntrID == Intrinsic::amdgcn_if) {
8251 B.buildInstr(AMDGPU::SI_IF)
8254 .addMBB(UncondBrTarget);
8256 B.buildInstr(AMDGPU::SI_ELSE)
8259 .addMBB(UncondBrTarget);
8268 B.buildBr(*CondBrTarget);
8273 MI.eraseFromParent();
8274 BrCond->eraseFromParent();
8280 case Intrinsic::amdgcn_loop: {
8283 bool Negated =
false;
8293 std::swap(CondBrTarget, UncondBrTarget);
8295 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8296 B.buildInstr(AMDGPU::SI_LOOP)
8298 .addMBB(UncondBrTarget);
8303 B.buildBr(*CondBrTarget);
8305 MI.eraseFromParent();
8306 BrCond->eraseFromParent();
8313 case Intrinsic::amdgcn_wave_reduce_min:
8314 case Intrinsic::amdgcn_wave_reduce_umin:
8315 case Intrinsic::amdgcn_wave_reduce_fmin:
8316 case Intrinsic::amdgcn_wave_reduce_max:
8317 case Intrinsic::amdgcn_wave_reduce_umax:
8318 case Intrinsic::amdgcn_wave_reduce_fmax:
8319 case Intrinsic::amdgcn_wave_reduce_add:
8320 case Intrinsic::amdgcn_wave_reduce_fadd:
8321 case Intrinsic::amdgcn_wave_reduce_sub:
8322 case Intrinsic::amdgcn_wave_reduce_fsub:
8323 case Intrinsic::amdgcn_wave_reduce_and:
8324 case Intrinsic::amdgcn_wave_reduce_or:
8325 case Intrinsic::amdgcn_wave_reduce_xor: {
8330 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8331 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8332 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8333 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8334 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8335 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8336 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8337 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8338 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8345 .addUse(Ext.getReg(0))
8346 .addImm(
MI.getOperand(3).getImm());
8348 B.buildFPTrunc(DstReg, NewDst);
8350 B.buildTrunc(DstReg, NewDst);
8351 MI.eraseFromParent();
8354 case Intrinsic::amdgcn_addrspacecast_nonnull:
8356 case Intrinsic::amdgcn_make_buffer_rsrc:
8358 case Intrinsic::amdgcn_kernarg_segment_ptr:
8361 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8362 MI.eraseFromParent();
8368 case Intrinsic::amdgcn_implicitarg_ptr:
8370 case Intrinsic::amdgcn_workitem_id_x:
8373 case Intrinsic::amdgcn_workitem_id_y:
8376 case Intrinsic::amdgcn_workitem_id_z:
8379 case Intrinsic::amdgcn_workgroup_id_x:
8384 case Intrinsic::amdgcn_workgroup_id_y:
8389 case Intrinsic::amdgcn_workgroup_id_z:
8394 case Intrinsic::amdgcn_cluster_id_x:
8395 return ST.hasClusters() &&
8398 case Intrinsic::amdgcn_cluster_id_y:
8399 return ST.hasClusters() &&
8402 case Intrinsic::amdgcn_cluster_id_z:
8403 return ST.hasClusters() &&
8406 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8407 return ST.hasClusters() &&
8410 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8411 return ST.hasClusters() &&
8414 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8415 return ST.hasClusters() &&
8418 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8419 return ST.hasClusters() &&
8421 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8422 return ST.hasClusters() &&
8425 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8426 return ST.hasClusters() &&
8429 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8430 return ST.hasClusters() &&
8433 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8434 return ST.hasClusters() &&
8438 case Intrinsic::amdgcn_wave_id:
8440 case Intrinsic::amdgcn_lds_kernel_id:
8443 case Intrinsic::amdgcn_dispatch_ptr:
8446 case Intrinsic::amdgcn_queue_ptr:
8449 case Intrinsic::amdgcn_implicit_buffer_ptr:
8452 case Intrinsic::amdgcn_dispatch_id:
8455 case Intrinsic::r600_read_ngroups_x:
8459 case Intrinsic::r600_read_ngroups_y:
8462 case Intrinsic::r600_read_ngroups_z:
8465 case Intrinsic::r600_read_local_size_x:
8468 case Intrinsic::r600_read_local_size_y:
8472 case Intrinsic::r600_read_local_size_z:
8475 case Intrinsic::amdgcn_fdiv_fast:
8477 case Intrinsic::amdgcn_is_shared:
8479 case Intrinsic::amdgcn_is_private:
8481 case Intrinsic::amdgcn_wavefrontsize: {
8482 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8483 MI.eraseFromParent();
8486 case Intrinsic::amdgcn_s_buffer_load:
8487 case Intrinsic::amdgcn_ptr_s_buffer_load:
8489 case Intrinsic::amdgcn_raw_buffer_store:
8490 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8491 case Intrinsic::amdgcn_struct_buffer_store:
8492 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8494 case Intrinsic::amdgcn_raw_buffer_store_format:
8495 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8496 case Intrinsic::amdgcn_struct_buffer_store_format:
8497 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8499 case Intrinsic::amdgcn_raw_tbuffer_store:
8500 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8501 case Intrinsic::amdgcn_struct_tbuffer_store:
8502 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8504 case Intrinsic::amdgcn_raw_buffer_load:
8505 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8506 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8507 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8508 case Intrinsic::amdgcn_struct_buffer_load:
8509 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8510 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8511 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8513 case Intrinsic::amdgcn_raw_buffer_load_format:
8514 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8515 case Intrinsic::amdgcn_struct_buffer_load_format:
8516 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8518 case Intrinsic::amdgcn_raw_tbuffer_load:
8519 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8520 case Intrinsic::amdgcn_struct_tbuffer_load:
8521 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8523 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8524 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8525 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8526 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8527 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8528 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8529 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8530 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8531 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8532 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8533 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8534 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8535 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8536 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8537 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8538 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8539 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8540 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8541 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8542 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8543 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8544 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8545 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8546 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8547 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8548 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8549 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8550 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8551 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8552 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8553 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8554 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8555 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8556 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8557 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8558 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8559 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8560 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8561 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8562 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8563 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8564 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8565 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8566 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8567 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8568 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8569 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8570 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8571 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8572 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8573 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8574 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8575 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8576 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8577 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8578 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8579 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8580 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8581 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8582 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8583 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8584 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8585 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8586 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8587 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8588 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8589 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8590 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8591 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8592 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8593 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8594 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8596 case Intrinsic::amdgcn_rsq_clamp:
8598 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8600 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8601 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8603 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8604 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8605 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8606 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8607 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8608 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8609 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8610 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8614 if (IndexArgTy != I64) {
8615 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8616 :
B.buildAnyExt(I64, Index);
8617 MI.getOperand(5).setReg(NewIndex.getReg(0));
8621 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8622 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8623 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8624 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8625 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8626 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8627 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8628 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8631 if (MRI.
getType(Index) != I32)
8632 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8635 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8636 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8637 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8638 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8639 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8640 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8641 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8642 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8643 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8645 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8649 if (IndexArgTy != IdxTy) {
8650 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8651 :
B.buildAnyExt(IdxTy, Index);
8652 MI.getOperand(7).setReg(NewIndex.getReg(0));
8657 case Intrinsic::amdgcn_fmed3: {
8663 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8664 MI.removeOperand(1);
8668 case Intrinsic::amdgcn_readlane:
8669 case Intrinsic::amdgcn_writelane:
8670 case Intrinsic::amdgcn_readfirstlane:
8671 case Intrinsic::amdgcn_permlane16:
8672 case Intrinsic::amdgcn_permlanex16:
8673 case Intrinsic::amdgcn_permlane64:
8674 case Intrinsic::amdgcn_set_inactive:
8675 case Intrinsic::amdgcn_set_inactive_chain_arg:
8676 case Intrinsic::amdgcn_mov_dpp8:
8677 case Intrinsic::amdgcn_update_dpp:
8678 case Intrinsic::amdgcn_permlane_bcast:
8679 case Intrinsic::amdgcn_permlane_up:
8680 case Intrinsic::amdgcn_permlane_down:
8681 case Intrinsic::amdgcn_permlane_xor:
8683 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8685 case Intrinsic::amdgcn_dead: {
8689 MI.eraseFromParent();
8692 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8693 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8694 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8695 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8696 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8697 MI.eraseFromParent();
8699 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8700 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8701 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8702 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8703 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8704 MI.eraseFromParent();
8706 case Intrinsic::amdgcn_av_load_b128:
8707 case Intrinsic::amdgcn_av_store_b128: {
8708 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8709 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8710 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8712 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8713 **
MI.memoperands_begin());
8714 MI.eraseFromParent();
8717 case Intrinsic::amdgcn_flat_load_monitor_b32:
8718 case Intrinsic::amdgcn_flat_load_monitor_b64:
8719 case Intrinsic::amdgcn_flat_load_monitor_b128:
8720 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8721 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8722 .add(
MI.getOperand(0))
8723 .add(
MI.getOperand(2))
8724 .addMemOperand(*
MI.memoperands_begin());
8725 MI.eraseFromParent();
8727 case Intrinsic::amdgcn_global_load_monitor_b32:
8728 case Intrinsic::amdgcn_global_load_monitor_b64:
8729 case Intrinsic::amdgcn_global_load_monitor_b128:
8730 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8731 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8732 .add(
MI.getOperand(0))
8733 .add(
MI.getOperand(2))
8734 .addMemOperand(*
MI.memoperands_begin());
8735 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< 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 legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFPow(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & 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 TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void truncate(size_type N)
Like resize, but requires that N is less than size().
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
unsigned getPointerSizeInBits(unsigned AS) const
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.