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);
4616 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4617 Carry OddCarryIn = std::move(OddCarry);
4618 Carry EvenCarryIn = std::move(EvenCarry);
4623 if (2 * i < Accum.
size()) {
4624 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4625 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4630 if (!SeparateOddAlignedProducts) {
4631 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4632 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4634 bool IsHighest = 2 * i >= Accum.
size();
4637 .take_front(IsHighest ? 1 : 2);
4638 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4644 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4646 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4648 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4651 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4654 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4655 Lo->getOperand(1).getReg());
4656 Accum[2 * i] =
Hi.getReg(0);
4657 SeparateOddCarry =
Hi.getReg(1);
4664 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4665 EvenCarryIn.push_back(CarryOut);
4667 if (2 * i < Accum.
size()) {
4668 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4669 OddCarry.push_back(CarryOut);
4681 assert(ST.hasMad64_32());
4682 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4694 unsigned Size = Ty.getSizeInBits();
4695 if (ST.hasVMulU64Inst() &&
Size == 64)
4698 unsigned NumParts =
Size / 32;
4710 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4714 for (
unsigned i = 0; i < NumParts; ++i) {
4718 B.buildUnmerge(Src0Parts, Src0);
4719 B.buildUnmerge(Src1Parts, Src1);
4722 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4723 SeparateOddAlignedProducts);
4725 B.buildMergeLikeInstr(DstReg, AccumRegs);
4726 MI.eraseFromParent();
4741 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4742 ? AMDGPU::G_AMDGPU_FFBH_U32
4743 : AMDGPU::G_AMDGPU_FFBL_B32;
4744 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4747 MI.eraseFromParent();
4757 TypeSize NumBits = SrcTy.getSizeInBits();
4762 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4763 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4764 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4765 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4766 B.buildTrunc(Dst, Ctlz);
4767 MI.eraseFromParent();
4778 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4779 unsigned BitWidth = SrcTy.getSizeInBits();
4781 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4782 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4783 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4784 MI.eraseFromParent();
4790 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4793 return ConstVal == -1;
4800 Register CondDef =
MI.getOperand(0).getReg();
4819 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4828 UncondBrTarget = &*NextMBB;
4830 if (
Next->getOpcode() != AMDGPU::G_BR)
4849 *ArgRC,
B.getDebugLoc(), ArgTy);
4853 const unsigned Mask = Arg->
getMask();
4861 auto ShiftAmt =
B.buildConstant(I32, Shift);
4862 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4865 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4867 B.buildCopy(DstReg, LiveIn);
4877 if (!ST.hasClusters()) {
4880 MI.eraseFromParent();
4900 auto One =
B.buildConstant(I32, 1);
4901 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4902 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4903 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4910 B.buildCopy(DstReg, GlobalIdXYZ);
4911 MI.eraseFromParent();
4915 B.buildCopy(DstReg, ClusterIdXYZ);
4916 MI.eraseFromParent();
4921 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4923 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4924 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4926 .addImm(ClusterIdField);
4927 auto Zero =
B.buildConstant(I32, 0);
4930 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4931 MI.eraseFromParent();
4973 auto LoadConstant = [&](
unsigned N) {
4974 B.buildConstant(DstReg,
N);
4978 if (ST.hasArchitectedSGPRs() &&
4985 Arg = &WorkGroupIDX;
4986 ArgRC = &AMDGPU::SReg_32RegClass;
4990 Arg = &WorkGroupIDY;
4991 ArgRC = &AMDGPU::SReg_32RegClass;
4995 Arg = &WorkGroupIDZ;
4996 ArgRC = &AMDGPU::SReg_32RegClass;
5000 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5001 return LoadConstant(0);
5002 Arg = &ClusterWorkGroupIDX;
5003 ArgRC = &AMDGPU::SReg_32RegClass;
5007 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5008 return LoadConstant(0);
5009 Arg = &ClusterWorkGroupIDY;
5010 ArgRC = &AMDGPU::SReg_32RegClass;
5014 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5015 return LoadConstant(0);
5016 Arg = &ClusterWorkGroupIDZ;
5017 ArgRC = &AMDGPU::SReg_32RegClass;
5022 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5023 Arg = &ClusterWorkGroupMaxIDX;
5024 ArgRC = &AMDGPU::SReg_32RegClass;
5029 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5030 Arg = &ClusterWorkGroupMaxIDY;
5031 ArgRC = &AMDGPU::SReg_32RegClass;
5036 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5037 Arg = &ClusterWorkGroupMaxIDZ;
5038 ArgRC = &AMDGPU::SReg_32RegClass;
5042 Arg = &ClusterWorkGroupMaxFlatID;
5043 ArgRC = &AMDGPU::SReg_32RegClass;
5058 return LoadConstant(0);
5063 B.buildUndef(DstReg);
5067 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5079 MI.eraseFromParent();
5085 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5086 MI.eraseFromParent();
5093 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5107 B.buildUndef(DstReg);
5108 MI.eraseFromParent();
5112 if (Arg->isMasked()) {
5126 MI.eraseFromParent();
5141 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5150 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5158 Align Alignment)
const {
5162 "unexpected kernarg parameter type");
5169 MI.eraseFromParent();
5201 auto FloatY =
B.buildUITOFP(
F32,
Y);
5202 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5204 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5205 auto Z =
B.buildFPTOUI(I32, ScaledY);
5208 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5209 auto NegYZ =
B.buildMul(I32, NegY, Z);
5210 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5213 auto Q =
B.buildUMulH(I32,
X, Z);
5214 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5217 auto One =
B.buildConstant(I32, 1);
5220 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5221 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5226 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5229 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5248 auto Unmerge =
B.buildUnmerge(I32, Val);
5250 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5251 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5253 auto Mad =
B.buildFMAD(
5257 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5258 auto Mul1 =
B.buildFMul(
5262 auto Mul2 =
B.buildFMul(
5264 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5267 auto Mad2 =
B.buildFMAD(
5271 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5272 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5274 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5289 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5291 auto Zero64 =
B.buildConstant(I64, 0);
5292 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5294 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5295 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5297 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5298 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5299 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5301 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5302 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5303 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5305 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5306 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5307 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5308 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5309 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5311 auto Zero32 =
B.buildConstant(I32, 0);
5312 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5313 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5314 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5316 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5317 Register NumerLo = UnmergeNumer.getReg(0);
5318 Register NumerHi = UnmergeNumer.getReg(1);
5320 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5321 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5322 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5323 Register Mul3_Lo = UnmergeMul3.getReg(0);
5324 Register Mul3_Hi = UnmergeMul3.getReg(1);
5325 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5326 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5327 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5328 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5330 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5331 Register DenomLo = UnmergeDenom.getReg(0);
5332 Register DenomHi = UnmergeDenom.getReg(1);
5335 auto C1 =
B.buildSExt(I32, CmpHi);
5338 auto C2 =
B.buildSExt(I32, CmpLo);
5341 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5348 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5349 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5350 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5351 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5353 auto One64 =
B.buildConstant(I64, 1);
5354 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5360 auto C6 =
B.buildSelect(
5364 auto Add4 =
B.buildAdd(I64, Add3, One64);
5365 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5367 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5368 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5369 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5375 auto Sel1 =
B.buildSelect(
5382 auto Sel2 =
B.buildSelect(
5393 switch (
MI.getOpcode()) {
5396 case AMDGPU::G_UDIV: {
5397 DstDivReg =
MI.getOperand(0).getReg();
5400 case AMDGPU::G_UREM: {
5401 DstRemReg =
MI.getOperand(0).getReg();
5404 case AMDGPU::G_UDIVREM: {
5405 DstDivReg =
MI.getOperand(0).getReg();
5406 DstRemReg =
MI.getOperand(1).getReg();
5413 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5414 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5415 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5425 MI.eraseFromParent();
5436 if (Ty != I32 && Ty != I64)
5439 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5440 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5441 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5443 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5444 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5445 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5447 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5448 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5450 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5451 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5453 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5454 switch (
MI.getOpcode()) {
5457 case AMDGPU::G_SDIV: {
5458 DstDivReg =
MI.getOperand(0).getReg();
5462 case AMDGPU::G_SREM: {
5463 DstRemReg =
MI.getOperand(0).getReg();
5467 case AMDGPU::G_SDIVREM: {
5468 DstDivReg =
MI.getOperand(0).getReg();
5469 DstRemReg =
MI.getOperand(1).getReg();
5482 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5483 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5484 B.buildSub(DstDivReg, SignXor, Sign);
5488 auto Sign = LHSign.getReg(0);
5489 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5490 B.buildSub(DstRemReg, SignXor, Sign);
5493 MI.eraseFromParent();
5509 if (!AllowInaccurateRcp && ResTy !=
F16)
5520 if (CLHS->isOne()) {
5521 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5525 MI.eraseFromParent();
5530 if (CLHS->isMinusOne()) {
5531 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5532 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5533 .addUse(FNeg.getReg(0))
5536 MI.eraseFromParent();
5543 if (!AllowInaccurateRcp &&
5548 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5551 B.buildFMul(Res, LHS, RCP, Flags);
5553 MI.eraseFromParent();
5568 if (!AllowInaccurateRcp)
5576 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5578 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5579 auto One =
B.buildFConstant(ResTy, 1.0);
5581 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5585 R =
B.buildFNeg(ResTy, R);
5587 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5588 R =
B.buildFMA(ResTy, Tmp0, R, R);
5590 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5591 R =
B.buildFMA(ResTy, Tmp1, R, R);
5594 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5595 B.buildCopy(Res, R);
5596 MI.eraseFromParent();
5600 auto Ret =
B.buildFMul(ResTy,
X, R);
5601 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5603 B.buildFMA(Res, Tmp2, R, Ret);
5604 MI.eraseFromParent();
5635 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5636 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5637 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5638 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5639 .addUse(RHSExt.getReg(0))
5641 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5643 if (ST.hasMadMacF32Insts()) {
5644 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5645 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5646 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5648 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5649 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5650 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5652 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5653 auto TmpInt =
B.buildBitcast(I32, Tmp);
5654 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5655 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5656 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5657 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5658 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5659 .addUse(RDst.getReg(0))
5664 MI.eraseFromParent();
5677 unsigned SPDenormMode =
5680 if (ST.hasDenormModeInst()) {
5682 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5684 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5685 B.buildInstr(AMDGPU::S_DENORM_MODE)
5686 .addImm(NewDenormModeValue);
5689 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5690 .addImm(SPDenormMode)
5711 auto One =
B.buildFConstant(
F32, 1.0f);
5713 auto DenominatorScaled =
5714 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5719 auto NumeratorScaled =
5720 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5726 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5727 .addUse(DenominatorScaled.getReg(0))
5729 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5732 const bool HasDynamicDenormals =
5737 if (!PreservesDenormals) {
5738 if (HasDynamicDenormals) {
5740 B.buildInstr(AMDGPU::S_GETREG_B32)
5741 .addDef(SavedSPDenormMode)
5747 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5748 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5749 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5750 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5751 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5752 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5754 if (!PreservesDenormals) {
5755 if (HasDynamicDenormals) {
5756 assert(SavedSPDenormMode);
5757 B.buildInstr(AMDGPU::S_SETREG_B32)
5758 .addReg(SavedSPDenormMode)
5764 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5765 .addUse(Fma4.getReg(0))
5766 .addUse(Fma1.getReg(0))
5767 .addUse(Fma3.getReg(0))
5768 .addUse(NumeratorScaled.getReg(1))
5771 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5772 .addUse(Fmas.getReg(0))
5777 MI.eraseFromParent();
5795 auto One =
B.buildFConstant(
F64, 1.0);
5797 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5803 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5805 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5806 .addUse(DivScale0.getReg(0))
5809 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5810 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5811 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5813 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5819 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5820 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5821 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5824 if (!ST.hasUsableDivScaleConditionOutput()) {
5831 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5832 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5833 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5834 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5837 Scale1Unmerge.getReg(1));
5839 Scale0Unmerge.getReg(1));
5840 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5842 Scale = DivScale1.getReg(1);
5845 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5846 .addUse(Fma4.getReg(0))
5847 .addUse(Fma3.getReg(0))
5848 .addUse(
Mul.getReg(0))
5852 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5853 .addUse(Fmas.getReg(0))
5858 MI.eraseFromParent();
5873 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5876 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5880 if (ST.hasFractBug()) {
5881 auto Fabs =
B.buildFAbs(Ty, Val);
5885 auto Zero =
B.buildConstant(InstrExpTy, 0);
5886 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5887 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5890 B.buildCopy(Res0, Mant);
5891 B.buildSExtOrTrunc(Res1, Exp);
5893 MI.eraseFromParent();
5907 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5910 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5911 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5912 auto C2 =
B.buildFConstant(
F32, 1.0f);
5915 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5917 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5919 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5920 .addUse(Mul0.getReg(0))
5923 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5925 B.buildFMul(Res, Sel, Mul1, Flags);
5927 MI.eraseFromParent();
5936 unsigned Flags =
MI.getFlags();
5937 assert(!ST.has16BitInsts());
5938 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5939 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5940 .addUse(Ext.getReg(0))
5942 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5943 MI.eraseFromParent();
5953 const unsigned Flags =
MI.getFlags();
5961 MI.eraseFromParent();
5965 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5967 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5968 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5969 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5974 .addUse(SqrtX.getReg(0))
5977 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5978 auto NegOne =
B.buildConstant(I32, -1);
5979 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5981 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5982 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5984 auto PosOne =
B.buildConstant(I32, 1);
5985 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5987 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5988 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
5990 auto Zero =
B.buildFConstant(
F32, 0.0f);
5994 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
5998 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6001 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6002 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6004 auto Half =
B.buildFConstant(
F32, 0.5f);
6005 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6006 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6007 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6008 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6009 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6010 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6011 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6012 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6015 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6017 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6019 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6022 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6024 MI.eraseFromParent();
6058 unsigned Flags =
MI.getFlags();
6063 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6065 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6069 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6070 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6071 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6074 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6076 auto Half =
B.buildFConstant(
F64, 0.5);
6077 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6078 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6080 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6081 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6083 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6084 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6086 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6087 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6089 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6091 Register SqrtRet = SqrtS2.getReg(0);
6093 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6094 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6095 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6098 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6099 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6100 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6105 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6108 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6114 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6116 MI.eraseFromParent();
6147 auto Flags =
MI.getFlags();
6159 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6169 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6170 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6175 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6177 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6178 MI.eraseFromParent();
6190 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6191 IID == Intrinsic::amdgcn_permlanex16;
6192 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6193 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6194 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6195 IID == Intrinsic::amdgcn_permlane_up ||
6196 IID == Intrinsic::amdgcn_permlane_down ||
6197 IID == Intrinsic::amdgcn_permlane_xor;
6201 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6203 case Intrinsic::amdgcn_readfirstlane:
6204 case Intrinsic::amdgcn_permlane64:
6205 return LaneOp.getReg(0);
6206 case Intrinsic::amdgcn_readlane:
6207 case Intrinsic::amdgcn_set_inactive:
6208 case Intrinsic::amdgcn_set_inactive_chain_arg:
6209 return LaneOp.addUse(Src1).getReg(0);
6210 case Intrinsic::amdgcn_writelane:
6211 case Intrinsic::amdgcn_permlane_bcast:
6212 case Intrinsic::amdgcn_permlane_up:
6213 case Intrinsic::amdgcn_permlane_down:
6214 case Intrinsic::amdgcn_permlane_xor:
6215 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6216 case Intrinsic::amdgcn_permlane16:
6217 case Intrinsic::amdgcn_permlanex16: {
6219 int64_t Src4 =
MI.getOperand(6).getImm();
6220 int64_t Src5 =
MI.getOperand(7).getImm();
6221 return LaneOp.addUse(Src1)
6228 case Intrinsic::amdgcn_mov_dpp8:
6229 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6230 case Intrinsic::amdgcn_update_dpp:
6231 return LaneOp.addUse(Src1)
6232 .addImm(
MI.getOperand(4).getImm())
6233 .addImm(
MI.getOperand(5).getImm())
6234 .addImm(
MI.getOperand(6).getImm())
6235 .addImm(
MI.getOperand(7).getImm())
6245 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6246 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6247 IsPermlaneShuffle) {
6248 Src1 =
MI.getOperand(3).getReg();
6249 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6250 IsPermlaneShuffle) {
6251 Src2 =
MI.getOperand(4).getReg();
6256 unsigned Size = Ty.getSizeInBits();
6258 unsigned SplitSize = 32;
6259 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6260 ST.hasDPALU_DPP() &&
6264 if (
Size == SplitSize) {
6271 bool IsFloat = Ty.getScalarType().isFloat();
6275 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6277 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6279 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6283 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6285 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6286 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6288 if (IID == Intrinsic::amdgcn_writelane)
6289 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6291 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6293 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6295 B.buildTrunc(DstReg, LaneOpDst);
6296 MI.eraseFromParent();
6300 if (
Size % SplitSize != 0)
6304 bool NeedsBitcast =
false;
6305 if (IntTy.isVector()) {
6308 if (EltSize == SplitSize) {
6309 PartialResTy = EltTy;
6310 }
else if (EltSize == 16 || EltSize == 32) {
6311 unsigned NElem = SplitSize / EltSize;
6314 NeedsBitcast =
true;
6319 unsigned NumParts =
Size / SplitSize;
6323 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6324 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6326 if (IID == Intrinsic::amdgcn_writelane)
6327 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6329 for (
unsigned i = 0; i < NumParts; ++i) {
6330 Src0 = Src0Parts.
getReg(i);
6332 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6333 Src1 = Src1Parts.
getReg(i);
6335 if (IID == Intrinsic::amdgcn_writelane)
6336 Src2 = Src2Parts.
getReg(i);
6338 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6341 if (NeedsBitcast || IsFloat)
6344 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6346 B.buildMergeLikeInstr(DstReg, PartialRes);
6348 MI.eraseFromParent();
6356 ST.getTargetLowering()->getImplicitParameterOffset(
6366 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6367 B.buildConstant(IdxTy,
Offset).getReg(0));
6378 Register Pointer =
MI.getOperand(2).getReg();
6380 Register NumRecords =
MI.getOperand(4).getReg();
6386 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6388 auto ExtStride =
B.buildAnyExt(I32, Stride);
6390 if (ST.has45BitNumRecordsBufferResource()) {
6391 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6393 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6395 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6399 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6400 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6401 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6402 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6406 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6407 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6408 auto ExtShiftedStride =
6409 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6410 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6411 auto ExtShiftedFlags =
6412 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6413 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6415 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6416 B.buildMergeValues(Result, {LowHalf, HighHalf});
6418 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6419 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6420 auto LowHalf = Unmerge.getReg(0);
6421 auto HighHalf = Unmerge.getReg(1);
6423 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6424 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6425 auto ShiftConst =
B.buildConstant(I32, 16);
6426 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6427 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6428 Register NewHighHalfReg = NewHighHalf.getReg(0);
6429 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6432 MI.eraseFromParent();
6449 MI.eraseFromParent();
6457 std::optional<uint32_t> KnownSize =
6459 if (KnownSize.has_value())
6460 B.buildConstant(DstReg, *KnownSize);
6478 MI.eraseFromParent();
6485 unsigned AddrSpace)
const {
6487 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6491 ST.hasGloballyAddressableScratch()) {
6493 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6494 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6496 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6498 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6500 B.buildConstant(I32, 1u << 26));
6505 MI.eraseFromParent();
6515std::pair<Register, unsigned>
6527 bool CheckNUW = ST.hasGFX1250Insts();
6529 MRI, OrigOffset,
nullptr, CheckNUW);
6533 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6543 unsigned Overflow = ImmOffset & ~MaxImm;
6544 ImmOffset -= Overflow;
6545 if ((int32_t)Overflow < 0) {
6546 Overflow += ImmOffset;
6550 if (Overflow != 0) {
6552 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6554 auto OverflowVal =
B.buildConstant(I32, Overflow);
6555 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6560 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6562 return std::pair(BaseReg, ImmOffset);
6569 bool ImageStore)
const {
6577 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6579 if (ST.hasUnpackedD16VMem()) {
6580 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6583 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6584 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6592 if (ImageStore && ST.hasImageStoreD16Bug()) {
6595 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6597 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6604 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6605 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6607 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6615 auto Unmerge =
B.buildUnmerge(I32, Reg);
6616 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6618 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6628 Reg =
B.buildPadVectorWithUndefElements(
6637 bool IsFormat)
const {
6647 VData =
B.buildBitcast(Ty, VData).getReg(0);
6655 if (Ty.isVector()) {
6656 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6668 bool IsFormat)
const {
6675 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6682 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6683 const Function &Fn =
B.getMF().getFunction();
6685 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6686 MI.eraseFromParent();
6698 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6701 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6705 VIndex =
MI.getOperand(3).getReg();
6708 VIndex =
B.buildConstant(I32, 0).getReg(0);
6711 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6712 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6716 Format =
MI.getOperand(5 + OpOffset).getImm();
6720 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6726 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6727 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6728 }
else if (IsFormat) {
6729 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6730 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6734 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6737 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6740 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6745 auto MIB =
B.buildInstr(
Opc)
6756 MIB.addImm(AuxiliaryData)
6757 .addImm(HasVIndex ? -1 : 0)
6758 .addMemOperand(MMO);
6760 MI.eraseFromParent();
6766 unsigned ImmOffset,
unsigned Format,
6769 auto MIB =
B.buildInstr(
Opc)
6780 MIB.addImm(AuxiliaryData)
6781 .addImm(HasVIndex ? -1 : 0)
6782 .addMemOperand(MMO);
6788 bool IsTyped)
const {
6802 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6803 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6805 StatusDst =
MI.getOperand(1).getReg();
6810 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6813 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6816 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6819 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6822 VIndex =
B.buildConstant(I32, 0).getReg(0);
6825 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6826 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6830 Format =
MI.getOperand(5 + OpOffset).getImm();
6834 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6844 Dst =
MI.getOperand(0).getReg();
6845 B.setInsertPt(
B.getMBB(),
MI);
6852 Dst =
MI.getOperand(0).getReg();
6853 B.setInsertPt(
B.getMBB(),
MI);
6857 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6858 const bool Unpacked = ST.hasUnpackedD16VMem();
6860 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6861 const Function &Fn =
B.getMF().getFunction();
6863 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6866 B.buildUndef(StatusDst);
6867 MI.eraseFromParent();
6879 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6880 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6881 }
else if (IsFormat) {
6885 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6887 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6888 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6893 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6894 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6897 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6898 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6901 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6902 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6908 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6909 unsigned NumLoadDWords = NumValueDWords + 1;
6911 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6913 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6914 bool IsFloat = Ty.getScalarType().isFloat();
6919 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6921 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6922 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6923 B.buildTrunc(DstInt, ExtDst);
6924 }
else if (NumValueDWords == 1) {
6925 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6928 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6929 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6931 B.buildUnmerge(LoadElts, LoadDstReg);
6933 B.buildMergeLikeInstr(DstInt, LoadElts);
6936 B.buildBitcast(Dst, DstInt);
6938 (IsD16 && !Ty.isVector())) {
6939 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6941 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6942 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6943 B.buildTrunc(Dst, LoadDstReg);
6944 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6946 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6948 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6949 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6951 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6953 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6954 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6955 B.buildMergeLikeInstr(Dst, Repack);
6958 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6961 MI.eraseFromParent();
6967 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6968 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6969 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6970 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6971 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6972 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6973 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6974 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6975 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6976 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6977 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6978 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6979 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6980 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6981 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6982 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6983 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6984 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6985 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6986 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6987 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6988 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6989 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6990 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
6991 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
6992 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
6993 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
6994 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
6995 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
6996 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
6997 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
6998 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
6999 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7000 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7001 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7002 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7003 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7004 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7005 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7006 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7007 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7008 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7009 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7010 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7011 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7012 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7013 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7014 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7015 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7016 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7017 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7018 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7019 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7020 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7021 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7022 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7023 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7024 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7025 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7026 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7027 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7028 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7029 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7030 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7031 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7032 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7033 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7034 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7036 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7037 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7038 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7039 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7040 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7041 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7042 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7043 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7044 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7045 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7046 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7047 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7048 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7049 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7050 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7051 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7052 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7053 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7054 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7055 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7056 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7065 const bool IsCmpSwap =
7066 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7067 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7068 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7069 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7080 CmpVal =
MI.getOperand(3).getReg();
7085 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7086 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7089 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7092 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7098 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7099 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7100 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7119 .addImm(AuxiliaryData)
7120 .addImm(HasVIndex ? -1 : 0)
7121 .addMemOperand(MMO);
7123 MI.eraseFromParent();
7133 bool IsA16,
bool IsG16) {
7147 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7152 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7156 "Bias needs to be converted to 16 bit in A16 mode");
7158 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7162 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7166 if (((
I + 1) >= EndIdx) ||
7173 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7175 B.buildBuildVector(V2EltTy,
7176 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7181 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7192 int DimIdx,
int NumVAddrs) {
7194 for (
int I = 0;
I != NumVAddrs; ++
I) {
7196 if (
SrcOp.isReg()) {
7199 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7200 if (
B.getMRI()->getType(
Reg) != I32)
7201 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7206 int NumAddrRegs = AddrRegs.
size();
7207 if (NumAddrRegs != 1) {
7208 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7211 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7214 for (
int I = 1;
I != NumVAddrs; ++
I) {
7217 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7239 const unsigned NumDefs =
MI.getNumExplicitDefs();
7240 const unsigned ArgOffset = NumDefs + 1;
7241 bool IsTFE = NumDefs == 2;
7259 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7263 const bool IsAtomicPacked16Bit =
7264 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7265 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7272 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7273 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7274 const bool DataTyIs16 =
7275 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7277 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7278 const bool IsA16 = AddrTyIs16;
7279 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7282 if (!BaseOpcode->
Atomic) {
7283 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7286 }
else if (DMask != 0) {
7288 }
else if (!IsTFE && !BaseOpcode->
Store) {
7290 B.buildUndef(
MI.getOperand(0));
7291 MI.eraseFromParent();
7299 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7300 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7301 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7302 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7303 unsigned NewOpcode = LoadOpcode;
7304 if (BaseOpcode->
Store)
7305 NewOpcode = StoreOpcode;
7307 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7310 MI.setDesc(
B.getTII().get(NewOpcode));
7314 if (IsTFE && DMask == 0) {
7317 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7320 if (BaseOpcode->
Atomic) {
7325 if (Ty.isVector() && !IsAtomicPacked16Bit)
7332 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7333 MI.getOperand(2).setReg(
Concat.getReg(0));
7334 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7338 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7341 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7347 if (IsA16 && !ST.hasA16()) {
7352 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7353 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7355 if (IsA16 || IsG16) {
7363 const bool UseNSA = ST.hasNSAEncoding() &&
7364 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7365 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7366 const bool UsePartialNSA =
7367 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7369 if (UsePartialNSA) {
7373 auto Concat =
B.buildConcatVectors(
7374 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7375 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7376 PackedRegs.
resize(NSAMaxSize);
7377 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7379 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7380 PackedRegs[0] =
Concat.getReg(0);
7384 const unsigned NumPacked = PackedRegs.
size();
7387 if (!
SrcOp.isReg()) {
7397 SrcOp.setReg(AMDGPU::NoRegister);
7414 const bool UseNSA = ST.hasNSAEncoding() &&
7415 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7416 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7417 const bool UsePartialNSA =
7418 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7420 if (UsePartialNSA) {
7422 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7424 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7439 if (!Ty.isVector() || !IsD16)
7443 if (RepackedReg != VData) {
7444 MI.getOperand(1).setReg(RepackedReg);
7452 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7455 if (NumElts < DMaskLanes)
7458 if (NumElts > 4 || DMaskLanes > 4)
7469 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7470 const LLT AdjustedTy =
7486 if (IsD16 && ST.hasUnpackedD16VMem()) {
7493 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7494 unsigned RoundedSize = 32 * RoundedElts;
7498 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7503 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7509 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7513 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7514 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7518 MI.getOperand(0).setReg(NewResultReg);
7526 Dst1Reg =
MI.getOperand(1).getReg();
7527 if (MRI->
getType(Dst1Reg) != I32)
7531 MI.removeOperand(1);
7534 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7535 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7536 B.buildBitcast(DstReg, Unmerge.getReg(0));
7537 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7546 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7548 if (ResultNumRegs == 1) {
7550 ResultRegs[0] = NewResultReg;
7553 for (
int I = 0;
I != NumDataRegs; ++
I)
7555 B.buildUnmerge(ResultRegs, NewResultReg);
7560 ResultRegs.
resize(NumDataRegs);
7565 if (IsD16 && !Ty.isVector()) {
7566 B.buildTrunc(DstReg, ResultRegs[0]);
7571 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7572 !ST.hasUnpackedD16VMem()) {
7573 B.buildBitcast(DstReg, ResultRegs[0]);
7585 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7587 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7588 }
else if (ST.hasUnpackedD16VMem()) {
7590 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7594 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7598 for (
int I = 0;
I != NumElts; ++
I)
7605 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7606 B.buildBuildVector(DstReg, ResultRegs);
7610 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7611 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7616 if (Ty == V3I16 || Ty == V3F16) {
7618 if (ResultRegs.
size() == 1) {
7619 NewResultReg = ResultRegs[0];
7620 }
else if (ResultRegs.
size() == 2) {
7622 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7637 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7639 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7641 if (ResizeDst != DstReg)
7642 B.buildBitcast(DstReg, ResizeDst);
7646 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7647 B.buildConcatVectors(DstReg, ResultRegs);
7656 Register OrigDst =
MI.getOperand(0).getReg();
7658 LLT Ty =
B.getMRI()->getType(OrigDst);
7659 unsigned Size = Ty.getSizeInBits();
7661 bool HasMMO = !
MI.memoperands_empty();
7663 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7665 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7666 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7669 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7671 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7680 B.setInsertPt(
B.getMBB(),
MI);
7685 B.setInsertPt(
B.getMBB(),
MI);
7688 MI.setDesc(
B.getTII().get(
Opc));
7689 MI.removeOperand(1);
7695 const unsigned MemSize = (
Size + 7) / 8;
7696 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7703 MI.addMemOperand(MF, MMO);
7705 if (Dst != OrigDst) {
7706 MI.getOperand(0).setReg(Dst);
7707 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7708 B.buildTrunc(OrigDst, Dst);
7730 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7731 MI.removeOperand(0);
7741 if (!ST.hasTrapHandler() ||
7745 return ST.supportsGetDoorbellID() ?
7758 MI.eraseFromParent();
7768 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7770 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7774 MI.eraseFromParent();
7783 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7790 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7810 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7813 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7814 B.buildCopy(SGPR01, Temp);
7815 B.buildInstr(AMDGPU::S_TRAP)
7818 MI.eraseFromParent();
7829 B.buildCopy(SGPR01, LiveIn);
7830 B.buildInstr(AMDGPU::S_TRAP)
7834 MI.eraseFromParent();
7843 if (ST.hasPrivEnabledTrap2NopBug()) {
7844 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7846 MI.eraseFromParent();
7850 B.buildInstr(AMDGPU::S_TRAP)
7852 MI.eraseFromParent();
7861 if (!ST.hasTrapHandler() ||
7865 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7868 B.buildInstr(AMDGPU::S_TRAP)
7872 MI.eraseFromParent();
7886 Register NodePtr =
MI.getOperand(2).getReg();
7887 Register RayExtent =
MI.getOperand(3).getReg();
7888 Register RayOrigin =
MI.getOperand(4).getReg();
7890 Register RayInvDir =
MI.getOperand(6).getReg();
7893 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7900 const unsigned NumVDataDwords = 4;
7901 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7902 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7904 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7906 const unsigned BaseOpcodes[2][2] = {
7907 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7908 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7909 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7913 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7914 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7915 : AMDGPU::MIMGEncGfx10NSA,
7916 NumVDataDwords, NumVAddrDwords);
7920 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7921 : AMDGPU::MIMGEncGfx10Default,
7922 NumVDataDwords, NumVAddrDwords);
7927 if (UseNSA && IsGFX11Plus) {
7928 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7929 auto SrcInt =
B.buildBitcast(V3I32, Src);
7930 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7931 auto Merged =
B.buildMergeLikeInstr(
7932 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7933 Ops.push_back(Merged.getReg(0));
7936 Ops.push_back(NodePtr);
7937 Ops.push_back(RayExtent);
7938 packLanes(RayOrigin);
7941 auto UnmergeRayDir =
7942 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7943 auto UnmergeRayInvDir =
7944 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7945 auto MergedDir =
B.buildMergeLikeInstr(
7948 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7949 UnmergeRayDir.getReg(0)}))
7952 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7953 UnmergeRayDir.getReg(1)}))
7956 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7957 UnmergeRayDir.getReg(2)}))
7959 Ops.push_back(MergedDir.getReg(0));
7962 packLanes(RayInvDir);
7966 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7967 Ops.push_back(Unmerge.getReg(0));
7968 Ops.push_back(Unmerge.getReg(1));
7970 Ops.push_back(NodePtr);
7972 Ops.push_back(RayExtent);
7974 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7975 auto SrcInt =
B.buildBitcast(V3I32, Src);
7976 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7977 Ops.push_back(Unmerge.getReg(0));
7978 Ops.push_back(Unmerge.getReg(1));
7979 Ops.push_back(Unmerge.getReg(2));
7982 packLanes(RayOrigin);
7984 auto UnmergeRayDir =
7985 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7986 auto UnmergeRayInvDir =
7987 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7991 B.buildMergeLikeInstr(R1,
7992 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
7993 B.buildMergeLikeInstr(
7994 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
7995 B.buildMergeLikeInstr(
7996 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8002 packLanes(RayInvDir);
8011 Ops.push_back(MergedOps);
8014 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8023 .addImm(IsA16 ? 1 : 0)
8026 MI.eraseFromParent();
8036 Register DstOrigin =
MI.getOperand(1).getReg();
8038 Register NodePtr =
MI.getOperand(4).getReg();
8039 Register RayExtent =
MI.getOperand(5).getReg();
8040 Register InstanceMask =
MI.getOperand(6).getReg();
8041 Register RayOrigin =
MI.getOperand(7).getReg();
8043 Register Offsets =
MI.getOperand(9).getReg();
8044 Register TDescr =
MI.getOperand(10).getReg();
8047 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8048 const unsigned NumVDataDwords = 10;
8049 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8051 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8052 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8053 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8056 auto RayExtentInstanceMaskVec =
8057 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8058 B.buildAnyExt(I32, InstanceMask)});
8060 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8061 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8067 .addUse(RayExtentInstanceMaskVec.getReg(0))
8074 MI.eraseFromParent();
8083 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8084 MI.eraseFromParent();
8091 if (!ST.hasArchitectedSGPRs())
8095 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8096 auto LSB =
B.buildConstant(I32, 25);
8097 auto Width =
B.buildConstant(I32, 5);
8098 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8099 MI.eraseFromParent();
8107 unsigned Width)
const {
8111 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8112 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8115 MI.eraseFromParent();
8135 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8139 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8142 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8143 MI.eraseFromParent();
8156 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8160 .addReg(Unmerge.getReg(0));
8164 .addReg(Unmerge.getReg(1));
8165 MI.eraseFromParent();
8177 case Intrinsic::amdgcn_icmp: {
8188 if (!Src1Const || Src1Const->Value != 0)
8192 int64_t Pred =
MI.getOperand(4).getImm();
8198 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8199 MI.eraseFromParent();
8202 case Intrinsic::sponentry:
8208 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8211 B.buildIntToPtr(DstReg, TmpReg);
8212 MI.eraseFromParent();
8214 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8216 B.buildFrameIndex(
MI.getOperand(0), FI);
8217 MI.eraseFromParent();
8220 case Intrinsic::amdgcn_if:
8221 case Intrinsic::amdgcn_else: {
8224 bool Negated =
false;
8236 std::swap(CondBrTarget, UncondBrTarget);
8238 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8239 if (IntrID == Intrinsic::amdgcn_if) {
8240 B.buildInstr(AMDGPU::SI_IF)
8243 .addMBB(UncondBrTarget);
8245 B.buildInstr(AMDGPU::SI_ELSE)
8248 .addMBB(UncondBrTarget);
8257 B.buildBr(*CondBrTarget);
8262 MI.eraseFromParent();
8263 BrCond->eraseFromParent();
8269 case Intrinsic::amdgcn_loop: {
8272 bool Negated =
false;
8282 std::swap(CondBrTarget, UncondBrTarget);
8284 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8285 B.buildInstr(AMDGPU::SI_LOOP)
8287 .addMBB(UncondBrTarget);
8292 B.buildBr(*CondBrTarget);
8294 MI.eraseFromParent();
8295 BrCond->eraseFromParent();
8302 case Intrinsic::amdgcn_wave_reduce_min:
8303 case Intrinsic::amdgcn_wave_reduce_umin:
8304 case Intrinsic::amdgcn_wave_reduce_fmin:
8305 case Intrinsic::amdgcn_wave_reduce_max:
8306 case Intrinsic::amdgcn_wave_reduce_umax:
8307 case Intrinsic::amdgcn_wave_reduce_fmax:
8308 case Intrinsic::amdgcn_wave_reduce_add:
8309 case Intrinsic::amdgcn_wave_reduce_fadd:
8310 case Intrinsic::amdgcn_wave_reduce_sub:
8311 case Intrinsic::amdgcn_wave_reduce_fsub:
8312 case Intrinsic::amdgcn_wave_reduce_and:
8313 case Intrinsic::amdgcn_wave_reduce_or:
8314 case Intrinsic::amdgcn_wave_reduce_xor: {
8319 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8320 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8321 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8322 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8323 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8324 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8325 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8326 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8327 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8334 .addUse(Ext.getReg(0))
8335 .addImm(
MI.getOperand(3).getImm());
8337 B.buildFPTrunc(DstReg, NewDst);
8339 B.buildTrunc(DstReg, NewDst);
8340 MI.eraseFromParent();
8343 case Intrinsic::amdgcn_addrspacecast_nonnull:
8345 case Intrinsic::amdgcn_make_buffer_rsrc:
8347 case Intrinsic::amdgcn_kernarg_segment_ptr:
8350 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8351 MI.eraseFromParent();
8357 case Intrinsic::amdgcn_implicitarg_ptr:
8359 case Intrinsic::amdgcn_workitem_id_x:
8362 case Intrinsic::amdgcn_workitem_id_y:
8365 case Intrinsic::amdgcn_workitem_id_z:
8368 case Intrinsic::amdgcn_workgroup_id_x:
8373 case Intrinsic::amdgcn_workgroup_id_y:
8378 case Intrinsic::amdgcn_workgroup_id_z:
8383 case Intrinsic::amdgcn_cluster_id_x:
8384 return ST.hasClusters() &&
8387 case Intrinsic::amdgcn_cluster_id_y:
8388 return ST.hasClusters() &&
8391 case Intrinsic::amdgcn_cluster_id_z:
8392 return ST.hasClusters() &&
8395 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8396 return ST.hasClusters() &&
8399 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8400 return ST.hasClusters() &&
8403 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8404 return ST.hasClusters() &&
8407 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8408 return ST.hasClusters() &&
8410 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8411 return ST.hasClusters() &&
8414 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8415 return ST.hasClusters() &&
8418 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8419 return ST.hasClusters() &&
8422 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8423 return ST.hasClusters() &&
8427 case Intrinsic::amdgcn_wave_id:
8429 case Intrinsic::amdgcn_lds_kernel_id:
8432 case Intrinsic::amdgcn_dispatch_ptr:
8435 case Intrinsic::amdgcn_queue_ptr:
8438 case Intrinsic::amdgcn_implicit_buffer_ptr:
8441 case Intrinsic::amdgcn_dispatch_id:
8444 case Intrinsic::r600_read_ngroups_x:
8448 case Intrinsic::r600_read_ngroups_y:
8451 case Intrinsic::r600_read_ngroups_z:
8454 case Intrinsic::r600_read_local_size_x:
8457 case Intrinsic::r600_read_local_size_y:
8461 case Intrinsic::r600_read_local_size_z:
8464 case Intrinsic::amdgcn_fdiv_fast:
8466 case Intrinsic::amdgcn_is_shared:
8468 case Intrinsic::amdgcn_is_private:
8470 case Intrinsic::amdgcn_wavefrontsize: {
8471 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8472 MI.eraseFromParent();
8475 case Intrinsic::amdgcn_s_buffer_load:
8476 case Intrinsic::amdgcn_ptr_s_buffer_load:
8478 case Intrinsic::amdgcn_raw_buffer_store:
8479 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8480 case Intrinsic::amdgcn_struct_buffer_store:
8481 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8483 case Intrinsic::amdgcn_raw_buffer_store_format:
8484 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8485 case Intrinsic::amdgcn_struct_buffer_store_format:
8486 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8488 case Intrinsic::amdgcn_raw_tbuffer_store:
8489 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8490 case Intrinsic::amdgcn_struct_tbuffer_store:
8491 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8493 case Intrinsic::amdgcn_raw_buffer_load:
8494 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8495 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8496 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8497 case Intrinsic::amdgcn_struct_buffer_load:
8498 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8499 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8500 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8502 case Intrinsic::amdgcn_raw_buffer_load_format:
8503 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8504 case Intrinsic::amdgcn_struct_buffer_load_format:
8505 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8507 case Intrinsic::amdgcn_raw_tbuffer_load:
8508 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8509 case Intrinsic::amdgcn_struct_tbuffer_load:
8510 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8512 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8513 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8514 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8515 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8516 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8517 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8518 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8519 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8520 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8521 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8522 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8523 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8524 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8525 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8526 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8527 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8528 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8529 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8530 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8531 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8532 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8533 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8534 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8535 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8536 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8537 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8538 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8539 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8540 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8541 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8542 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8543 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8544 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8545 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8546 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8547 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8548 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8549 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8550 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8551 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8552 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8553 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8554 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8555 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8556 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8557 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8558 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8559 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8560 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8561 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8562 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8563 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8564 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8565 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8566 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8567 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8568 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8569 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8570 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8571 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8572 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8573 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8574 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8575 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8576 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8577 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8578 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8579 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8580 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8581 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8582 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8583 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8585 case Intrinsic::amdgcn_rsq_clamp:
8587 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8589 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8590 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8592 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8593 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8594 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8595 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8596 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8597 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8598 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8599 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8603 if (IndexArgTy != I64) {
8604 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8605 :
B.buildAnyExt(I64, Index);
8606 MI.getOperand(5).setReg(NewIndex.getReg(0));
8610 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8611 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8612 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8613 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8614 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8615 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8616 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8617 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8620 if (MRI.
getType(Index) != I32)
8621 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8624 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8625 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8626 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8627 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8628 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8629 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8630 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8631 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8632 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8634 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8638 if (IndexArgTy != IdxTy) {
8639 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8640 :
B.buildAnyExt(IdxTy, Index);
8641 MI.getOperand(7).setReg(NewIndex.getReg(0));
8646 case Intrinsic::amdgcn_fmed3: {
8652 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8653 MI.removeOperand(1);
8657 case Intrinsic::amdgcn_readlane:
8658 case Intrinsic::amdgcn_writelane:
8659 case Intrinsic::amdgcn_readfirstlane:
8660 case Intrinsic::amdgcn_permlane16:
8661 case Intrinsic::amdgcn_permlanex16:
8662 case Intrinsic::amdgcn_permlane64:
8663 case Intrinsic::amdgcn_set_inactive:
8664 case Intrinsic::amdgcn_set_inactive_chain_arg:
8665 case Intrinsic::amdgcn_mov_dpp8:
8666 case Intrinsic::amdgcn_update_dpp:
8667 case Intrinsic::amdgcn_permlane_bcast:
8668 case Intrinsic::amdgcn_permlane_up:
8669 case Intrinsic::amdgcn_permlane_down:
8670 case Intrinsic::amdgcn_permlane_xor:
8672 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8674 case Intrinsic::amdgcn_dead: {
8678 MI.eraseFromParent();
8681 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8682 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8683 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8684 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8685 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8686 MI.eraseFromParent();
8688 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8689 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8690 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8691 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8692 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8693 MI.eraseFromParent();
8695 case Intrinsic::amdgcn_av_load_b128:
8696 case Intrinsic::amdgcn_av_store_b128: {
8697 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8698 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8699 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8701 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8702 **
MI.memoperands_begin());
8703 MI.eraseFromParent();
8706 case Intrinsic::amdgcn_flat_load_monitor_b32:
8707 case Intrinsic::amdgcn_flat_load_monitor_b64:
8708 case Intrinsic::amdgcn_flat_load_monitor_b128:
8709 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8710 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8711 .add(
MI.getOperand(0))
8712 .add(
MI.getOperand(2))
8713 .addMemOperand(*
MI.memoperands_begin());
8714 MI.eraseFromParent();
8716 case Intrinsic::amdgcn_global_load_monitor_b32:
8717 case Intrinsic::amdgcn_global_load_monitor_b64:
8718 case Intrinsic::amdgcn_global_load_monitor_b128:
8719 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8720 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8721 .add(
MI.getOperand(0))
8722 .add(
MI.getOperand(2))
8723 .addMemOperand(*
MI.memoperands_begin());
8724 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 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.