36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
488 if (!ST.hasDwordx3LoadStores())
501 if (AlignBits < MemSize) {
504 Align(AlignBits / 8)))
534 const unsigned Size = Ty.getSizeInBits();
535 if (Ty.isPointerVector())
545 unsigned EltSize = Ty.getScalarSizeInBits();
546 return EltSize != 32 && EltSize != 64;
560 const unsigned Size = Ty.getSizeInBits();
561 if (
Size != MemSizeInBits)
562 return Size <= 32 && Ty.isVector();
568 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
577 uint64_t AlignInBits,
unsigned AddrSpace,
587 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
598 if (AlignInBits < RoundedSize)
605 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
617 Query.
Types[1].getAddressSpace(), Opcode);
637 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
641 std::array<Register, 4> VectorElems;
642 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
643 for (
unsigned I = 0;
I < NumParts; ++
I)
645 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
646 B.buildMergeValues(MO, VectorElems);
651 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
652 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
653 B.buildIntToPtr(MO, Scalar);
673 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
675 for (
unsigned I = 0;
I < NumParts; ++
I)
677 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
679 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
680 return B.buildBitcast(VectorTy, Scalar).getReg(0);
699 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
712 const LLT BufferStridedPtr =
715 const LLT CodePtr = FlatPtr;
717 const std::initializer_list<LLT> AddrSpaces64 = {
718 GlobalPtr, ConstantPtr, FlatPtr
721 const std::initializer_list<LLT> AddrSpaces32 = {
722 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
725 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
727 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
728 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
729 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
730 const std::initializer_list<LLT> FPTypesPK16_64 = {
F32,
F64,
F16,
V2F16,
760 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
762 if (ST.hasAnyPackedU64Ops()) {
765 .clampMaxNumElementsStrict(0,
S16, 2)
771 }
else if (ST.hasScalarAddSub64()) {
774 .clampMaxNumElementsStrict(0,
S16, 2)
782 .clampMaxNumElementsStrict(0,
S16, 2)
789 if (ST.hasScalarSMulU64()) {
792 .clampMaxNumElementsStrict(0,
S16, 2)
800 .clampMaxNumElementsStrict(0,
S16, 2)
810 .minScalarOrElt(0,
S16)
815 }
else if (ST.has16BitInsts()) {
849 .widenScalarToNextMultipleOf(0, 32)
859 if (ST.hasMad64_32())
864 if (ST.hasIntClamp()) {
887 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
897 if (ST.hasVOP3PInsts()) {
899 .clampMaxNumElements(0,
S8, 2)
920 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
936 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
977 auto &FCanonicalizeActions =
979 auto &StrictFPOpActions =
986 if (ST.has16BitInsts()) {
987 if (ST.hasVOP3PInsts()) {
989 FCanonicalizeActions.legalFor({
F16,
V2F16});
990 StrictFPOpActions.legalFor({
F16,
V2F16});
992 FPOpActions.legalFor({
F16});
993 FCanonicalizeActions.legalFor({
F16});
994 StrictFPOpActions.legalFor({
F16});
997 TrigActions.customFor({
F16});
998 FDIVActions.customFor({
F16});
1004 if (ST.hasAnyPackedFP32Ops()) {
1005 FPOpActions.legalFor({
V2F32});
1006 FCanonicalizeActions.legalFor({
V2F32});
1007 StrictFPOpActions.legalFor({
V2F32});
1008 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1009 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1010 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1013 if (ST.hasAnyPackedFP64Ops()) {
1014 FPOpActions.legalFor({
V2F64});
1015 FCanonicalizeActions.legalFor({
V2F64});
1016 StrictFPOpActions.legalFor({
V2F64});
1017 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1018 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1019 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1022 auto &MinNumMaxNumIeee =
1025 if (ST.hasVOP3PInsts()) {
1026 MinNumMaxNumIeee.legalFor(FPTypesPK16)
1028 .clampMaxNumElements(0,
F16, 2)
1030 }
else if (ST.has16BitInsts()) {
1031 MinNumMaxNumIeee.legalFor(FPTypes16).scalarize(0);
1033 MinNumMaxNumIeee.legalFor(FPTypesBase).scalarize(0);
1037 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1039 if (ST.hasAnyPackedFP64Ops()) {
1040 MinNumMaxNum.customFor(FPTypesPK16_64)
1042 .clampMaxNumElements(0,
F16, 2)
1043 .clampMaxNumElements(0,
F64, 2)
1045 }
else if (ST.hasVOP3PInsts()) {
1046 MinNumMaxNum.customFor(FPTypesPK16)
1048 .clampMaxNumElements(0,
F16, 2)
1050 }
else if (ST.has16BitInsts()) {
1051 MinNumMaxNum.customFor(FPTypes16).scalarize(0);
1053 MinNumMaxNum.customFor(FPTypesBase).scalarize(0);
1056 if (!ST.has16BitInsts()) {
1057 MinNumMaxNumIeee.minScalar(0,
F32);
1058 MinNumMaxNum.minScalar(0,
F32);
1061 if (ST.hasVOP3PInsts()) {
1062 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1063 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1064 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1072 if (!ST.has16BitInsts()) {
1083 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1086 if (ST.hasAnyPackedFP32Ops())
1090 if (ST.has16BitInsts()) {
1093 .legalFor(ST.hasBF16TransInsts(), {BF16})
1103 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1125 if (ST.hasFractBug()) {
1139 .legalFor({{
F32, I32}, {
F64, I32}})
1159 if (ST.hasCvtPkF16F32Inst()) {
1161 .clampMaxNumElements(0,
F16, 2);
1174 if (ST.has16BitInsts()) {
1188 if (ST.hasAnyPackedFP32Ops())
1196 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1197 FMad.customFor({
F32,
F16});
1198 else if (ST.hasMadMacF32Insts())
1199 FMad.customFor({
F32});
1200 else if (ST.hasMadF16())
1201 FMad.customFor({
F16});
1206 if (ST.has16BitInsts()) {
1209 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1217 .clampMaxNumElements(0,
S16, 2)
1233 .legalFor({{
F32, I32}, {
F64, I32}})
1237 if (ST.has16BitInsts())
1245 .legalFor({{I32,
F32}, {I32,
F64}})
1246 .customFor({{I64,
F32}, {I64,
F64}})
1249 if (ST.has16BitInsts())
1258 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1259 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1260 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1264 if (
ST.has16BitInsts())
1267 if (
ST.hasVCvtPkIU16F32())
1277 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1278 .clampScalar(0, I16, I64)
1282 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1288 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1292 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1293 .clampScalar(0, I16, I64)
1297 auto &RoundingActions = getActionDefinitionsBuilder(
1298 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1299 if (
ST.has16BitInsts())
1307 if (!
ST.has16BitInsts())
1310 getActionDefinitionsBuilder(G_PTR_ADD)
1316 getActionDefinitionsBuilder(G_PTRMASK)
1318 .scalarSameSizeAs(1, 0)
1322 getActionDefinitionsBuilder(G_ICMP)
1334 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1335 .legalForCartesianProduct(
1336 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1337 if (
ST.has16BitInsts()) {
1338 CmpBuilder.legalFor({{
S1,
S16}});
1347 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1350 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1351 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1353 if (
ST.hasSALUFloatInsts())
1354 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1356 FCmpBuilder.widenScalarToNextPow2(1).minScalar(1,
F32).scalarize(0);
1358 getActionDefinitionsBuilder(G_FPOW)
1360 .clampScalar(0,
F32,
F32)
1363 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1365 getActionDefinitionsBuilder(G_FLOG2)
1366 .legalFor(
ST.has16BitInsts(), {F16})
1367 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1373 getActionDefinitionsBuilder(G_FEXP2)
1374 .legalFor(
ST.has16BitInsts(), {F16})
1375 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1381 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1385 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1390 getActionDefinitionsBuilder(G_CTPOP)
1392 .clampScalar(0,
S32,
S32)
1393 .widenScalarToNextPow2(1, 32)
1394 .clampScalar(1,
S32,
S64)
1396 .widenScalarToNextPow2(0, 32);
1399 if (
ST.has16BitInsts())
1400 getActionDefinitionsBuilder(G_IS_FPCLASS)
1401 .legalForCartesianProduct({
I1}, FPTypes16)
1402 .widenScalarToNextPow2(1)
1406 getActionDefinitionsBuilder(G_IS_FPCLASS)
1407 .legalForCartesianProduct({
I1}, FPTypesBase)
1408 .lowerFor({
I1,
F16})
1409 .widenScalarToNextPow2(1)
1416 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1418 .clampScalar(0,
S32,
S32)
1419 .clampScalar(1,
S32,
S64)
1420 .widenScalarToNextPow2(0, 32)
1421 .widenScalarToNextPow2(1, 32)
1425 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1428 .clampScalar(0,
S32,
S32)
1429 .clampScalar(1,
S32,
S64)
1431 .widenScalarToNextPow2(0, 32)
1432 .widenScalarToNextPow2(1, 32);
1434 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1436 .clampScalar(0,
S32,
S32)
1437 .clampScalar(1,
S32,
S64)
1439 .widenScalarToNextPow2(0, 32)
1440 .widenScalarToNextPow2(1, 32);
1442 getActionDefinitionsBuilder(G_CTLS)
1445 .clampScalar(0,
S32,
S32)
1446 .clampScalar(1,
S32,
S32);
1450 getActionDefinitionsBuilder(G_BITREVERSE)
1452 .clampScalar(0,
S32,
S64)
1454 .widenScalarToNextPow2(0);
1456 if (
ST.has16BitInsts()) {
1457 getActionDefinitionsBuilder(G_BSWAP)
1459 .clampMaxNumElementsStrict(0,
S16, 2)
1462 .widenScalarToNextPow2(0)
1463 .clampScalar(0,
S16,
S32)
1466 if (
ST.hasVOP3PInsts()) {
1467 getActionDefinitionsBuilder(G_ABS)
1469 .clampMaxNumElements(0,
S16, 2)
1471 .widenScalarToNextPow2(0)
1474 if (
ST.useMinMaxI64Insts()) {
1475 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1477 .clampMaxNumElements(0,
S16, 2)
1479 .widenScalarToNextPow2(0)
1483 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1485 .clampMaxNumElements(0,
S16, 2)
1487 .widenScalarToNextPow2(0)
1492 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1494 .widenScalarToNextPow2(0)
1501 getActionDefinitionsBuilder(G_BSWAP)
1506 .widenScalarToNextPow2(0)
1511 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1514 .widenScalarToNextPow2(0)
1519 getActionDefinitionsBuilder(G_INTTOPTR)
1521 .legalForCartesianProduct(AddrSpaces64, {
S64})
1522 .legalForCartesianProduct(AddrSpaces32, {
S32})
1535 getActionDefinitionsBuilder(G_PTRTOINT)
1537 .legalForCartesianProduct(AddrSpaces64, {
S64})
1538 .legalForCartesianProduct(AddrSpaces32, {
S32})
1551 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1555 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1556 bool IsLoad) ->
bool {
1560 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1574 unsigned NumRegs = (MemSize + 31) / 32;
1576 if (!
ST.hasDwordx3LoadStores())
1587 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1588 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1589 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1595 for (
unsigned Op : {G_LOAD, G_STORE}) {
1596 const bool IsStore =
Op == G_STORE;
1598 auto &Actions = getActionDefinitionsBuilder(
Op);
1601 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1604 {
S64, GlobalPtr,
S64, GlobalAlign32},
1607 {
S32, GlobalPtr,
S8, GlobalAlign8},
1608 {
S32, GlobalPtr,
S16, GlobalAlign16},
1610 {
S32, LocalPtr,
S32, 32},
1611 {
S64, LocalPtr,
S64, 32},
1613 {
S32, LocalPtr,
S8, 8},
1614 {
S32, LocalPtr,
S16, 16},
1617 {
S32, PrivatePtr,
S32, 32},
1618 {
S32, PrivatePtr,
S8, 8},
1619 {
S32, PrivatePtr,
S16, 16},
1622 {
S32, ConstantPtr,
S32, GlobalAlign32},
1625 {
S64, ConstantPtr,
S64, GlobalAlign32},
1626 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1628 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1629 {{S16, GlobalPtr, S8, GlobalAlign8},
1630 {S16, GlobalPtr, S16, GlobalAlign16},
1631 {S16, LocalPtr, S8, 8},
1632 {S16, LocalPtr, S16, 16},
1633 {S16, PrivatePtr, S8, 8},
1634 {S16, PrivatePtr, S16, 16}});
1644 Actions.unsupportedIf(
1645 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1659 Actions.customIf(
typeIs(1, Constant32Ptr));
1685 return !Query.
Types[0].isVector() &&
1686 needToSplitMemOp(Query,
Op == G_LOAD);
1688 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1693 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1696 if (DstSize > MemSize)
1702 if (MemSize > MaxSize)
1710 return Query.
Types[0].isVector() &&
1711 needToSplitMemOp(Query,
Op == G_LOAD);
1713 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1727 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1728 if (MemSize > MaxSize) {
1732 if (MaxSize % EltSize == 0) {
1738 unsigned NumPieces = MemSize / MaxSize;
1742 if (NumPieces == 1 || NumPieces >= NumElts ||
1743 NumElts % NumPieces != 0)
1744 return std::pair(0, EltTy);
1752 return std::pair(0, EltTy);
1767 return std::pair(0, EltTy);
1772 .widenScalarToNextPow2(0)
1779 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1780 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1781 {
S32, GlobalPtr,
S16, 2 * 8},
1782 {
S32, LocalPtr,
S8, 8},
1783 {
S32, LocalPtr,
S16, 16},
1784 {
S32, PrivatePtr,
S8, 8},
1785 {
S32, PrivatePtr,
S16, 16},
1786 {
S32, ConstantPtr,
S8, 8},
1787 {
S32, ConstantPtr,
S16, 2 * 8}})
1788 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1789 {{S16, GlobalPtr, S8, GlobalAlign8},
1790 {S16, LocalPtr, S8, GlobalAlign8},
1791 {S16, PrivatePtr, S8, GlobalAlign8},
1792 {S16, ConstantPtr, S8, GlobalAlign8}})
1797 if (
ST.hasFlatAddressSpace()) {
1798 ExtLoads.legalForTypesWithMemDesc(
1799 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1801 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1802 {{S16, FlatPtr, S8, GlobalAlign8}});
1810 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1812 ExtLoads.narrowScalarIf(
1819 ExtLoads.clampScalar(0,
S32,
S32)
1820 .widenScalarToNextPow2(0)
1823 auto &Atomics = getActionDefinitionsBuilder(
1824 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1825 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1826 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1827 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1828 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1829 {
S64, GlobalPtr}, {
S64, LocalPtr},
1830 {
S32, RegionPtr}, {
S64, RegionPtr}});
1831 if (
ST.hasFlatAddressSpace()) {
1832 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1836 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1837 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1838 if (
ST.hasFlatAddressSpace()) {
1839 Atomics32.legalFor({{
S32, FlatPtr}});
1843 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1844 if (
ST.hasLDSFPAtomicAddF32()) {
1846 if (
ST.hasLdsAtomicAddF64())
1848 if (
ST.hasAtomicDsPkAdd16Insts())
1851 if (
ST.hasAtomicFaddInsts())
1853 if (
ST.hasFlatAtomicFaddF32Inst())
1856 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1860 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1863 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1864 ST.hasAtomicBufferGlobalPkAddF16Insts())
1866 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1868 if (
ST.hasAtomicFlatPkAdd16Insts())
1874 auto &AtomicFMinFMax =
1875 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1876 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1878 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1879 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1880 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1881 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1882 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1883 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1884 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1885 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1889 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1890 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1891 {
S32, FlatPtr}, {
S64, FlatPtr}})
1892 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1893 {
S32, RegionPtr}, {
S64, RegionPtr}});
1897 getActionDefinitionsBuilder(G_SELECT)
1899 LocalPtr, FlatPtr, PrivatePtr,
1903 .clampScalar(0,
S16,
S64)
1907 .clampMaxNumElements(0,
S32, 2)
1908 .clampMaxNumElements(0, LocalPtr, 2)
1909 .clampMaxNumElements(0, PrivatePtr, 2)
1911 .widenScalarToNextPow2(0)
1916 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1918 if (
ST.has16BitInsts()) {
1919 if (
ST.hasVOP3PInsts()) {
1921 .clampMaxNumElements(0,
S16, 2);
1923 Shifts.legalFor({{
S16,
S16}});
1926 Shifts.widenScalarIf(
1931 const LLT AmountTy = Query.
Types[1];
1937 Shifts.clampScalar(1,
S32,
S32);
1938 Shifts.widenScalarToNextPow2(0, 16);
1939 Shifts.clampScalar(0,
S16,
S64);
1941 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1949 Shifts.clampScalar(1,
S32,
S32);
1950 Shifts.widenScalarToNextPow2(0, 32);
1951 Shifts.clampScalar(0,
S32,
S64);
1953 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1958 Shifts.scalarize(0);
1960 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1961 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1962 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1963 unsigned IdxTypeIdx = 2;
1965 getActionDefinitionsBuilder(
Op)
1967 const LLT EltTy = Query.
Types[EltTypeIdx];
1968 const LLT VecTy = Query.
Types[VecTypeIdx];
1969 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1971 const bool isLegalVecType =
1981 return (EltSize == 32 || EltSize == 64) &&
1997 const LLT EltTy = Query.
Types[EltTypeIdx];
1998 const LLT VecTy = Query.
Types[VecTypeIdx];
2002 const unsigned TargetEltSize =
2003 DstEltSize % 64 == 0 ? 64 : 32;
2004 return std::pair(VecTypeIdx,
2008 .clampScalar(EltTypeIdx,
S32,
S64)
2009 .clampScalar(VecTypeIdx,
S32,
S64)
2010 .clampScalar(IdxTypeIdx,
S32,
S32)
2011 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2020 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2022 const LLT &EltTy = Query.
Types[1].getElementType();
2023 return Query.
Types[0] != EltTy;
2026 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2027 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2028 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2029 getActionDefinitionsBuilder(
Op)
2032 const LLT BigTy = Query.
Types[BigTyIdx];
2038 const LLT LitTy = Query.
Types[LitTyIdx];
2043 .widenScalarToNextPow2(BigTyIdx, 32)
2051 const LLT BigTy = Query.
Types[BigTyIdx];
2052 const LLT LitTy = Query.
Types[LitTyIdx];
2060 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2070 if (
ST.hasScalarPackInsts()) {
2073 .minScalarOrElt(0,
S16)
2076 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2080 BuildVector.customFor({
V2S16,
S16});
2081 BuildVector.minScalarOrElt(0,
S32);
2083 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2091 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2093 .clampMaxNumElements(0,
S32, 32)
2094 .clampMaxNumElements(1,
S16, 2)
2095 .clampMaxNumElements(0,
S16, 64);
2097 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2100 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2101 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2102 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2104 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2105 const LLT Ty = Query.
Types[TypeIdx];
2117 getActionDefinitionsBuilder(
Op)
2121 const LLT BigTy = Query.
Types[BigTyIdx];
2127 .widenScalarToNextPow2(LitTyIdx, 16)
2136 .clampScalar(LitTyIdx,
S32,
S512)
2137 .widenScalarToNextPow2(LitTyIdx, 32)
2141 return notValidElt(Query, LitTyIdx);
2146 return notValidElt(Query, BigTyIdx);
2151 if (
Op == G_MERGE_VALUES) {
2152 Builder.widenScalarIf(
2155 const LLT Ty = Query.
Types[LitTyIdx];
2161 Builder.widenScalarIf(
2163 const LLT Ty = Query.
Types[BigTyIdx];
2169 const LLT &Ty = Query.
Types[BigTyIdx];
2171 if (NewSizeInBits >= 256) {
2173 if (RoundedTo < NewSizeInBits)
2174 NewSizeInBits = RoundedTo;
2176 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2185 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2186 .legalFor({{
S32}, {
S64}})
2187 .clampScalar(0,
S32,
S64);
2189 if (
ST.hasVOP3PInsts()) {
2190 SextInReg.lowerFor({{
V2S16}})
2194 .clampMaxNumElementsStrict(0,
S16, 2);
2195 }
else if (
ST.has16BitInsts()) {
2196 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2200 SextInReg.lowerFor({{
S32}, {
S64}});
2205 .clampScalar(0,
S32,
S64)
2208 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2212 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2213 FSHRActionDefs.legalFor({{
S32,
S32}})
2214 .clampMaxNumElementsStrict(0,
S16, 2);
2215 if (
ST.hasVOP3PInsts())
2217 FSHRActionDefs.scalarize(0).lower();
2219 if (
ST.hasVOP3PInsts()) {
2220 getActionDefinitionsBuilder(G_FSHL)
2222 .clampMaxNumElementsStrict(0,
S16, 2)
2226 getActionDefinitionsBuilder(G_FSHL)
2231 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2234 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2236 getActionDefinitionsBuilder(G_FENCE)
2239 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2244 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2246 .clampScalar(1,
S32,
S32)
2247 .clampScalar(0,
S32,
S64)
2248 .widenScalarToNextPow2(0)
2251 getActionDefinitionsBuilder(
2255 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2256 G_READ_REGISTER, G_WRITE_REGISTER,
2261 if (
ST.hasIEEEMinimumMaximumInsts()) {
2262 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2263 .legalFor(FPTypesPK16)
2264 .clampMaxNumElements(0,
F16, 2)
2266 }
else if (
ST.hasVOP3PInsts()) {
2267 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2269 .clampMaxNumElementsStrict(0,
F16, 2)
2273 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2275 .clampScalar(0,
F32,
F64)
2279 getActionDefinitionsBuilder(
2280 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2283 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2285 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2286 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2287 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2290 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2292 getActionDefinitionsBuilder(
2293 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2294 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2295 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2296 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2301 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2302 G_INTRINSIC_CONVERGENT,
2303 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2315 switch (
MI.getOpcode()) {
2316 case TargetOpcode::G_ADDRSPACE_CAST:
2318 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2320 case TargetOpcode::G_FCEIL:
2322 case TargetOpcode::G_FREM:
2324 case TargetOpcode::G_INTRINSIC_TRUNC:
2326 case TargetOpcode::G_SITOFP:
2328 case TargetOpcode::G_UITOFP:
2330 case TargetOpcode::G_FPTOSI:
2332 case TargetOpcode::G_FPTOUI:
2334 case TargetOpcode::G_FMINNUM:
2335 case TargetOpcode::G_FMAXNUM:
2336 case TargetOpcode::G_FMINIMUMNUM:
2337 case TargetOpcode::G_FMAXIMUMNUM:
2339 case TargetOpcode::G_EXTRACT:
2341 case TargetOpcode::G_INSERT:
2343 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2345 case TargetOpcode::G_INSERT_VECTOR_ELT:
2347 case TargetOpcode::G_FSIN:
2348 case TargetOpcode::G_FCOS:
2350 case TargetOpcode::G_GLOBAL_VALUE:
2352 case TargetOpcode::G_LOAD:
2353 case TargetOpcode::G_SEXTLOAD:
2354 case TargetOpcode::G_ZEXTLOAD:
2356 case TargetOpcode::G_STORE:
2358 case TargetOpcode::G_FMAD:
2360 case TargetOpcode::G_FDIV:
2362 case TargetOpcode::G_FFREXP:
2364 case TargetOpcode::G_FSQRT:
2366 case TargetOpcode::G_UDIV:
2367 case TargetOpcode::G_UREM:
2368 case TargetOpcode::G_UDIVREM:
2370 case TargetOpcode::G_SDIV:
2371 case TargetOpcode::G_SREM:
2372 case TargetOpcode::G_SDIVREM:
2374 case TargetOpcode::G_ATOMIC_CMPXCHG:
2376 case TargetOpcode::G_FLOG2:
2378 case TargetOpcode::G_FLOG:
2379 case TargetOpcode::G_FLOG10:
2381 case TargetOpcode::G_FEXP2:
2383 case TargetOpcode::G_FEXP:
2384 case TargetOpcode::G_FEXP10:
2386 case TargetOpcode::G_FPOW:
2388 case TargetOpcode::G_FFLOOR:
2390 case TargetOpcode::G_BUILD_VECTOR:
2391 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2393 case TargetOpcode::G_MUL:
2395 case TargetOpcode::G_CTLZ:
2396 case TargetOpcode::G_CTTZ:
2398 case TargetOpcode::G_CTLS:
2400 case TargetOpcode::G_CTLZ_ZERO_POISON:
2402 case TargetOpcode::G_STACKSAVE:
2404 case TargetOpcode::G_GET_FPENV:
2406 case TargetOpcode::G_SET_FPENV:
2408 case TargetOpcode::G_TRAP:
2410 case TargetOpcode::G_DEBUGTRAP:
2422 unsigned BaseAS = AS;
2427 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2431 auto Tag =
B.buildConstant(
S32, SANum);
2432 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2438Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2448 if (ST.hasApertureRegs()) {
2452 const unsigned ApertureRegNo =
2453 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2454 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2455 !ST.hasGloballyAddressableScratch()) &&
2456 "Cannot use src_private_base with globally addressable scratch!");
2459 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2460 return B.buildUnmerge(I32, Dst).getReg(1);
2475 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2491 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2494 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2508 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2516 B.buildObjectPtrOffset(
2519 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2527 switch (Def->getOpcode()) {
2528 case AMDGPU::G_FRAME_INDEX:
2529 case AMDGPU::G_GLOBAL_VALUE:
2530 case AMDGPU::G_BLOCK_ADDR:
2532 case AMDGPU::G_CONSTANT: {
2533 const ConstantInt *CI = Def->getOperand(1).getCImm();
2548 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2557 unsigned SrcAS = SrcTy.getAddressSpace();
2571 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2578 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2580 ST.hasGloballyAddressableScratch()) {
2583 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2585 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2586 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2588 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2589 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2590 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2593 return B.buildExtract(Dst, Src, 0).getReg(0);
2597 castFlatToLocalOrPrivate(Dst);
2598 MI.eraseFromParent();
2604 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2605 auto FlatNull =
B.buildConstant(SrcTy, 0);
2608 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2612 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2614 MI.eraseFromParent();
2621 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2624 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2627 ST.hasGloballyAddressableScratch()) {
2631 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2632 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2636 if (ST.isWave64()) {
2637 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2643 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2644 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2646 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2650 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2651 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2653 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2654 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2663 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2667 castLocalOrPrivateToFlat(Dst);
2668 MI.eraseFromParent();
2672 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2679 SegmentNull.getReg(0));
2681 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2683 MI.eraseFromParent();
2688 SrcTy.getSizeInBits() == 64) {
2690 B.buildExtract(Dst, Src, 0);
2691 MI.eraseFromParent();
2698 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2699 auto PtrLo =
B.buildPtrToInt(I32, Src);
2700 if (AddrHiVal == 0) {
2701 auto Zext =
B.buildZExt(I64, PtrLo);
2702 B.buildIntToPtr(Dst, Zext);
2704 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2705 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2708 MI.eraseFromParent();
2715 MI.eraseFromParent();
2724 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2729 auto C1 =
B.buildFConstant(Ty, C1Val);
2730 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2733 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2734 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2736 auto C2 =
B.buildFConstant(Ty, C2Val);
2737 auto Fabs =
B.buildFAbs(Ty, Src);
2740 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2741 MI.eraseFromParent();
2758 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2760 const auto Zero =
B.buildFConstant(
F64, 0.0);
2761 const auto One =
B.buildFConstant(
F64, 1.0);
2764 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2765 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2768 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2769 MI.eraseFromParent();
2777 Register Src0Reg =
MI.getOperand(1).getReg();
2778 Register Src1Reg =
MI.getOperand(2).getReg();
2779 auto Flags =
MI.getFlags();
2782 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2783 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2784 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2785 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2786 MI.eraseFromParent();
2792 const unsigned FractBits = 52;
2793 const unsigned ExpBits = 11;
2796 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2797 auto Const1 =
B.buildConstant(I32, ExpBits);
2799 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2801 .addUse(Const0.getReg(0))
2802 .addUse(Const1.getReg(0));
2804 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2817 auto SrcInt =
B.buildBitcast(I64, Src);
2820 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2827 const unsigned FractBits = 52;
2830 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2831 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2833 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2835 const auto Zero32 =
B.buildConstant(I32, 0);
2838 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2840 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2841 auto Not =
B.buildNot(I64, Shr);
2842 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2843 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2848 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2849 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2850 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2851 MI.eraseFromParent();
2867 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2868 auto ThirtyTwo =
B.buildConstant(I32, 32);
2871 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2872 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2874 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2875 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2878 B.buildFAdd(Dst, LdExp, CvtLo);
2879 MI.eraseFromParent();
2885 auto One =
B.buildConstant(I32, 1);
2889 auto ThirtyOne =
B.buildConstant(I32, 31);
2890 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2891 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2892 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2893 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2894 .addUse(Unmerge.getReg(1));
2895 auto LS2 =
B.buildSub(I32, LS, One);
2896 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2898 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2899 auto Norm =
B.buildShl(I64, Src, ShAmt);
2900 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2901 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2902 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2903 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2904 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2905 B.buildFLdexp(Dst, FVal, Scale);
2906 MI.eraseFromParent();
2926 unsigned Flags =
MI.getFlags();
2937 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2945 auto SrcInt =
B.buildBitcast(I32, Src);
2946 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2947 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2951 K0 =
B.buildFConstant(
2953 K1 =
B.buildFConstant(
2956 K0 =
B.buildFConstant(
2958 K1 =
B.buildFConstant(
2962 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2963 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2964 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2966 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2967 :
B.buildFPTOUI(I32, FloorMul);
2968 auto Lo =
B.buildFPTOUI(I32, Fma);
2972 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2974 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2977 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2978 MI.eraseFromParent();
3001 uint64_t
Offset =
MI.getOperand(2).getImm();
3010 unsigned StartIdx =
Offset / 32;
3014 if (DstCount == 1) {
3016 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3024 for (
unsigned I = 0;
I < DstCount; ++
I)
3025 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3026 B.buildMergeLikeInstr(DstReg, MergeVec);
3029 MI.eraseFromParent();
3039 Register InsertSrc =
MI.getOperand(2).getReg();
3040 uint64_t
Offset =
MI.getOperand(3).getImm();
3048 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3052 unsigned DstCount = DstSize / 32;
3053 unsigned InsertCount = InsertSize / 32;
3054 unsigned StartIdx =
Offset / 32;
3056 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3059 for (
unsigned I = 0;
I < StartIdx; ++
I)
3062 if (InsertCount == 1) {
3066 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3069 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3070 for (
unsigned I = 0;
I < InsertCount; ++
I)
3074 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3077 B.buildMergeLikeInstr(DstReg, MergeVec);
3079 MI.eraseFromParent();
3106 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3107 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3108 B.buildIntToPtr(Dst, IntElt);
3110 MI.eraseFromParent();
3117 std::optional<ValueAndVReg> MaybeIdxVal =
3121 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3124 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3125 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3130 MI.eraseFromParent();
3159 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3160 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3161 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3163 B.buildIntToPtr(Dst, IntVecDest);
3164 MI.eraseFromParent();
3171 std::optional<ValueAndVReg> MaybeIdxVal =
3176 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3179 if (IdxVal < NumElts) {
3181 for (
unsigned i = 0; i < NumElts; ++i)
3183 B.buildUnmerge(SrcRegs, Vec);
3185 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3186 B.buildMergeLikeInstr(Dst, SrcRegs);
3191 MI.eraseFromParent();
3202 unsigned Flags =
MI.getFlags();
3206 if (ST.hasTrigReducedRange()) {
3207 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3208 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3209 .addUse(MulVal.getReg(0))
3213 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3216 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3220 MI.eraseFromParent();
3228 unsigned GAFlags)
const {
3261 if (ST.has64BitLiterals()) {
3265 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3269 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3279 B.buildExtract(DstReg, PCReg, 0);
3281 B.buildCopy(DstReg, PCReg);
3291 if (RequiresHighHalf && ST.has64BitLiterals()) {
3294 B.buildInstr(AMDGPU::S_MOV_B64)
3297 B.buildCopy(DstReg, Addr);
3305 B.buildInstr(AMDGPU::S_MOV_B32)
3310 if (RequiresHighHalf) {
3312 "Must provide a 64-bit pointer type!");
3317 B.buildInstr(AMDGPU::S_MOV_B32)
3324 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3325 B.buildCast(DstReg, AddrDst);
3327 B.buildCast(DstReg, AddrLo);
3336 unsigned AS = Ty.getAddressSpace();
3347 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3349 B.buildUndef(DstReg);
3350 MI.eraseFromParent();
3354 B.buildConstant(DstReg,
3356 MI.eraseFromParent();
3362 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3365 Fn,
"local memory global used by non-kernel function",
3374 B.buildUndef(DstReg);
3375 MI.eraseFromParent();
3399 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3400 B.buildIntToPtr(DstReg, Sz);
3401 MI.eraseFromParent();
3407 MI.eraseFromParent();
3411 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3413 MI.eraseFromParent();
3421 MI.eraseFromParent();
3427 MI.eraseFromParent();
3443 if (Ty.getSizeInBits() == 32) {
3445 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3446 B.buildExtract(DstReg,
Load, 0);
3448 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3450 MI.eraseFromParent();
3473 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3475 MI.getOperand(1).setReg(Cast.getReg(0));
3480 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3498 const uint64_t AlignInBits = 8 * MemAlign.
value();
3506 if (WideMemSize == ValSize) {
3512 MI.setMemRefs(MF, {WideMMO});
3518 if (ValSize > WideMemSize)
3525 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3526 B.buildTrunc(ValReg, WideLoad).getReg(0);
3533 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3534 B.buildExtract(ValReg, WideLoad, 0);
3538 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3539 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3543 MI.eraseFromParent();
3556 Register DataReg =
MI.getOperand(0).getReg();
3601 "this should not have been custom lowered");
3606 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3608 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3612 .setMemRefs(
MI.memoperands());
3614 MI.eraseFromParent();
3622 switch (
DefMI->getOpcode()) {
3623 case TargetOpcode::G_INTRINSIC: {
3625 case Intrinsic::amdgcn_frexp_mant:
3626 case Intrinsic::amdgcn_log:
3627 case Intrinsic::amdgcn_log_clamp:
3628 case Intrinsic::amdgcn_exp2:
3629 case Intrinsic::amdgcn_sqrt:
3637 case TargetOpcode::G_FSQRT:
3639 case TargetOpcode::G_FFREXP: {
3640 if (
DefMI->getOperand(0).getReg() == Src)
3644 case TargetOpcode::G_FPEXT: {
3665std::pair<Register, Register>
3667 unsigned Flags)
const {
3671 auto SmallestNormal =
B.buildFConstant(
3673 auto IsLtSmallestNormal =
3676 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3677 auto One =
B.buildFConstant(
F32, 1.0);
3679 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3680 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3682 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3695 LLT Ty =
B.getMRI()->getType(Dst);
3696 unsigned Flags =
MI.getFlags();
3700 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3701 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3702 .addUse(Ext.getReg(0))
3704 B.buildFPTrunc(Dst,
Log2, Flags);
3705 MI.eraseFromParent();
3713 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3716 MI.eraseFromParent();
3720 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3721 .addUse(ScaledInput)
3724 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3725 auto Zero =
B.buildFConstant(Ty, 0.0);
3727 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3728 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3730 MI.eraseFromParent();
3736 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3737 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3742 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3743 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3748 unsigned Flags =
MI.getFlags();
3758 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3760 B.buildFPTrunc(Dst, LogVal, Flags);
3765 MI.eraseFromParent();
3774 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3777 if (ST.hasFastFMAF32()) {
3779 const float c_log10 = 0x1.344134p-2f;
3780 const float cc_log10 = 0x1.09f79ep-26f;
3783 const float c_log = 0x1.62e42ep-1f;
3784 const float cc_log = 0x1.efa39ep-25f;
3786 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3787 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3791 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3792 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3793 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3794 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3795 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3798 const float ch_log10 = 0x1.344000p-2f;
3799 const float ct_log10 = 0x1.3509f6p-18f;
3802 const float ch_log = 0x1.62e000p-1f;
3803 const float ct_log = 0x1.0bfbe8p-15f;
3805 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3806 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3809 auto YInt =
B.buildBitcast(I32,
Y);
3810 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3811 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3812 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3816 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3819 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3821 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3824 const bool IsFiniteOnly =
3827 if (!IsFiniteOnly) {
3830 auto Fabs =
B.buildFAbs(Ty,
Y);
3833 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3837 auto Zero =
B.buildFConstant(Ty, 0.0);
3839 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3840 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3841 B.buildFSub(Dst, R, Shift, Flags);
3843 B.buildCopy(Dst, R);
3846 MI.eraseFromParent();
3852 unsigned Flags)
const {
3853 const double Log2BaseInverted =
3856 LLT Ty =
B.getMRI()->getType(Dst);
3861 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3862 .addUse(ScaledInput)
3864 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3865 auto Zero =
B.buildFConstant(Ty, 0.0);
3867 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3868 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3870 if (ST.hasFastFMAF32())
3871 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3873 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3874 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3881 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3882 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3885 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3886 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3897 unsigned Flags =
MI.getFlags();
3898 LLT Ty =
B.getMRI()->getType(Dst);
3905 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3906 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3907 .addUse(Ext.getReg(0))
3909 B.buildFPTrunc(Dst,
Log2, Flags);
3910 MI.eraseFromParent();
3920 MI.eraseFromParent();
3928 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3930 RangeCheckConst, Flags);
3932 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3933 auto Zero =
B.buildFConstant(Ty, 0.0);
3934 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3935 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3937 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3938 .addUse(AddInput.getReg(0))
3941 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3942 auto One =
B.buildFConstant(Ty, 1.0);
3943 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3944 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3945 MI.eraseFromParent();
3950 const SrcOp &Src,
unsigned Flags) {
3951 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3954 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3955 .addUse(Src.getReg())
3958 return B.buildFExp2(Dst, Src, Flags);
3964 bool IsExp10)
const {
3965 LLT Ty =
B.getMRI()->getType(
X);
3969 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3970 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3977 LLT Ty =
B.getMRI()->getType(Dst);
3983 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3986 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3987 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3988 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3991 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3993 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3994 .addUse(ExpInput.getReg(0))
3997 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3998 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3999 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4005 unsigned Flags)
const {
4006 LLT Ty =
B.getMRI()->getType(Dst);
4010 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4011 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4013 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4014 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4015 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4016 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4017 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4027 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4031 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4032 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4033 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4035 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4036 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4038 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4039 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4040 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4041 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4043 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4044 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4045 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4047 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4065 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4067 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4069 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4071 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4072 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4073 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4074 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4076 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4077 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4078 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4079 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4081 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4082 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4083 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4084 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4085 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4087 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4088 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4089 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4090 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4093 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4094 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4095 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4097 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4098 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4099 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4100 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4101 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4105 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4106 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4108 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4110 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4112 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4114 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4116 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4117 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4118 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4119 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4121 auto One =
B.buildFConstant(
F64, 1.0);
4122 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4123 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4126 auto DnInt =
B.buildFPTOSI(I32, Dn);
4127 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4134 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4141 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4143 MI.eraseFromParent();
4151 const unsigned Flags =
MI.getFlags();
4159 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4167 MI.eraseFromParent();
4178 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4181 B.buildFPTrunc(Dst, Lowered, Flags);
4182 MI.eraseFromParent();
4193 MI.eraseFromParent();
4221 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4224 if (ST.hasFastFMAF32()) {
4226 const float cc_exp = 0x1.4ae0bep-26f;
4227 const float c_exp10 = 0x1.a934f0p+1f;
4228 const float cc_exp10 = 0x1.2f346ep-24f;
4230 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4231 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4232 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4233 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4235 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4236 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4238 const float ch_exp = 0x1.714000p+0f;
4239 const float cl_exp = 0x1.47652ap-12f;
4241 const float ch_exp10 = 0x1.a92000p+1f;
4242 const float cl_exp10 = 0x1.4f0978p-11f;
4245 auto XInt =
B.buildBitcast(I32,
X);
4246 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4247 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4248 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4250 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4251 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4253 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4254 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4257 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4258 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4261 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4264 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4265 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4267 auto IntE =
B.buildFPTOSI(I32, E);
4269 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4270 .addUse(
A.getReg(0))
4272 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4274 auto UnderflowCheckConst =
4275 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4276 auto Zero =
B.buildFConstant(Ty, 0.0);
4280 R =
B.buildSelect(Ty, Underflow, Zero, R);
4283 auto OverflowCheckConst =
4284 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4289 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4292 B.buildCopy(Dst, R);
4293 MI.eraseFromParent();
4304 unsigned Flags =
MI.getFlags();
4313 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4315 .setMIFlags(CoreFlags);
4316 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4318 .addUse(Log.getReg(0))
4319 .setMIFlags(CoreFlags);
4321 MI.eraseFromParent();
4325 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4326 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4327 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4329 .addUse(Log.getReg(0))
4330 .setMIFlags(CoreFlags);
4335 .signBitIsZeroOrNaN()) {
4336 B.buildFExp2(Dst,
Mul, CoreFlags);
4337 MI.eraseFromParent();
4343 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4345 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4346 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4347 auto YIsOdd =
B.buildAnd(
4351 auto Neg =
B.buildFCopysign(
F32, R,
X);
4353 B.buildSelect(Dst, YIsOdd, Neg, R);
4354 MI.eraseFromParent();
4357 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4364 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4366 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4368 B.buildSelect(Dst, NegNonInt, NaN, R);
4370 MI.eraseFromParent();
4378 ModSrc = SrcFNeg->getOperand(1).getReg();
4380 ModSrc = SrcFAbs->getOperand(1).getReg();
4382 ModSrc = SrcFAbs->getOperand(1).getReg();
4392 Register OrigSrc =
MI.getOperand(1).getReg();
4393 unsigned Flags =
MI.getFlags();
4395 "this should not have been custom lowered");
4405 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4425 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4427 B.buildFMinNum(Min, Fract, Const, Flags);
4432 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4435 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4436 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4438 MI.eraseFromParent();
4456 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4458 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4459 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4462 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4463 B.buildBitcast(Dst,
Merge);
4465 MI.eraseFromParent();
4482 bool UsePartialMad64_32,
4483 bool SeparateOddAlignedProducts)
const {
4498 auto getZero32 = [&]() ->
Register {
4500 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4503 auto getZero64 = [&]() ->
Register {
4505 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4510 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4521 if (CarryIn.empty())
4524 bool HaveCarryOut =
true;
4526 if (CarryIn.size() == 1) {
4528 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4532 CarryAccum = getZero32();
4534 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4535 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4537 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4542 LocalAccum = getZero32();
4543 HaveCarryOut =
false;
4548 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4549 LocalAccum =
Add.getReg(0);
4563 auto buildMadChain =
4566 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4567 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4574 if (LocalAccum.size() == 1 &&
4575 (!UsePartialMad64_32 || !CarryIn.empty())) {
4578 unsigned j1 = DstIndex - j0;
4579 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4583 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4585 LocalAccum[0] =
Mul.getReg(0);
4587 if (CarryIn.empty()) {
4588 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4591 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4597 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4601 if (j0 <= DstIndex) {
4602 bool HaveSmallAccum =
false;
4605 if (LocalAccum[0]) {
4606 if (LocalAccum.size() == 1) {
4607 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4608 HaveSmallAccum =
true;
4609 }
else if (LocalAccum[1]) {
4610 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4611 HaveSmallAccum =
false;
4613 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4614 HaveSmallAccum =
true;
4617 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4619 HaveSmallAccum =
true;
4623 unsigned j1 = DstIndex - j0;
4624 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4628 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4629 {Src0[j0], Src1[j1], Tmp});
4630 Tmp = Mad.getReg(0);
4631 if (!HaveSmallAccum)
4632 CarryOut.push_back(Mad.getReg(1));
4633 HaveSmallAccum =
false;
4636 }
while (j0 <= DstIndex);
4638 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4639 LocalAccum[0] = Unmerge.getReg(0);
4640 if (LocalAccum.size() > 1)
4641 LocalAccum[1] = Unmerge.getReg(1);
4648 LocalAccum[0] = getZero32();
4652 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4653 "Uninitialized accumulator part");
4679 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4680 Carry OddCarryIn = std::move(OddCarry);
4681 Carry EvenCarryIn = std::move(EvenCarry);
4686 if (2 * i < Accum.
size()) {
4687 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4688 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4693 if (!SeparateOddAlignedProducts) {
4694 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4695 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4697 bool IsHighest = 2 * i >= Accum.
size();
4700 .take_front(IsHighest ? 1 : 2);
4701 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4707 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4709 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4711 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4714 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4717 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4718 Lo->getOperand(1).getReg());
4719 Accum[2 * i] =
Hi.getReg(0);
4720 SeparateOddCarry =
Hi.getReg(1);
4727 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4728 EvenCarryIn.push_back(CarryOut);
4730 if (2 * i < Accum.
size()) {
4731 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4732 OddCarry.push_back(CarryOut);
4744 assert(ST.hasMad64_32());
4745 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4757 unsigned Size = Ty.getSizeInBits();
4758 if (ST.useVMulU64Inst() &&
Size == 64)
4761 unsigned NumParts =
Size / 32;
4773 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4777 for (
unsigned i = 0; i < NumParts; ++i) {
4781 B.buildUnmerge(Src0Parts, Src0);
4782 B.buildUnmerge(Src1Parts, Src1);
4785 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4786 SeparateOddAlignedProducts);
4788 B.buildMergeLikeInstr(DstReg, AccumRegs);
4789 MI.eraseFromParent();
4804 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4805 ? AMDGPU::G_AMDGPU_FFBH_U32
4806 : AMDGPU::G_AMDGPU_FFBL_B32;
4807 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4810 MI.eraseFromParent();
4820 TypeSize NumBits = SrcTy.getSizeInBits();
4825 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4826 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4827 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4828 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4829 B.buildTrunc(Dst, Ctlz);
4830 MI.eraseFromParent();
4841 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4842 unsigned BitWidth = SrcTy.getSizeInBits();
4844 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4845 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4846 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4847 MI.eraseFromParent();
4853 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4856 return ConstVal == -1;
4863 Register CondDef =
MI.getOperand(0).getReg();
4882 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4891 UncondBrTarget = &*NextMBB;
4893 if (
Next->getOpcode() != AMDGPU::G_BR)
4912 *ArgRC,
B.getDebugLoc(), ArgTy);
4916 const unsigned Mask = Arg->
getMask();
4924 auto ShiftAmt =
B.buildConstant(I32, Shift);
4925 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4928 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4930 B.buildCopy(DstReg, LiveIn);
4940 if (!ST.hasClusters()) {
4943 MI.eraseFromParent();
4963 auto One =
B.buildConstant(I32, 1);
4964 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4965 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4966 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4973 B.buildCopy(DstReg, GlobalIdXYZ);
4974 MI.eraseFromParent();
4978 B.buildCopy(DstReg, ClusterIdXYZ);
4979 MI.eraseFromParent();
4984 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4986 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4987 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4989 .addImm(ClusterIdField);
4990 auto Zero =
B.buildConstant(I32, 0);
4993 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4994 MI.eraseFromParent();
5036 auto LoadConstant = [&](
unsigned N) {
5037 B.buildConstant(DstReg,
N);
5041 if (ST.hasArchitectedSGPRs() &&
5048 Arg = &WorkGroupIDX;
5049 ArgRC = &AMDGPU::SReg_32RegClass;
5053 Arg = &WorkGroupIDY;
5054 ArgRC = &AMDGPU::SReg_32RegClass;
5058 Arg = &WorkGroupIDZ;
5059 ArgRC = &AMDGPU::SReg_32RegClass;
5063 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5064 return LoadConstant(0);
5065 Arg = &ClusterWorkGroupIDX;
5066 ArgRC = &AMDGPU::SReg_32RegClass;
5070 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5071 return LoadConstant(0);
5072 Arg = &ClusterWorkGroupIDY;
5073 ArgRC = &AMDGPU::SReg_32RegClass;
5077 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5078 return LoadConstant(0);
5079 Arg = &ClusterWorkGroupIDZ;
5080 ArgRC = &AMDGPU::SReg_32RegClass;
5085 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5086 Arg = &ClusterWorkGroupMaxIDX;
5087 ArgRC = &AMDGPU::SReg_32RegClass;
5092 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5093 Arg = &ClusterWorkGroupMaxIDY;
5094 ArgRC = &AMDGPU::SReg_32RegClass;
5099 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5100 Arg = &ClusterWorkGroupMaxIDZ;
5101 ArgRC = &AMDGPU::SReg_32RegClass;
5105 Arg = &ClusterWorkGroupMaxFlatID;
5106 ArgRC = &AMDGPU::SReg_32RegClass;
5121 return LoadConstant(0);
5126 B.buildUndef(DstReg);
5130 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5142 MI.eraseFromParent();
5148 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5149 MI.eraseFromParent();
5156 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5170 B.buildUndef(DstReg);
5171 MI.eraseFromParent();
5175 if (Arg->isMasked()) {
5189 MI.eraseFromParent();
5204 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5213 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5221 Align Alignment)
const {
5225 "unexpected kernarg parameter type");
5232 MI.eraseFromParent();
5264 auto FloatY =
B.buildUITOFP(
F32,
Y);
5265 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5267 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5268 auto Z =
B.buildFPTOUI(I32, ScaledY);
5271 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5272 auto NegYZ =
B.buildMul(I32, NegY, Z);
5273 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5276 auto Q =
B.buildUMulH(I32,
X, Z);
5277 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5280 auto One =
B.buildConstant(I32, 1);
5283 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5284 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5289 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5292 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5311 auto Unmerge =
B.buildUnmerge(I32, Val);
5313 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5314 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5316 auto Mad =
B.buildFMAD(
5320 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5321 auto Mul1 =
B.buildFMul(
5325 auto Mul2 =
B.buildFMul(
5327 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5330 auto Mad2 =
B.buildFMAD(
5334 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5335 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5337 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5352 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5354 auto Zero64 =
B.buildConstant(I64, 0);
5355 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5357 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5358 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5360 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5361 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5362 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5364 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5365 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5366 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5368 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5369 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5370 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5371 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5372 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5374 auto Zero32 =
B.buildConstant(I32, 0);
5375 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5376 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5377 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5379 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5380 Register NumerLo = UnmergeNumer.getReg(0);
5381 Register NumerHi = UnmergeNumer.getReg(1);
5383 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5384 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5385 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5386 Register Mul3_Lo = UnmergeMul3.getReg(0);
5387 Register Mul3_Hi = UnmergeMul3.getReg(1);
5388 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5389 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5390 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5391 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5393 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5394 Register DenomLo = UnmergeDenom.getReg(0);
5395 Register DenomHi = UnmergeDenom.getReg(1);
5398 auto C1 =
B.buildSExt(I32, CmpHi);
5401 auto C2 =
B.buildSExt(I32, CmpLo);
5404 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5411 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5412 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5413 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5414 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5416 auto One64 =
B.buildConstant(I64, 1);
5417 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5423 auto C6 =
B.buildSelect(
5427 auto Add4 =
B.buildAdd(I64, Add3, One64);
5428 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5430 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5431 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5432 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5438 auto Sel1 =
B.buildSelect(
5445 auto Sel2 =
B.buildSelect(
5456 switch (
MI.getOpcode()) {
5459 case AMDGPU::G_UDIV: {
5460 DstDivReg =
MI.getOperand(0).getReg();
5463 case AMDGPU::G_UREM: {
5464 DstRemReg =
MI.getOperand(0).getReg();
5467 case AMDGPU::G_UDIVREM: {
5468 DstDivReg =
MI.getOperand(0).getReg();
5469 DstRemReg =
MI.getOperand(1).getReg();
5476 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5477 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5478 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5488 MI.eraseFromParent();
5499 if (Ty != I32 && Ty != I64)
5502 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5503 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5504 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5506 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5507 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5508 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5510 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5511 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5513 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5514 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5516 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5517 switch (
MI.getOpcode()) {
5520 case AMDGPU::G_SDIV: {
5521 DstDivReg =
MI.getOperand(0).getReg();
5525 case AMDGPU::G_SREM: {
5526 DstRemReg =
MI.getOperand(0).getReg();
5530 case AMDGPU::G_SDIVREM: {
5531 DstDivReg =
MI.getOperand(0).getReg();
5532 DstRemReg =
MI.getOperand(1).getReg();
5545 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5546 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5547 B.buildSub(DstDivReg, SignXor, Sign);
5551 auto Sign = LHSign.getReg(0);
5552 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5553 B.buildSub(DstRemReg, SignXor, Sign);
5556 MI.eraseFromParent();
5566 uint16_t Flags =
MI.getFlags();
5572 if (!AllowInaccurateRcp && ResTy !=
F16)
5583 if (CLHS->isOne()) {
5584 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5588 MI.eraseFromParent();
5593 if (CLHS->isMinusOne()) {
5594 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5595 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5596 .addUse(FNeg.getReg(0))
5599 MI.eraseFromParent();
5606 if (!AllowInaccurateRcp &&
5611 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5614 B.buildFMul(Res, LHS, RCP, Flags);
5616 MI.eraseFromParent();
5626 uint16_t Flags =
MI.getFlags();
5631 if (!AllowInaccurateRcp)
5639 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5641 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5642 auto One =
B.buildFConstant(ResTy, 1.0);
5644 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5648 R =
B.buildFNeg(ResTy, R);
5650 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5651 R =
B.buildFMA(ResTy, Tmp0, R, R);
5653 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5654 R =
B.buildFMA(ResTy, Tmp1, R, R);
5657 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5658 B.buildCopy(Res, R);
5659 MI.eraseFromParent();
5663 auto Ret =
B.buildFMul(ResTy,
X, R);
5664 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5666 B.buildFMA(Res, Tmp2, R, Ret);
5667 MI.eraseFromParent();
5681 uint16_t Flags =
MI.getFlags();
5698 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5699 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5700 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5701 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5702 .addUse(RHSExt.getReg(0))
5704 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5706 if (ST.hasMadMacF32Insts()) {
5707 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5708 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5709 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5711 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5712 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5713 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5715 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5716 auto TmpInt =
B.buildBitcast(I32, Tmp);
5717 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5718 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5719 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5720 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5721 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5722 .addUse(RDst.getReg(0))
5727 MI.eraseFromParent();
5740 unsigned SPDenormMode =
5743 if (ST.hasDenormModeInst()) {
5745 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5747 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5748 B.buildInstr(AMDGPU::S_DENORM_MODE)
5749 .addImm(NewDenormModeValue);
5752 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5753 .addImm(SPDenormMode)
5770 uint16_t Flags =
MI.getFlags();
5774 auto One =
B.buildFConstant(
F32, 1.0f);
5776 auto DenominatorScaled =
5777 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5782 auto NumeratorScaled =
5783 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5789 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5790 .addUse(DenominatorScaled.getReg(0))
5792 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5795 const bool HasDynamicDenormals =
5800 if (!PreservesDenormals) {
5801 if (HasDynamicDenormals) {
5803 B.buildInstr(AMDGPU::S_GETREG_B32)
5804 .addDef(SavedSPDenormMode)
5810 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5811 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5812 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5813 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5814 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5815 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5817 if (!PreservesDenormals) {
5818 if (HasDynamicDenormals) {
5819 assert(SavedSPDenormMode);
5820 B.buildInstr(AMDGPU::S_SETREG_B32)
5821 .addReg(SavedSPDenormMode)
5827 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5828 .addUse(Fma4.getReg(0))
5829 .addUse(Fma1.getReg(0))
5830 .addUse(Fma3.getReg(0))
5831 .addUse(NumeratorScaled.getReg(1))
5834 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5835 .addUse(Fmas.getReg(0))
5840 MI.eraseFromParent();
5854 uint16_t Flags =
MI.getFlags();
5858 auto One =
B.buildFConstant(
F64, 1.0);
5860 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5866 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5868 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5869 .addUse(DivScale0.getReg(0))
5872 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5873 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5874 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5876 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5882 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5883 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5884 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5887 if (!ST.hasUsableDivScaleConditionOutput()) {
5894 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5895 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5896 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5897 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5900 Scale1Unmerge.getReg(1));
5902 Scale0Unmerge.getReg(1));
5903 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5905 Scale = DivScale1.getReg(1);
5908 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5909 .addUse(Fma4.getReg(0))
5910 .addUse(Fma3.getReg(0))
5911 .addUse(
Mul.getReg(0))
5915 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5916 .addUse(Fmas.getReg(0))
5921 MI.eraseFromParent();
5931 uint16_t Flags =
MI.getFlags();
5936 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5939 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5943 if (ST.hasFractBug()) {
5944 auto Fabs =
B.buildFAbs(Ty, Val);
5948 auto Zero =
B.buildConstant(InstrExpTy, 0);
5949 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5950 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5953 B.buildCopy(Res0, Mant);
5954 B.buildSExtOrTrunc(Res1, Exp);
5956 MI.eraseFromParent();
5966 uint16_t Flags =
MI.getFlags();
5970 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5973 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5974 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5975 auto C2 =
B.buildFConstant(
F32, 1.0f);
5978 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5980 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5982 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5983 .addUse(Mul0.getReg(0))
5986 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5988 B.buildFMul(Res, Sel, Mul1, Flags);
5990 MI.eraseFromParent();
5999 unsigned Flags =
MI.getFlags();
6000 assert(!ST.has16BitInsts());
6001 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6002 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6003 .addUse(Ext.getReg(0))
6005 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6006 MI.eraseFromParent();
6016 const unsigned Flags =
MI.getFlags();
6024 MI.eraseFromParent();
6028 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6030 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6031 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6032 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6037 .addUse(SqrtX.getReg(0))
6040 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6041 auto NegOne =
B.buildConstant(I32, -1);
6042 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6044 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6045 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6047 auto PosOne =
B.buildConstant(I32, 1);
6048 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6050 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6051 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6053 auto Zero =
B.buildFConstant(
F32, 0.0f);
6057 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6061 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6064 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6065 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6067 auto Half =
B.buildFConstant(
F32, 0.5f);
6068 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6069 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6070 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6071 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6072 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6073 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6074 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6075 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6078 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6080 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6082 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6085 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6087 MI.eraseFromParent();
6121 unsigned Flags =
MI.getFlags();
6126 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6128 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6132 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6133 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6134 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6137 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6139 auto Half =
B.buildFConstant(
F64, 0.5);
6140 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6141 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6143 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6144 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6146 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6147 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6149 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6150 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6152 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6154 Register SqrtRet = SqrtS2.getReg(0);
6156 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6157 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6158 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6161 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6162 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6163 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6168 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6171 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6177 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6179 MI.eraseFromParent();
6210 auto Flags =
MI.getFlags();
6222 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6232 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6233 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6238 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6240 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6241 MI.eraseFromParent();
6253 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6254 IID == Intrinsic::amdgcn_permlanex16;
6255 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6256 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6257 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6258 IID == Intrinsic::amdgcn_permlane_up ||
6259 IID == Intrinsic::amdgcn_permlane_down ||
6260 IID == Intrinsic::amdgcn_permlane_xor;
6264 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6266 case Intrinsic::amdgcn_readfirstlane:
6267 case Intrinsic::amdgcn_permlane64:
6268 return LaneOp.getReg(0);
6269 case Intrinsic::amdgcn_readlane:
6270 case Intrinsic::amdgcn_set_inactive:
6271 case Intrinsic::amdgcn_set_inactive_chain_arg:
6272 return LaneOp.addUse(Src1).getReg(0);
6273 case Intrinsic::amdgcn_writelane:
6274 case Intrinsic::amdgcn_permlane_bcast:
6275 case Intrinsic::amdgcn_permlane_up:
6276 case Intrinsic::amdgcn_permlane_down:
6277 case Intrinsic::amdgcn_permlane_xor:
6278 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6279 case Intrinsic::amdgcn_permlane16:
6280 case Intrinsic::amdgcn_permlanex16: {
6282 int64_t Src4 =
MI.getOperand(6).getImm();
6283 int64_t Src5 =
MI.getOperand(7).getImm();
6284 return LaneOp.addUse(Src1)
6291 case Intrinsic::amdgcn_mov_dpp8:
6292 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6293 case Intrinsic::amdgcn_update_dpp:
6294 return LaneOp.addUse(Src1)
6295 .addImm(
MI.getOperand(4).getImm())
6296 .addImm(
MI.getOperand(5).getImm())
6297 .addImm(
MI.getOperand(6).getImm())
6298 .addImm(
MI.getOperand(7).getImm())
6308 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6309 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6310 IsPermlaneShuffle) {
6311 Src1 =
MI.getOperand(3).getReg();
6312 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6313 IsPermlaneShuffle) {
6314 Src2 =
MI.getOperand(4).getReg();
6319 unsigned Size = Ty.getSizeInBits();
6321 unsigned SplitSize = 32;
6322 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6323 ST.hasDPALU_DPP() &&
6327 if (
Size == SplitSize) {
6334 bool IsFloat = Ty.getScalarType().isFloat();
6338 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6340 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6342 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6346 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6348 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6349 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6351 if (IID == Intrinsic::amdgcn_writelane)
6352 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6354 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6356 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6358 B.buildTrunc(DstReg, LaneOpDst);
6359 MI.eraseFromParent();
6363 if (
Size % SplitSize != 0)
6367 bool NeedsBitcast =
false;
6368 if (IntTy.isVector()) {
6371 if (EltSize == SplitSize) {
6372 PartialResTy = EltTy;
6373 }
else if (EltSize == 16 || EltSize == 32) {
6374 unsigned NElem = SplitSize / EltSize;
6377 NeedsBitcast =
true;
6382 unsigned NumParts =
Size / SplitSize;
6386 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6387 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6389 if (IID == Intrinsic::amdgcn_writelane)
6390 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6392 for (
unsigned i = 0; i < NumParts; ++i) {
6393 Src0 = Src0Parts.
getReg(i);
6395 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6396 Src1 = Src1Parts.
getReg(i);
6398 if (IID == Intrinsic::amdgcn_writelane)
6399 Src2 = Src2Parts.
getReg(i);
6401 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6404 if (NeedsBitcast || IsFloat)
6407 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6409 B.buildMergeLikeInstr(DstReg, PartialRes);
6411 MI.eraseFromParent();
6419 ST.getTargetLowering()->getImplicitParameterOffset(
6429 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6430 B.buildConstant(IdxTy,
Offset).getReg(0));
6441 Register Pointer =
MI.getOperand(2).getReg();
6443 Register NumRecords =
MI.getOperand(4).getReg();
6449 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6451 auto ExtStride =
B.buildAnyExt(I32, Stride);
6453 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6454 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6456 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6458 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6462 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6463 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6464 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6465 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6469 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6470 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6471 auto ExtShiftedStride =
6472 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6473 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6474 auto ExtShiftedFlags =
6475 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6476 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6478 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6479 B.buildMergeValues(Result, {LowHalf, HighHalf});
6481 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6482 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6483 auto LowHalf = Unmerge.getReg(0);
6484 auto HighHalf = Unmerge.getReg(1);
6486 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6487 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6488 auto ShiftConst =
B.buildConstant(I32, 16);
6489 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6490 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6491 Register NewHighHalfReg = NewHighHalf.getReg(0);
6492 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6495 MI.eraseFromParent();
6512 MI.eraseFromParent();
6520 std::optional<uint32_t> KnownSize =
6522 if (KnownSize.has_value())
6523 B.buildConstant(DstReg, *KnownSize);
6541 MI.eraseFromParent();
6548 unsigned AddrSpace)
const {
6550 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6554 ST.hasGloballyAddressableScratch()) {
6556 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6557 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6559 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6561 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6563 B.buildConstant(I32, 1u << 26));
6568 MI.eraseFromParent();
6578std::pair<Register, unsigned>
6590 bool CheckNUW = ST.hasGFX1250Insts();
6592 MRI, OrigOffset,
nullptr, CheckNUW);
6596 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6606 unsigned Overflow = ImmOffset & ~MaxImm;
6607 ImmOffset -= Overflow;
6608 if ((int32_t)Overflow < 0) {
6609 Overflow += ImmOffset;
6613 if (Overflow != 0) {
6615 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6617 auto OverflowVal =
B.buildConstant(I32, Overflow);
6618 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6623 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6625 return std::pair(BaseReg, ImmOffset);
6632 bool ImageStore)
const {
6640 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6642 if (ST.hasUnpackedD16VMem()) {
6643 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6646 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6647 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6655 if (ImageStore && ST.hasImageStoreD16Bug()) {
6658 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6660 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6667 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6668 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6670 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6678 auto Unmerge =
B.buildUnmerge(I32, Reg);
6679 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6681 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6691 Reg =
B.buildPadVectorWithUndefElements(
6700 bool IsFormat)
const {
6710 VData =
B.buildBitcast(Ty, VData).getReg(0);
6718 if (Ty.isVector()) {
6719 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6731 bool IsFormat)
const {
6738 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6745 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6746 const Function &Fn =
B.getMF().getFunction();
6748 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6749 MI.eraseFromParent();
6761 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6764 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6768 VIndex =
MI.getOperand(3).getReg();
6771 VIndex =
B.buildConstant(I32, 0).getReg(0);
6774 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6775 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6779 Format =
MI.getOperand(5 + OpOffset).getImm();
6783 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6789 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6790 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6791 }
else if (IsFormat) {
6792 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6793 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6797 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6800 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6803 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6808 auto MIB =
B.buildInstr(
Opc)
6819 MIB.addImm(AuxiliaryData)
6820 .addImm(HasVIndex ? -1 : 0)
6821 .addMemOperand(MMO);
6823 MI.eraseFromParent();
6829 unsigned ImmOffset,
unsigned Format,
6832 auto MIB =
B.buildInstr(
Opc)
6843 MIB.addImm(AuxiliaryData)
6844 .addImm(HasVIndex ? -1 : 0)
6845 .addMemOperand(MMO);
6851 Register SOffset,
unsigned ImmOffset,
6852 unsigned Format,
unsigned AuxiliaryData,
6856 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6858 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6861 B.buildUnmerge(Unmerge, LoadDstReg);
6867 bool IsTyped)
const {
6881 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6882 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6884 StatusDst =
MI.getOperand(1).getReg();
6889 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6892 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6895 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6898 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6901 VIndex =
B.buildConstant(I32, 0).getReg(0);
6904 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6905 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6909 Format =
MI.getOperand(5 + OpOffset).getImm();
6913 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6923 Dst =
MI.getOperand(0).getReg();
6924 B.setInsertPt(
B.getMBB(),
MI);
6931 Dst =
MI.getOperand(0).getReg();
6932 B.setInsertPt(
B.getMBB(),
MI);
6936 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6937 const bool Unpacked = ST.hasUnpackedD16VMem();
6939 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6940 const Function &Fn =
B.getMF().getFunction();
6942 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6945 B.buildUndef(StatusDst);
6946 MI.eraseFromParent();
6950 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6951 const Function &Fn =
B.getMF().getFunction();
6953 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6956 B.buildUndef(StatusDst);
6957 MI.eraseFromParent();
6969 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6970 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6971 }
else if (IsFormat) {
6973 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
6974 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6976 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6977 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6982 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6983 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6986 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6987 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6990 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6991 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6996 if (IsTFE && IsD16 && Ty.isVector()) {
6998 const unsigned NumElts = Ty.getNumElements();
6999 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7002 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7005 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7010 R =
B.buildTrunc(EltTy, R).getReg(0);
7011 B.buildMergeLikeInstr(Dst, ValueDWords);
7020 if (PackedTy == Ty) {
7021 B.buildBitcast(Dst, Merged);
7023 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7024 B.buildDeleteTrailingVectorElements(Dst, Packed);
7028 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7036 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7038 B.buildTrunc(DstInt, ExtDst);
7039 }
else if (NumValueDWords == 1) {
7041 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7045 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7048 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7049 IsTyped, HasVIndex,
B);
7050 B.buildMergeLikeInstr(DstInt, ValueDWords);
7053 B.buildBitcast(Dst, DstInt);
7055 (IsD16 && !Ty.isVector())) {
7056 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7058 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7059 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7060 B.buildTrunc(Dst, LoadDstReg);
7061 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7063 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7065 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7066 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7068 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7070 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7071 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7072 B.buildMergeLikeInstr(Dst, Repack);
7075 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7078 MI.eraseFromParent();
7084 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7085 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7086 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7087 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7088 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7089 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7090 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7091 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7092 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7093 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7094 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7095 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7096 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7097 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7098 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7099 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7100 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7101 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7102 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7103 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7104 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7105 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7106 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7107 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7108 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7109 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7110 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7111 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7112 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7113 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7114 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7115 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7116 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7117 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7118 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7119 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7120 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7121 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7122 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7123 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7124 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7125 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7126 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7127 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7128 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7129 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7130 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7131 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7132 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7133 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7134 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7135 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7136 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7137 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7138 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7139 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7140 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7141 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7142 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7143 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7144 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7145 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7146 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7147 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7148 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7149 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7150 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7151 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7152 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7153 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7154 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7155 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7156 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7157 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7158 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7159 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7160 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7161 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7162 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7163 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7164 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7165 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7166 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7167 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7168 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7169 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7170 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7171 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7172 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7173 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7182 const bool IsCmpSwap =
7183 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7184 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7185 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7186 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7197 CmpVal =
MI.getOperand(3).getReg();
7202 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7203 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7206 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7209 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7215 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7216 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7217 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7236 .addImm(AuxiliaryData)
7237 .addImm(HasVIndex ? -1 : 0)
7238 .addMemOperand(MMO);
7240 MI.eraseFromParent();
7250 bool IsA16,
bool IsG16) {
7264 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7269 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7273 "Bias needs to be converted to 16 bit in A16 mode");
7275 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7279 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7283 if (((
I + 1) >= EndIdx) ||
7290 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7292 B.buildBuildVector(V2EltTy,
7293 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7298 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7309 int DimIdx,
int NumVAddrs) {
7311 for (
int I = 0;
I != NumVAddrs; ++
I) {
7313 if (
SrcOp.isReg()) {
7316 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7317 if (
B.getMRI()->getType(
Reg) != I32)
7318 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7323 int NumAddrRegs = AddrRegs.
size();
7324 if (NumAddrRegs != 1) {
7325 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7328 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7331 for (
int I = 1;
I != NumVAddrs; ++
I) {
7334 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7356 const unsigned NumDefs =
MI.getNumExplicitDefs();
7357 const unsigned ArgOffset = NumDefs + 1;
7358 bool IsTFE = NumDefs == 2;
7376 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7380 const bool IsAtomicPacked16Bit =
7381 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7382 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7389 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7390 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7391 const bool DataTyIs16 =
7392 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7394 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7395 const bool IsA16 = AddrTyIs16;
7396 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7399 if (!BaseOpcode->
Atomic) {
7400 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7403 }
else if (DMask != 0) {
7405 }
else if (!IsTFE && !BaseOpcode->
Store) {
7407 B.buildUndef(
MI.getOperand(0));
7408 MI.eraseFromParent();
7416 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7417 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7418 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7419 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7420 unsigned NewOpcode = LoadOpcode;
7421 if (BaseOpcode->
Store)
7422 NewOpcode = StoreOpcode;
7424 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7427 MI.setDesc(
B.getTII().get(NewOpcode));
7431 if (IsTFE && DMask == 0) {
7434 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7437 if (BaseOpcode->
Atomic) {
7442 if (Ty.isVector() && !IsAtomicPacked16Bit)
7449 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7450 MI.getOperand(2).setReg(
Concat.getReg(0));
7451 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7455 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7458 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7464 if (IsA16 && !ST.hasA16()) {
7469 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7470 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7472 if (IsA16 || IsG16) {
7480 const bool UseNSA = ST.hasNSAEncoding() &&
7481 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7482 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7483 const bool UsePartialNSA =
7484 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7486 if (UsePartialNSA) {
7490 auto Concat =
B.buildConcatVectors(
7491 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7492 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7493 PackedRegs.
resize(NSAMaxSize);
7494 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7496 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7497 PackedRegs[0] =
Concat.getReg(0);
7501 const unsigned NumPacked = PackedRegs.
size();
7504 if (!
SrcOp.isReg()) {
7514 SrcOp.setReg(AMDGPU::NoRegister);
7531 const bool UseNSA = ST.hasNSAEncoding() &&
7532 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7533 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7534 const bool UsePartialNSA =
7535 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7537 if (UsePartialNSA) {
7539 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7541 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7556 if (!Ty.isVector() || !IsD16)
7560 if (RepackedReg != VData) {
7561 MI.getOperand(1).setReg(RepackedReg);
7569 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7572 if (NumElts < DMaskLanes)
7575 if (NumElts > 4 || DMaskLanes > 4)
7586 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7587 const LLT AdjustedTy =
7603 if (IsD16 && ST.hasUnpackedD16VMem()) {
7610 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7611 unsigned RoundedSize = 32 * RoundedElts;
7615 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7620 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7626 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7630 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7631 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7635 MI.getOperand(0).setReg(NewResultReg);
7643 Dst1Reg =
MI.getOperand(1).getReg();
7644 if (MRI->
getType(Dst1Reg) != I32)
7648 MI.removeOperand(1);
7651 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7652 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7653 B.buildBitcast(DstReg, Unmerge.getReg(0));
7654 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7663 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7665 if (ResultNumRegs == 1) {
7667 ResultRegs[0] = NewResultReg;
7670 for (
int I = 0;
I != NumDataRegs; ++
I)
7672 B.buildUnmerge(ResultRegs, NewResultReg);
7677 ResultRegs.
resize(NumDataRegs);
7682 if (IsD16 && !Ty.isVector()) {
7683 B.buildTrunc(DstReg, ResultRegs[0]);
7688 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7689 !ST.hasUnpackedD16VMem()) {
7690 B.buildBitcast(DstReg, ResultRegs[0]);
7702 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7704 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7705 }
else if (ST.hasUnpackedD16VMem()) {
7707 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7711 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7715 for (
int I = 0;
I != NumElts; ++
I)
7722 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7723 B.buildBuildVector(DstReg, ResultRegs);
7727 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7728 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7733 if (Ty == V3I16 || Ty == V3F16) {
7735 if (ResultRegs.
size() == 1) {
7736 NewResultReg = ResultRegs[0];
7737 }
else if (ResultRegs.
size() == 2) {
7739 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7754 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7756 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7758 if (ResizeDst != DstReg)
7759 B.buildBitcast(DstReg, ResizeDst);
7763 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7764 B.buildConcatVectors(DstReg, ResultRegs);
7773 Register OrigDst =
MI.getOperand(0).getReg();
7775 LLT Ty =
B.getMRI()->getType(OrigDst);
7776 unsigned Size = Ty.getSizeInBits();
7778 bool HasMMO = !
MI.memoperands_empty();
7783 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7784 if (
Size % 32 != 0 && !IsSubwordLoad) {
7787 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7788 B.buildUndef(OrigDst);
7789 MI.eraseFromParent();
7794 if (IsSubwordLoad) {
7796 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7797 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7800 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7802 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7811 B.setInsertPt(
B.getMBB(),
MI);
7816 B.setInsertPt(
B.getMBB(),
MI);
7819 MI.setDesc(
B.getTII().get(
Opc));
7820 MI.removeOperand(1);
7826 const unsigned MemSize = (
Size + 7) / 8;
7827 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7834 MI.addMemOperand(MF, MMO);
7836 if (Dst != OrigDst) {
7837 MI.getOperand(0).setReg(Dst);
7838 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7839 B.buildTrunc(OrigDst, Dst);
7861 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7862 MI.removeOperand(0);
7873 if (!ST.hasTrapHandler() ||
7877 return ST.supportsGetDoorbellID() ?
7892 MI.eraseFromParent();
7904 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7913 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7915 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7919 MI.eraseFromParent();
7928 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7935 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7955 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7958 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7959 B.buildCopy(SGPR01, Temp);
7960 B.buildInstr(AMDGPU::S_TRAP)
7963 MI.eraseFromParent();
7974 B.buildCopy(SGPR01, LiveIn);
7975 B.buildInstr(AMDGPU::S_TRAP)
7979 MI.eraseFromParent();
7988 if (ST.hasPrivEnabledTrap2NopBug()) {
7989 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7991 MI.eraseFromParent();
7995 B.buildInstr(AMDGPU::S_TRAP)
7997 MI.eraseFromParent();
8006 if (!ST.hasTrapHandler() ||
8010 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8013 B.buildInstr(AMDGPU::S_TRAP)
8017 MI.eraseFromParent();
8031 Register NodePtr =
MI.getOperand(2).getReg();
8032 Register RayExtent =
MI.getOperand(3).getReg();
8033 Register RayOrigin =
MI.getOperand(4).getReg();
8035 Register RayInvDir =
MI.getOperand(6).getReg();
8038 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8045 const unsigned NumVDataDwords = 4;
8046 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8047 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8049 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8051 const unsigned BaseOpcodes[2][2] = {
8052 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8053 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8054 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8058 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8059 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8060 : AMDGPU::MIMGEncGfx10NSA,
8061 NumVDataDwords, NumVAddrDwords);
8065 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8066 : AMDGPU::MIMGEncGfx10Default,
8067 NumVDataDwords, NumVAddrDwords);
8072 if (UseNSA && IsGFX11Plus) {
8073 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8074 auto SrcInt =
B.buildBitcast(V3I32, Src);
8075 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8076 auto Merged =
B.buildMergeLikeInstr(
8077 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8078 Ops.push_back(Merged.getReg(0));
8081 Ops.push_back(NodePtr);
8082 Ops.push_back(RayExtent);
8083 packLanes(RayOrigin);
8086 auto UnmergeRayDir =
8087 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8088 auto UnmergeRayInvDir =
8089 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8090 auto MergedDir =
B.buildMergeLikeInstr(
8093 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8094 UnmergeRayDir.getReg(0)}))
8097 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8098 UnmergeRayDir.getReg(1)}))
8101 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8102 UnmergeRayDir.getReg(2)}))
8104 Ops.push_back(MergedDir.getReg(0));
8107 packLanes(RayInvDir);
8111 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8112 Ops.push_back(Unmerge.getReg(0));
8113 Ops.push_back(Unmerge.getReg(1));
8115 Ops.push_back(NodePtr);
8117 Ops.push_back(RayExtent);
8119 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8120 auto SrcInt =
B.buildBitcast(V3I32, Src);
8121 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8122 Ops.push_back(Unmerge.getReg(0));
8123 Ops.push_back(Unmerge.getReg(1));
8124 Ops.push_back(Unmerge.getReg(2));
8127 packLanes(RayOrigin);
8129 auto UnmergeRayDir =
8130 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8131 auto UnmergeRayInvDir =
8132 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8136 B.buildMergeLikeInstr(R1,
8137 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8138 B.buildMergeLikeInstr(
8139 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8140 B.buildMergeLikeInstr(
8141 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8147 packLanes(RayInvDir);
8156 Ops.push_back(MergedOps);
8159 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8168 .addImm(IsA16 ? 1 : 0)
8171 MI.eraseFromParent();
8181 Register DstOrigin =
MI.getOperand(1).getReg();
8183 Register NodePtr =
MI.getOperand(4).getReg();
8184 Register RayExtent =
MI.getOperand(5).getReg();
8185 Register InstanceMask =
MI.getOperand(6).getReg();
8186 Register RayOrigin =
MI.getOperand(7).getReg();
8188 Register Offsets =
MI.getOperand(9).getReg();
8189 Register TDescr =
MI.getOperand(10).getReg();
8192 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8193 const unsigned NumVDataDwords = 10;
8194 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8196 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8197 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8198 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8201 auto RayExtentInstanceMaskVec =
8202 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8203 B.buildAnyExt(I32, InstanceMask)});
8205 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8206 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8212 .addUse(RayExtentInstanceMaskVec.getReg(0))
8219 MI.eraseFromParent();
8228 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8229 MI.eraseFromParent();
8236 if (!ST.hasArchitectedSGPRs())
8240 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8241 auto LSB =
B.buildConstant(I32, 25);
8242 auto Width =
B.buildConstant(I32, 5);
8243 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8244 MI.eraseFromParent();
8252 unsigned Width)
const {
8256 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8257 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8260 B.buildCopy(DstReg, Result);
8261 MI.eraseFromParent();
8281 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8285 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8288 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8289 MI.eraseFromParent();
8302 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8306 .addReg(Unmerge.getReg(0));
8310 .addReg(Unmerge.getReg(1));
8311 MI.eraseFromParent();
8323 case Intrinsic::sponentry:
8329 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8332 B.buildIntToPtr(DstReg, TmpReg);
8333 MI.eraseFromParent();
8335 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8337 B.buildFrameIndex(
MI.getOperand(0), FI);
8338 MI.eraseFromParent();
8341 case Intrinsic::amdgcn_if:
8342 case Intrinsic::amdgcn_else: {
8345 bool Negated =
false;
8362 std::swap(CondBrTarget, UncondBrTarget);
8364 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8365 B.buildCopy(NewUse,
Use);
8366 if (IntrID == Intrinsic::amdgcn_if) {
8367 B.buildInstr(AMDGPU::SI_IF)
8370 .addMBB(UncondBrTarget);
8372 B.buildInstr(AMDGPU::SI_ELSE)
8375 .addMBB(UncondBrTarget);
8384 B.buildBr(*CondBrTarget);
8387 MI.eraseFromParent();
8388 BrCond->eraseFromParent();
8399 case Intrinsic::amdgcn_loop: {
8402 bool Negated =
false;
8411 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8414 std::swap(CondBrTarget, UncondBrTarget);
8416 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8417 B.buildCopy(NewReg, Reg);
8418 B.buildInstr(AMDGPU::SI_LOOP).addUse(NewReg).addMBB(UncondBrTarget);
8423 B.buildBr(*CondBrTarget);
8425 MI.eraseFromParent();
8426 BrCond->eraseFromParent();
8432 case Intrinsic::amdgcn_wave_reduce_min:
8433 case Intrinsic::amdgcn_wave_reduce_umin:
8434 case Intrinsic::amdgcn_wave_reduce_fmin:
8435 case Intrinsic::amdgcn_wave_reduce_max:
8436 case Intrinsic::amdgcn_wave_reduce_umax:
8437 case Intrinsic::amdgcn_wave_reduce_fmax:
8438 case Intrinsic::amdgcn_wave_reduce_add:
8439 case Intrinsic::amdgcn_wave_reduce_fadd:
8440 case Intrinsic::amdgcn_wave_reduce_sub:
8441 case Intrinsic::amdgcn_wave_reduce_fsub:
8442 case Intrinsic::amdgcn_wave_reduce_and:
8443 case Intrinsic::amdgcn_wave_reduce_or:
8444 case Intrinsic::amdgcn_wave_reduce_xor: {
8449 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8450 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8451 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8452 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8453 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8454 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8455 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8456 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8457 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8464 .addUse(Ext.getReg(0))
8465 .addImm(
MI.getOperand(3).getImm());
8467 B.buildFPTrunc(DstReg, NewDst);
8469 B.buildTrunc(DstReg, NewDst);
8470 MI.eraseFromParent();
8473 case Intrinsic::amdgcn_make_buffer_rsrc:
8475 case Intrinsic::amdgcn_kernarg_segment_ptr:
8478 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8479 MI.eraseFromParent();
8485 case Intrinsic::amdgcn_implicitarg_ptr:
8487 case Intrinsic::amdgcn_workitem_id_x:
8490 case Intrinsic::amdgcn_workitem_id_y:
8493 case Intrinsic::amdgcn_workitem_id_z:
8496 case Intrinsic::amdgcn_workgroup_id_x:
8501 case Intrinsic::amdgcn_workgroup_id_y:
8506 case Intrinsic::amdgcn_workgroup_id_z:
8511 case Intrinsic::amdgcn_cluster_id_x:
8512 return ST.hasClusters() &&
8515 case Intrinsic::amdgcn_cluster_id_y:
8516 return ST.hasClusters() &&
8519 case Intrinsic::amdgcn_cluster_id_z:
8520 return ST.hasClusters() &&
8523 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8524 return ST.hasClusters() &&
8527 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8528 return ST.hasClusters() &&
8531 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8532 return ST.hasClusters() &&
8535 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8536 return ST.hasClusters() &&
8538 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8539 return ST.hasClusters() &&
8542 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8543 return ST.hasClusters() &&
8546 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8547 return ST.hasClusters() &&
8550 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8551 return ST.hasClusters() &&
8555 case Intrinsic::amdgcn_wave_id:
8557 case Intrinsic::amdgcn_lds_kernel_id:
8560 case Intrinsic::amdgcn_dispatch_ptr:
8563 case Intrinsic::amdgcn_queue_ptr:
8566 case Intrinsic::amdgcn_implicit_buffer_ptr:
8569 case Intrinsic::amdgcn_dispatch_id:
8572 case Intrinsic::r600_read_ngroups_x:
8576 case Intrinsic::r600_read_ngroups_y:
8579 case Intrinsic::r600_read_ngroups_z:
8582 case Intrinsic::r600_read_local_size_x:
8585 case Intrinsic::r600_read_local_size_y:
8589 case Intrinsic::r600_read_local_size_z:
8592 case Intrinsic::amdgcn_fdiv_fast:
8594 case Intrinsic::amdgcn_is_shared:
8596 case Intrinsic::amdgcn_is_private:
8598 case Intrinsic::amdgcn_wavefrontsize: {
8599 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8600 MI.eraseFromParent();
8603 case Intrinsic::amdgcn_s_buffer_load:
8604 case Intrinsic::amdgcn_ptr_s_buffer_load:
8606 case Intrinsic::amdgcn_raw_buffer_store:
8607 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8608 case Intrinsic::amdgcn_struct_buffer_store:
8609 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8611 case Intrinsic::amdgcn_raw_buffer_store_format:
8612 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8613 case Intrinsic::amdgcn_struct_buffer_store_format:
8614 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8616 case Intrinsic::amdgcn_raw_tbuffer_store:
8617 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8618 case Intrinsic::amdgcn_struct_tbuffer_store:
8619 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8621 case Intrinsic::amdgcn_raw_buffer_load:
8622 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8623 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8624 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8625 case Intrinsic::amdgcn_struct_buffer_load:
8626 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8627 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8628 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8630 case Intrinsic::amdgcn_raw_buffer_load_format:
8631 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8632 case Intrinsic::amdgcn_struct_buffer_load_format:
8633 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8635 case Intrinsic::amdgcn_raw_tbuffer_load:
8636 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8637 case Intrinsic::amdgcn_struct_tbuffer_load:
8638 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8640 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8641 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8642 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8643 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8644 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8645 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8646 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8647 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8648 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8649 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8650 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8651 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8652 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8653 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8654 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8655 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8656 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8657 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8658 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8659 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8660 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8661 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8662 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8663 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8664 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8665 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8666 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8667 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8668 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8669 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8670 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8671 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8672 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8673 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8674 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8675 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8676 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8677 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8678 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8679 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8680 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8681 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8682 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8683 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8684 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8685 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8686 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8687 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8688 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8689 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8690 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8691 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8692 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8693 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8694 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8695 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8696 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8697 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8698 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8699 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8700 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8701 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8702 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8703 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8704 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8705 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8706 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8707 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8708 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8709 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8710 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8711 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8713 case Intrinsic::amdgcn_rsq_clamp:
8715 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8717 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8718 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8720 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8721 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8722 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8723 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8724 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8725 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8726 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8727 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8731 if (IndexArgTy != I64) {
8732 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8733 :
B.buildAnyExt(I64, Index);
8734 MI.getOperand(5).setReg(NewIndex.getReg(0));
8738 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8739 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8740 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8741 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8742 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8743 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8744 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8745 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8748 if (MRI.
getType(Index) != I32)
8749 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8752 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8753 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8754 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8755 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8756 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8757 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8758 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8759 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8760 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8762 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8766 if (IndexArgTy != IdxTy) {
8767 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8768 :
B.buildAnyExt(IdxTy, Index);
8769 MI.getOperand(7).setReg(NewIndex.getReg(0));
8774 case Intrinsic::amdgcn_fmed3: {
8780 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8781 MI.removeOperand(1);
8785 case Intrinsic::amdgcn_readlane:
8786 case Intrinsic::amdgcn_writelane:
8787 case Intrinsic::amdgcn_readfirstlane:
8788 case Intrinsic::amdgcn_permlane16:
8789 case Intrinsic::amdgcn_permlanex16:
8790 case Intrinsic::amdgcn_permlane64:
8791 case Intrinsic::amdgcn_set_inactive:
8792 case Intrinsic::amdgcn_set_inactive_chain_arg:
8793 case Intrinsic::amdgcn_mov_dpp8:
8794 case Intrinsic::amdgcn_update_dpp:
8795 case Intrinsic::amdgcn_permlane_bcast:
8796 case Intrinsic::amdgcn_permlane_up:
8797 case Intrinsic::amdgcn_permlane_down:
8798 case Intrinsic::amdgcn_permlane_xor:
8800 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8802 case Intrinsic::amdgcn_dead: {
8806 MI.eraseFromParent();
8809 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8810 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8811 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8812 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8813 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8814 MI.eraseFromParent();
8816 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8817 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8818 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8819 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8820 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8821 MI.eraseFromParent();
8823 case Intrinsic::amdgcn_av_load_b128:
8824 case Intrinsic::amdgcn_av_store_b128: {
8825 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8826 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8827 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8829 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8830 **
MI.memoperands_begin());
8831 MI.eraseFromParent();
8834 case Intrinsic::amdgcn_flat_load_monitor_b32:
8835 case Intrinsic::amdgcn_flat_load_monitor_b64:
8836 case Intrinsic::amdgcn_flat_load_monitor_b128:
8837 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8838 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8839 .add(
MI.getOperand(0))
8840 .add(
MI.getOperand(2))
8841 .addMemOperand(*
MI.memoperands_begin());
8842 MI.eraseFromParent();
8844 case Intrinsic::amdgcn_global_load_monitor_b32:
8845 case Intrinsic::amdgcn_global_load_monitor_b64:
8846 case Intrinsic::amdgcn_global_load_monitor_b128:
8847 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8848 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8849 .add(
MI.getOperand(0))
8850 .add(
MI.getOperand(2))
8851 .addMemOperand(*
MI.memoperands_begin());
8852 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static void buildTFEBufferLoad(unsigned Opc, ArrayRef< Register > ValueDsts, Register StatusDst, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
unsigned getPointerSizeInBits(unsigned AS) const
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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)
unsigned getSyntheticApertureNumber(unsigned AS)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.