36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
488 if (!ST.hasDwordx3LoadStores())
501 if (AlignBits < MemSize) {
504 Align(AlignBits / 8)))
534 const unsigned Size = Ty.getSizeInBits();
535 if (Ty.isPointerVector())
545 unsigned EltSize = Ty.getScalarSizeInBits();
546 return EltSize != 32 && EltSize != 64;
560 const unsigned Size = Ty.getSizeInBits();
561 if (
Size != MemSizeInBits)
562 return Size <= 32 && Ty.isVector();
568 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
577 uint64_t AlignInBits,
unsigned AddrSpace,
587 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
598 if (AlignInBits < RoundedSize)
605 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
617 Query.
Types[1].getAddressSpace(), Opcode);
637 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
641 std::array<Register, 4> VectorElems;
642 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
643 for (
unsigned I = 0;
I < NumParts; ++
I)
645 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
646 B.buildMergeValues(MO, VectorElems);
651 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
652 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
653 B.buildIntToPtr(MO, Scalar);
673 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
675 for (
unsigned I = 0;
I < NumParts; ++
I)
677 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
679 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
680 return B.buildBitcast(VectorTy, Scalar).getReg(0);
708 const LLT BufferStridedPtr =
711 const LLT CodePtr = FlatPtr;
713 const std::initializer_list<LLT> AddrSpaces64 = {
714 GlobalPtr, ConstantPtr, FlatPtr
717 const std::initializer_list<LLT> AddrSpaces32 = {
718 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
721 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
723 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
724 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
725 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
754 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
756 if (ST.hasAnyPackedU64Ops()) {
759 .clampMaxNumElementsStrict(0,
S16, 2)
765 }
else if (ST.hasScalarAddSub64()) {
768 .clampMaxNumElementsStrict(0,
S16, 2)
776 .clampMaxNumElementsStrict(0,
S16, 2)
783 if (ST.hasScalarSMulU64()) {
786 .clampMaxNumElementsStrict(0,
S16, 2)
794 .clampMaxNumElementsStrict(0,
S16, 2)
804 .minScalarOrElt(0,
S16)
809 }
else if (ST.has16BitInsts()) {
843 .widenScalarToNextMultipleOf(0, 32)
853 if (ST.hasMad64_32())
858 if (ST.hasIntClamp()) {
881 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
891 if (ST.hasVOP3PInsts()) {
893 .clampMaxNumElements(0,
S8, 2)
914 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
930 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
971 auto &FCanonicalizeActions =
973 auto &StrictFPOpActions =
980 if (ST.has16BitInsts()) {
981 if (ST.hasVOP3PInsts()) {
983 FCanonicalizeActions.legalFor({
F16,
V2F16});
984 StrictFPOpActions.legalFor({
F16,
V2F16});
986 FPOpActions.legalFor({
F16});
987 FCanonicalizeActions.legalFor({
F16});
988 StrictFPOpActions.legalFor({
F16});
991 TrigActions.customFor({
F16});
992 FDIVActions.customFor({
F16});
995 if (ST.hasBF16PackedInsts()) {
996 FPOpActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
997 FCanonicalizeActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16,
999 StrictFPOpActions.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1005 if (ST.hasAnyPackedFP32Ops()) {
1006 FPOpActions.legalFor({
V2F32});
1007 FCanonicalizeActions.legalFor({
V2F32});
1008 StrictFPOpActions.legalFor({
V2F32});
1009 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1010 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1011 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1014 if (ST.hasAnyPackedFP64Ops()) {
1015 FPOpActions.legalFor({
V2F64});
1016 FCanonicalizeActions.legalFor({
V2F64});
1017 StrictFPOpActions.legalFor({
V2F64});
1018 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1019 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1020 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1023 auto &MinNumMaxNumIeee =
1026 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1031 if (ST.has16BitInsts()) {
1032 MinNumMaxNumIeee.legalFor({
F16});
1033 MinNumMaxNum.customFor({
F16});
1037 if (ST.hasVOP3PInsts()) {
1038 MinNumMaxNumIeee.legalFor({
V2F16})
1041 .clampMaxNumElements(0,
F16, 2);
1042 MinNumMaxNum.customFor({
V2F16})
1045 .clampMaxNumElements(0,
F16, 2);
1049 if (ST.hasAnyPackedFP64Ops()) {
1050 MinNumMaxNum.customFor({
V2F64})
1053 .clampMaxNumElements(0,
F64, 2);
1057 if (ST.hasBF16PackedInsts()) {
1058 MinNumMaxNumIeee.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1059 MinNumMaxNum.customFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1065 if (!ST.has16BitInsts()) {
1066 MinNumMaxNumIeee.minScalar(0,
F32);
1067 MinNumMaxNum.minScalar(0,
F32);
1070 if (ST.hasVOP3PInsts()) {
1071 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1072 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1073 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1081 if (!ST.has16BitInsts()) {
1092 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1095 if (ST.hasAnyPackedFP32Ops())
1099 if (ST.has16BitInsts()) {
1102 .legalFor(ST.hasBF16TransInsts(), {BF16})
1112 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1134 if (ST.hasFractBug()) {
1148 .legalFor({{
F32, I32}, {
F64, I32}})
1168 if (ST.hasCvtPkF16F32Inst()) {
1170 .clampMaxNumElements(0,
F16, 2);
1183 if (ST.has16BitInsts()) {
1197 if (ST.hasBF16PackedInsts()) {
1198 FSubActions.lowerFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1201 if (ST.hasAnyPackedFP32Ops())
1209 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1210 FMad.customFor({
F32,
F16});
1211 else if (ST.hasMadMacF32Insts())
1212 FMad.customFor({
F32});
1213 else if (ST.hasMadF16())
1214 FMad.customFor({
F16});
1219 if (ST.has16BitInsts()) {
1222 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1230 .clampMaxNumElements(0,
S16, 2)
1246 .legalFor({{
F32, I32}, {
F64, I32}})
1250 if (ST.has16BitInsts())
1258 .legalFor({{I32,
F32}, {I32,
F64}})
1259 .customFor({{I64,
F32}, {I64,
F64}})
1262 if (ST.has16BitInsts())
1271 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1272 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1273 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1277 if (
ST.has16BitInsts())
1280 if (
ST.hasVCvtPkIU16F32())
1290 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1291 .clampScalar(0, I16, I64)
1295 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1301 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1305 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1306 .clampScalar(0, I16, I64)
1310 auto &RoundingActions = getActionDefinitionsBuilder(
1311 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1312 if (
ST.has16BitInsts())
1320 if (!
ST.has16BitInsts())
1323 getActionDefinitionsBuilder(G_PTR_ADD)
1329 getActionDefinitionsBuilder(G_PTRMASK)
1331 .scalarSameSizeAs(1, 0)
1335 getActionDefinitionsBuilder(G_ICMP)
1347 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1348 .legalForCartesianProduct(
1349 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1350 if (
ST.has16BitInsts()) {
1351 CmpBuilder.legalFor({{
S1,
S16}});
1360 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1363 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1364 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1366 if (
ST.hasSALUFloatInsts())
1367 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1369 FCmpBuilder.widenScalarToNextPow2(1).minScalar(1,
F32).scalarize(0);
1371 getActionDefinitionsBuilder(G_FPOW)
1373 .clampScalar(0,
F32,
F32)
1376 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1378 getActionDefinitionsBuilder(G_FLOG2)
1379 .legalFor(
ST.has16BitInsts(), {F16})
1380 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1386 getActionDefinitionsBuilder(G_FEXP2)
1387 .legalFor(
ST.has16BitInsts(), {F16})
1388 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1394 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1398 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1403 getActionDefinitionsBuilder(G_CTPOP)
1405 .clampScalar(0,
S32,
S32)
1406 .widenScalarToNextPow2(1, 32)
1407 .clampScalar(1,
S32,
S64)
1409 .widenScalarToNextPow2(0, 32);
1412 if (
ST.has16BitInsts())
1413 getActionDefinitionsBuilder(G_IS_FPCLASS)
1414 .legalForCartesianProduct({
I1}, FPTypes16)
1415 .widenScalarToNextPow2(1)
1419 getActionDefinitionsBuilder(G_IS_FPCLASS)
1420 .legalForCartesianProduct({
I1}, FPTypesBase)
1421 .lowerFor({
I1,
F16})
1422 .widenScalarToNextPow2(1)
1429 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1431 .clampScalar(0,
S32,
S32)
1432 .clampScalar(1,
S32,
S64)
1433 .widenScalarToNextPow2(0, 32)
1434 .widenScalarToNextPow2(1, 32)
1438 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1441 .clampScalar(0,
S32,
S32)
1442 .clampScalar(1,
S32,
S64)
1444 .widenScalarToNextPow2(0, 32)
1445 .widenScalarToNextPow2(1, 32);
1447 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1449 .clampScalar(0,
S32,
S32)
1450 .clampScalar(1,
S32,
S64)
1452 .widenScalarToNextPow2(0, 32)
1453 .widenScalarToNextPow2(1, 32);
1455 getActionDefinitionsBuilder(G_CTLS)
1458 .clampScalar(0,
S32,
S32)
1459 .clampScalar(1,
S32,
S32);
1463 getActionDefinitionsBuilder(G_BITREVERSE)
1465 .clampScalar(0,
S32,
S64)
1467 .widenScalarToNextPow2(0);
1469 if (
ST.has16BitInsts()) {
1470 getActionDefinitionsBuilder(G_BSWAP)
1472 .clampMaxNumElementsStrict(0,
S16, 2)
1475 .widenScalarToNextPow2(0)
1476 .clampScalar(0,
S16,
S32)
1479 if (
ST.hasVOP3PInsts()) {
1480 getActionDefinitionsBuilder(G_ABS)
1482 .clampMaxNumElements(0,
S16, 2)
1484 .widenScalarToNextPow2(0)
1487 if (
ST.useMinMaxI64Insts()) {
1488 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1490 .clampMaxNumElements(0,
S16, 2)
1492 .widenScalarToNextPow2(0)
1496 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1498 .clampMaxNumElements(0,
S16, 2)
1500 .widenScalarToNextPow2(0)
1505 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1507 .widenScalarToNextPow2(0)
1514 getActionDefinitionsBuilder(G_BSWAP)
1519 .widenScalarToNextPow2(0)
1524 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1527 .widenScalarToNextPow2(0)
1532 getActionDefinitionsBuilder(G_INTTOPTR)
1534 .legalForCartesianProduct(AddrSpaces64, {
S64})
1535 .legalForCartesianProduct(AddrSpaces32, {
S32})
1548 getActionDefinitionsBuilder(G_PTRTOINT)
1550 .legalForCartesianProduct(AddrSpaces64, {
S64})
1551 .legalForCartesianProduct(AddrSpaces32, {
S32})
1564 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1568 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1569 bool IsLoad) ->
bool {
1573 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1587 unsigned NumRegs = (MemSize + 31) / 32;
1589 if (!
ST.hasDwordx3LoadStores())
1600 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1601 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1602 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1608 for (
unsigned Op : {G_LOAD, G_STORE}) {
1609 const bool IsStore =
Op == G_STORE;
1611 auto &Actions = getActionDefinitionsBuilder(
Op);
1614 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1617 {
S64, GlobalPtr,
S64, GlobalAlign32},
1620 {
S32, GlobalPtr,
S8, GlobalAlign8},
1621 {
S32, GlobalPtr,
S16, GlobalAlign16},
1623 {
S32, LocalPtr,
S32, 32},
1624 {
S64, LocalPtr,
S64, 32},
1626 {
S32, LocalPtr,
S8, 8},
1627 {
S32, LocalPtr,
S16, 16},
1630 {
S32, PrivatePtr,
S32, 32},
1631 {
S32, PrivatePtr,
S8, 8},
1632 {
S32, PrivatePtr,
S16, 16},
1635 {
S32, ConstantPtr,
S32, GlobalAlign32},
1638 {
S64, ConstantPtr,
S64, GlobalAlign32},
1639 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1641 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1642 {{S16, GlobalPtr, S8, GlobalAlign8},
1643 {S16, GlobalPtr, S16, GlobalAlign16},
1644 {S16, LocalPtr, S8, 8},
1645 {S16, LocalPtr, S16, 16},
1646 {S16, PrivatePtr, S8, 8},
1647 {S16, PrivatePtr, S16, 16}});
1657 Actions.unsupportedIf(
1658 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1672 Actions.customIf(
typeIs(1, Constant32Ptr));
1698 return !Query.
Types[0].isVector() &&
1699 needToSplitMemOp(Query,
Op == G_LOAD);
1701 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1706 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1709 if (DstSize > MemSize)
1715 if (MemSize > MaxSize)
1723 return Query.
Types[0].isVector() &&
1724 needToSplitMemOp(Query,
Op == G_LOAD);
1726 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1740 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1741 if (MemSize > MaxSize) {
1745 if (MaxSize % EltSize == 0) {
1751 unsigned NumPieces = MemSize / MaxSize;
1755 if (NumPieces == 1 || NumPieces >= NumElts ||
1756 NumElts % NumPieces != 0)
1757 return std::pair(0, EltTy);
1765 return std::pair(0, EltTy);
1780 return std::pair(0, EltTy);
1785 .widenScalarToNextPow2(0)
1792 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1793 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1794 {
S32, GlobalPtr,
S16, 2 * 8},
1795 {
S32, LocalPtr,
S8, 8},
1796 {
S32, LocalPtr,
S16, 16},
1797 {
S32, PrivatePtr,
S8, 8},
1798 {
S32, PrivatePtr,
S16, 16},
1799 {
S32, ConstantPtr,
S8, 8},
1800 {
S32, ConstantPtr,
S16, 2 * 8}})
1801 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1802 {{S16, GlobalPtr, S8, GlobalAlign8},
1803 {S16, LocalPtr, S8, GlobalAlign8},
1804 {S16, PrivatePtr, S8, GlobalAlign8},
1805 {S16, ConstantPtr, S8, GlobalAlign8}})
1810 if (
ST.hasFlatAddressSpace()) {
1811 ExtLoads.legalForTypesWithMemDesc(
1812 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1814 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1815 {{S16, FlatPtr, S8, GlobalAlign8}});
1823 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1825 ExtLoads.narrowScalarIf(
1832 ExtLoads.clampScalar(0,
S32,
S32)
1833 .widenScalarToNextPow2(0)
1836 auto &Atomics = getActionDefinitionsBuilder(
1837 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1838 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1839 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1840 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1841 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1842 {
S64, GlobalPtr}, {
S64, LocalPtr},
1843 {
S32, RegionPtr}, {
S64, RegionPtr}});
1844 if (
ST.hasFlatAddressSpace()) {
1845 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1849 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1850 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1851 if (
ST.hasFlatAddressSpace()) {
1852 Atomics32.legalFor({{
S32, FlatPtr}});
1856 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1857 if (
ST.hasLDSFPAtomicAddF32()) {
1859 if (
ST.hasLdsAtomicAddF64())
1861 if (
ST.hasAtomicDsPkAdd16Insts())
1864 if (
ST.hasAtomicFaddInsts())
1866 if (
ST.hasFlatAtomicFaddF32Inst())
1869 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1873 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1876 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1877 ST.hasAtomicBufferGlobalPkAddF16Insts())
1879 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1881 if (
ST.hasAtomicFlatPkAdd16Insts())
1887 auto &AtomicFMinFMax =
1888 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1889 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1891 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1892 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1893 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1894 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1895 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1896 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1897 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1898 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1902 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1903 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1904 {
S32, FlatPtr}, {
S64, FlatPtr}})
1905 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1906 {
S32, RegionPtr}, {
S64, RegionPtr}});
1910 getActionDefinitionsBuilder(G_SELECT)
1912 LocalPtr, FlatPtr, PrivatePtr,
1916 .clampScalar(0,
S16,
S64)
1920 .clampMaxNumElements(0,
S32, 2)
1921 .clampMaxNumElements(0, LocalPtr, 2)
1922 .clampMaxNumElements(0, PrivatePtr, 2)
1924 .widenScalarToNextPow2(0)
1929 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1931 if (
ST.has16BitInsts()) {
1932 if (
ST.hasVOP3PInsts()) {
1934 .clampMaxNumElements(0,
S16, 2);
1936 Shifts.legalFor({{
S16,
S16}});
1939 Shifts.widenScalarIf(
1944 const LLT AmountTy = Query.
Types[1];
1950 Shifts.clampScalar(1,
S32,
S32);
1951 Shifts.widenScalarToNextPow2(0, 16);
1952 Shifts.clampScalar(0,
S16,
S64);
1954 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1962 Shifts.clampScalar(1,
S32,
S32);
1963 Shifts.widenScalarToNextPow2(0, 32);
1964 Shifts.clampScalar(0,
S32,
S64);
1966 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1971 Shifts.scalarize(0);
1973 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1974 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1975 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1976 unsigned IdxTypeIdx = 2;
1978 getActionDefinitionsBuilder(
Op)
1980 const LLT EltTy = Query.
Types[EltTypeIdx];
1981 const LLT VecTy = Query.
Types[VecTypeIdx];
1982 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1984 const bool isLegalVecType =
1994 return (EltSize == 32 || EltSize == 64) &&
2010 const LLT EltTy = Query.
Types[EltTypeIdx];
2011 const LLT VecTy = Query.
Types[VecTypeIdx];
2015 const unsigned TargetEltSize =
2016 DstEltSize % 64 == 0 ? 64 : 32;
2017 return std::pair(VecTypeIdx,
2021 .clampScalar(EltTypeIdx,
S32,
S64)
2022 .clampScalar(VecTypeIdx,
S32,
S64)
2023 .clampScalar(IdxTypeIdx,
S32,
S32)
2024 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2033 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2035 const LLT &EltTy = Query.
Types[1].getElementType();
2036 return Query.
Types[0] != EltTy;
2039 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2040 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2041 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2042 getActionDefinitionsBuilder(
Op)
2045 const LLT BigTy = Query.
Types[BigTyIdx];
2051 const LLT LitTy = Query.
Types[LitTyIdx];
2056 .widenScalarToNextPow2(BigTyIdx, 32)
2064 const LLT BigTy = Query.
Types[BigTyIdx];
2065 const LLT LitTy = Query.
Types[LitTyIdx];
2073 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2083 if (
ST.hasScalarPackInsts()) {
2086 .minScalarOrElt(0,
S16)
2089 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2093 BuildVector.customFor({
V2S16,
S16});
2094 BuildVector.minScalarOrElt(0,
S32);
2096 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2104 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2106 .clampMaxNumElements(0,
S32, 32)
2107 .clampMaxNumElements(1,
S16, 2)
2108 .clampMaxNumElements(0,
S16, 64);
2110 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2113 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2114 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2115 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2117 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2118 const LLT Ty = Query.
Types[TypeIdx];
2130 getActionDefinitionsBuilder(
Op)
2134 const LLT BigTy = Query.
Types[BigTyIdx];
2140 .widenScalarToNextPow2(LitTyIdx, 16)
2149 .clampScalar(LitTyIdx,
S32,
S512)
2150 .widenScalarToNextPow2(LitTyIdx, 32)
2154 return notValidElt(Query, LitTyIdx);
2159 return notValidElt(Query, BigTyIdx);
2164 if (
Op == G_MERGE_VALUES) {
2165 Builder.widenScalarIf(
2168 const LLT Ty = Query.
Types[LitTyIdx];
2174 Builder.widenScalarIf(
2176 const LLT Ty = Query.
Types[BigTyIdx];
2182 const LLT &Ty = Query.
Types[BigTyIdx];
2184 if (NewSizeInBits >= 256) {
2186 if (RoundedTo < NewSizeInBits)
2187 NewSizeInBits = RoundedTo;
2189 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2198 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2199 .legalFor({{
S32}, {
S64}})
2200 .clampScalar(0,
S32,
S64);
2202 if (
ST.hasVOP3PInsts()) {
2203 SextInReg.lowerFor({{
V2S16}})
2207 .clampMaxNumElementsStrict(0,
S16, 2);
2208 }
else if (
ST.has16BitInsts()) {
2209 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2213 SextInReg.lowerFor({{
S32}, {
S64}});
2218 .clampScalar(0,
S32,
S64)
2221 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2225 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2226 FSHRActionDefs.legalFor({{
S32,
S32}})
2227 .clampMaxNumElementsStrict(0,
S16, 2);
2228 if (
ST.hasVOP3PInsts())
2230 FSHRActionDefs.scalarize(0).lower();
2232 if (
ST.hasVOP3PInsts()) {
2233 getActionDefinitionsBuilder(G_FSHL)
2235 .clampMaxNumElementsStrict(0,
S16, 2)
2239 getActionDefinitionsBuilder(G_FSHL)
2244 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2247 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2249 getActionDefinitionsBuilder(G_FENCE)
2252 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2257 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2259 .clampScalar(1,
S32,
S32)
2260 .clampScalar(0,
S32,
S64)
2261 .widenScalarToNextPow2(0)
2264 getActionDefinitionsBuilder(
2268 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2269 G_READ_REGISTER, G_WRITE_REGISTER,
2274 if (
ST.hasIEEEMinimumMaximumInsts()) {
2275 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2276 .legalFor(FPTypesPK16)
2277 .clampMaxNumElements(0,
F16, 2)
2279 }
else if (
ST.hasVOP3PInsts()) {
2280 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2282 .clampMaxNumElementsStrict(0,
F16, 2)
2286 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2288 .clampScalar(0,
F32,
F64)
2292 getActionDefinitionsBuilder(
2293 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2296 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2298 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2299 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2300 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2303 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2305 getActionDefinitionsBuilder(
2306 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2307 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2308 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2309 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2314 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2315 G_INTRINSIC_CONVERGENT,
2316 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2328 switch (
MI.getOpcode()) {
2329 case TargetOpcode::G_ADDRSPACE_CAST:
2331 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2333 case TargetOpcode::G_FCEIL:
2335 case TargetOpcode::G_FREM:
2337 case TargetOpcode::G_INTRINSIC_TRUNC:
2339 case TargetOpcode::G_SITOFP:
2341 case TargetOpcode::G_UITOFP:
2343 case TargetOpcode::G_FPTOSI:
2345 case TargetOpcode::G_FPTOUI:
2347 case TargetOpcode::G_FMINNUM:
2348 case TargetOpcode::G_FMAXNUM:
2349 case TargetOpcode::G_FMINIMUMNUM:
2350 case TargetOpcode::G_FMAXIMUMNUM:
2352 case TargetOpcode::G_EXTRACT:
2354 case TargetOpcode::G_INSERT:
2356 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2358 case TargetOpcode::G_INSERT_VECTOR_ELT:
2360 case TargetOpcode::G_FSIN:
2361 case TargetOpcode::G_FCOS:
2363 case TargetOpcode::G_GLOBAL_VALUE:
2365 case TargetOpcode::G_LOAD:
2366 case TargetOpcode::G_SEXTLOAD:
2367 case TargetOpcode::G_ZEXTLOAD:
2369 case TargetOpcode::G_STORE:
2371 case TargetOpcode::G_FMAD:
2373 case TargetOpcode::G_FDIV:
2375 case TargetOpcode::G_FFREXP:
2377 case TargetOpcode::G_FSQRT:
2379 case TargetOpcode::G_UDIV:
2380 case TargetOpcode::G_UREM:
2381 case TargetOpcode::G_UDIVREM:
2383 case TargetOpcode::G_SDIV:
2384 case TargetOpcode::G_SREM:
2385 case TargetOpcode::G_SDIVREM:
2387 case TargetOpcode::G_ATOMIC_CMPXCHG:
2389 case TargetOpcode::G_FLOG2:
2391 case TargetOpcode::G_FLOG:
2392 case TargetOpcode::G_FLOG10:
2394 case TargetOpcode::G_FEXP2:
2396 case TargetOpcode::G_FEXP:
2397 case TargetOpcode::G_FEXP10:
2399 case TargetOpcode::G_FPOW:
2401 case TargetOpcode::G_FFLOOR:
2403 case TargetOpcode::G_BUILD_VECTOR:
2404 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2406 case TargetOpcode::G_MUL:
2408 case TargetOpcode::G_CTLZ:
2409 case TargetOpcode::G_CTTZ:
2411 case TargetOpcode::G_CTLS:
2413 case TargetOpcode::G_CTLZ_ZERO_POISON:
2415 case TargetOpcode::G_STACKSAVE:
2417 case TargetOpcode::G_GET_FPENV:
2419 case TargetOpcode::G_SET_FPENV:
2421 case TargetOpcode::G_TRAP:
2423 case TargetOpcode::G_DEBUGTRAP:
2435 unsigned BaseAS = AS;
2440 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2444 auto Tag =
B.buildConstant(
S32, SANum);
2445 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2451Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2461 if (ST.hasApertureRegs()) {
2465 const unsigned ApertureRegNo =
2466 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2467 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2468 !ST.hasGloballyAddressableScratch()) &&
2469 "Cannot use src_private_base with globally addressable scratch!");
2472 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2473 return B.buildUnmerge(I32, Dst).getReg(1);
2488 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2504 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2507 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2521 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2529 B.buildObjectPtrOffset(
2532 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2540 switch (Def->getOpcode()) {
2541 case AMDGPU::G_FRAME_INDEX:
2542 case AMDGPU::G_GLOBAL_VALUE:
2543 case AMDGPU::G_BLOCK_ADDR:
2545 case AMDGPU::G_CONSTANT: {
2546 const ConstantInt *CI = Def->getOperand(1).getCImm();
2561 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2570 unsigned SrcAS = SrcTy.getAddressSpace();
2584 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2591 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2593 ST.hasGloballyAddressableScratch()) {
2596 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2598 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2599 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2601 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2602 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2603 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2606 return B.buildExtract(Dst, Src, 0).getReg(0);
2610 castFlatToLocalOrPrivate(Dst);
2611 MI.eraseFromParent();
2617 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2618 auto FlatNull =
B.buildConstant(SrcTy, 0);
2621 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2625 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2627 MI.eraseFromParent();
2634 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2637 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2640 ST.hasGloballyAddressableScratch()) {
2644 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2645 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2649 if (ST.isWave64()) {
2650 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2656 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2657 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2659 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2663 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2664 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2666 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2667 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2676 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2680 castLocalOrPrivateToFlat(Dst);
2681 MI.eraseFromParent();
2685 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2692 SegmentNull.getReg(0));
2694 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2696 MI.eraseFromParent();
2701 SrcTy.getSizeInBits() == 64) {
2703 B.buildExtract(Dst, Src, 0);
2704 MI.eraseFromParent();
2711 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2712 auto PtrLo =
B.buildPtrToInt(I32, Src);
2713 if (AddrHiVal == 0) {
2714 auto Zext =
B.buildZExt(I64, PtrLo);
2715 B.buildIntToPtr(Dst, Zext);
2717 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2718 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2721 MI.eraseFromParent();
2728 MI.eraseFromParent();
2737 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2742 auto C1 =
B.buildFConstant(Ty, C1Val);
2743 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2746 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2747 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2749 auto C2 =
B.buildFConstant(Ty, C2Val);
2750 auto Fabs =
B.buildFAbs(Ty, Src);
2753 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2754 MI.eraseFromParent();
2771 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2773 const auto Zero =
B.buildFConstant(
F64, 0.0);
2774 const auto One =
B.buildFConstant(
F64, 1.0);
2777 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2778 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2781 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2782 MI.eraseFromParent();
2790 Register Src0Reg =
MI.getOperand(1).getReg();
2791 Register Src1Reg =
MI.getOperand(2).getReg();
2792 auto Flags =
MI.getFlags();
2795 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2796 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2797 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2798 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2799 MI.eraseFromParent();
2805 const unsigned FractBits = 52;
2806 const unsigned ExpBits = 11;
2809 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2810 auto Const1 =
B.buildConstant(I32, ExpBits);
2812 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2814 .addUse(Const0.getReg(0))
2815 .addUse(Const1.getReg(0));
2817 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2830 auto SrcInt =
B.buildBitcast(I64, Src);
2833 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2840 const unsigned FractBits = 52;
2843 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2844 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2846 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2848 const auto Zero32 =
B.buildConstant(I32, 0);
2851 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2853 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2854 auto Not =
B.buildNot(I64, Shr);
2855 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2856 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2861 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2862 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2863 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2864 MI.eraseFromParent();
2880 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2881 auto ThirtyTwo =
B.buildConstant(I32, 32);
2884 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2885 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2887 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2888 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2891 B.buildFAdd(Dst, LdExp, CvtLo);
2892 MI.eraseFromParent();
2898 auto One =
B.buildConstant(I32, 1);
2902 auto ThirtyOne =
B.buildConstant(I32, 31);
2903 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2904 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2905 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2906 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2907 .addUse(Unmerge.getReg(1));
2908 auto LS2 =
B.buildSub(I32, LS, One);
2909 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2911 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2912 auto Norm =
B.buildShl(I64, Src, ShAmt);
2913 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2914 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2915 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2916 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2917 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2918 B.buildFLdexp(Dst, FVal, Scale);
2919 MI.eraseFromParent();
2939 unsigned Flags =
MI.getFlags();
2950 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2958 auto SrcInt =
B.buildBitcast(I32, Src);
2959 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2960 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2964 K0 =
B.buildFConstant(
2966 K1 =
B.buildFConstant(
2969 K0 =
B.buildFConstant(
2971 K1 =
B.buildFConstant(
2975 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2976 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2977 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2979 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2980 :
B.buildFPTOUI(I32, FloorMul);
2981 auto Lo =
B.buildFPTOUI(I32, Fma);
2985 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2987 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2990 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2991 MI.eraseFromParent();
3014 uint64_t
Offset =
MI.getOperand(2).getImm();
3023 unsigned StartIdx =
Offset / 32;
3027 if (DstCount == 1) {
3029 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3037 for (
unsigned I = 0;
I < DstCount; ++
I)
3038 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3039 B.buildMergeLikeInstr(DstReg, MergeVec);
3042 MI.eraseFromParent();
3052 Register InsertSrc =
MI.getOperand(2).getReg();
3053 uint64_t
Offset =
MI.getOperand(3).getImm();
3061 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3065 unsigned DstCount = DstSize / 32;
3066 unsigned InsertCount = InsertSize / 32;
3067 unsigned StartIdx =
Offset / 32;
3069 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3072 for (
unsigned I = 0;
I < StartIdx; ++
I)
3075 if (InsertCount == 1) {
3079 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3082 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3083 for (
unsigned I = 0;
I < InsertCount; ++
I)
3087 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3090 B.buildMergeLikeInstr(DstReg, MergeVec);
3092 MI.eraseFromParent();
3119 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3120 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3121 B.buildIntToPtr(Dst, IntElt);
3123 MI.eraseFromParent();
3130 std::optional<ValueAndVReg> MaybeIdxVal =
3134 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3137 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3138 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3143 MI.eraseFromParent();
3172 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3173 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3174 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3176 B.buildIntToPtr(Dst, IntVecDest);
3177 MI.eraseFromParent();
3184 std::optional<ValueAndVReg> MaybeIdxVal =
3189 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3192 if (IdxVal < NumElts) {
3194 for (
unsigned i = 0; i < NumElts; ++i)
3196 B.buildUnmerge(SrcRegs, Vec);
3198 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3199 B.buildMergeLikeInstr(Dst, SrcRegs);
3204 MI.eraseFromParent();
3215 unsigned Flags =
MI.getFlags();
3219 if (ST.hasTrigReducedRange()) {
3220 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3221 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3222 .addUse(MulVal.getReg(0))
3226 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3229 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3233 MI.eraseFromParent();
3241 unsigned GAFlags)
const {
3274 if (ST.has64BitLiterals()) {
3278 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3282 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3292 B.buildExtract(DstReg, PCReg, 0);
3294 B.buildCopy(DstReg, PCReg);
3304 if (RequiresHighHalf && ST.has64BitLiterals()) {
3307 B.buildInstr(AMDGPU::S_MOV_B64)
3310 B.buildCopy(DstReg, Addr);
3318 B.buildInstr(AMDGPU::S_MOV_B32)
3323 if (RequiresHighHalf) {
3325 "Must provide a 64-bit pointer type!");
3330 B.buildInstr(AMDGPU::S_MOV_B32)
3337 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3338 B.buildCast(DstReg, AddrDst);
3340 B.buildCast(DstReg, AddrLo);
3349 unsigned AS = Ty.getAddressSpace();
3360 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3362 B.buildUndef(DstReg);
3363 MI.eraseFromParent();
3367 B.buildConstant(DstReg,
3369 MI.eraseFromParent();
3375 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3378 Fn,
"local memory global used by non-kernel function",
3387 B.buildUndef(DstReg);
3388 MI.eraseFromParent();
3412 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3413 B.buildIntToPtr(DstReg, Sz);
3414 MI.eraseFromParent();
3420 MI.eraseFromParent();
3424 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3426 MI.eraseFromParent();
3434 MI.eraseFromParent();
3440 MI.eraseFromParent();
3456 if (Ty.getSizeInBits() == 32) {
3458 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3459 B.buildExtract(DstReg,
Load, 0);
3461 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3463 MI.eraseFromParent();
3486 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3488 MI.getOperand(1).setReg(Cast.getReg(0));
3493 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3511 const uint64_t AlignInBits = 8 * MemAlign.
value();
3519 if (WideMemSize == ValSize) {
3525 MI.setMemRefs(MF, {WideMMO});
3531 if (ValSize > WideMemSize)
3538 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3539 B.buildTrunc(ValReg, WideLoad).getReg(0);
3546 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3547 B.buildExtract(ValReg, WideLoad, 0);
3551 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3552 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3556 MI.eraseFromParent();
3569 Register DataReg =
MI.getOperand(0).getReg();
3614 "this should not have been custom lowered");
3619 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3621 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3625 .setMemRefs(
MI.memoperands());
3627 MI.eraseFromParent();
3635 switch (
DefMI->getOpcode()) {
3636 case TargetOpcode::G_INTRINSIC: {
3638 case Intrinsic::amdgcn_frexp_mant:
3639 case Intrinsic::amdgcn_log:
3640 case Intrinsic::amdgcn_log_clamp:
3641 case Intrinsic::amdgcn_exp2:
3642 case Intrinsic::amdgcn_sqrt:
3650 case TargetOpcode::G_FSQRT:
3652 case TargetOpcode::G_FFREXP: {
3653 if (
DefMI->getOperand(0).getReg() == Src)
3657 case TargetOpcode::G_FPEXT: {
3678std::pair<Register, Register>
3680 unsigned Flags)
const {
3684 auto SmallestNormal =
B.buildFConstant(
3686 auto IsLtSmallestNormal =
3689 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3690 auto One =
B.buildFConstant(
F32, 1.0);
3692 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3693 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3695 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3708 LLT Ty =
B.getMRI()->getType(Dst);
3709 unsigned Flags =
MI.getFlags();
3713 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3714 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3715 .addUse(Ext.getReg(0))
3717 B.buildFPTrunc(Dst,
Log2, Flags);
3718 MI.eraseFromParent();
3726 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3729 MI.eraseFromParent();
3733 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3734 .addUse(ScaledInput)
3737 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3738 auto Zero =
B.buildFConstant(Ty, 0.0);
3740 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3741 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3743 MI.eraseFromParent();
3749 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3750 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3755 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3756 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3761 unsigned Flags =
MI.getFlags();
3771 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3773 B.buildFPTrunc(Dst, LogVal, Flags);
3778 MI.eraseFromParent();
3787 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3790 if (ST.hasFastFMAF32()) {
3792 const float c_log10 = 0x1.344134p-2f;
3793 const float cc_log10 = 0x1.09f79ep-26f;
3796 const float c_log = 0x1.62e42ep-1f;
3797 const float cc_log = 0x1.efa39ep-25f;
3799 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3800 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3804 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3805 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3806 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3807 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3808 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3811 const float ch_log10 = 0x1.344000p-2f;
3812 const float ct_log10 = 0x1.3509f6p-18f;
3815 const float ch_log = 0x1.62e000p-1f;
3816 const float ct_log = 0x1.0bfbe8p-15f;
3818 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3819 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3822 auto YInt =
B.buildBitcast(I32,
Y);
3823 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3824 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3825 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3829 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3832 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3834 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3837 const bool IsFiniteOnly =
3840 if (!IsFiniteOnly) {
3843 auto Fabs =
B.buildFAbs(Ty,
Y);
3846 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3850 auto Zero =
B.buildFConstant(Ty, 0.0);
3852 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3853 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3854 B.buildFSub(Dst, R, Shift, Flags);
3856 B.buildCopy(Dst, R);
3859 MI.eraseFromParent();
3865 unsigned Flags)
const {
3866 const double Log2BaseInverted =
3869 LLT Ty =
B.getMRI()->getType(Dst);
3874 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3875 .addUse(ScaledInput)
3877 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3878 auto Zero =
B.buildFConstant(Ty, 0.0);
3880 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3881 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3883 if (ST.hasFastFMAF32())
3884 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3886 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3887 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3894 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3895 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3898 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3899 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3910 unsigned Flags =
MI.getFlags();
3911 LLT Ty =
B.getMRI()->getType(Dst);
3918 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3919 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3920 .addUse(Ext.getReg(0))
3922 B.buildFPTrunc(Dst,
Log2, Flags);
3923 MI.eraseFromParent();
3933 MI.eraseFromParent();
3941 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3943 RangeCheckConst, Flags);
3945 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3946 auto Zero =
B.buildFConstant(Ty, 0.0);
3947 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3948 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3950 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3951 .addUse(AddInput.getReg(0))
3954 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3955 auto One =
B.buildFConstant(Ty, 1.0);
3956 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3957 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3958 MI.eraseFromParent();
3963 const SrcOp &Src,
unsigned Flags) {
3964 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3967 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3968 .addUse(Src.getReg())
3971 return B.buildFExp2(Dst, Src, Flags);
3977 bool IsExp10)
const {
3978 LLT Ty =
B.getMRI()->getType(
X);
3982 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3983 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3990 LLT Ty =
B.getMRI()->getType(Dst);
3996 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3999 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4000 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4001 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4004 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4006 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4007 .addUse(ExpInput.getReg(0))
4010 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4011 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4012 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4018 unsigned Flags)
const {
4019 LLT Ty =
B.getMRI()->getType(Dst);
4023 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4024 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4026 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4027 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4028 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4029 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4030 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4040 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4044 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4045 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4046 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4048 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4049 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4051 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4052 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4053 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4054 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4056 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4057 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4058 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4060 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4078 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4080 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4082 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4084 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4085 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4086 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4087 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4089 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4090 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4091 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4092 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4094 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4095 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4096 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4097 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4098 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4100 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4101 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4102 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4103 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4106 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4107 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4108 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4110 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4111 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4112 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4113 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4114 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4118 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4119 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4121 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4123 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4125 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4127 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4129 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4130 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4131 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4132 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4134 auto One =
B.buildFConstant(
F64, 1.0);
4135 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4136 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4139 auto DnInt =
B.buildFPTOSI(I32, Dn);
4140 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4147 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4154 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4156 MI.eraseFromParent();
4164 const unsigned Flags =
MI.getFlags();
4172 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4180 MI.eraseFromParent();
4191 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4194 B.buildFPTrunc(Dst, Lowered, Flags);
4195 MI.eraseFromParent();
4206 MI.eraseFromParent();
4234 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4237 if (ST.hasFastFMAF32()) {
4239 const float cc_exp = 0x1.4ae0bep-26f;
4240 const float c_exp10 = 0x1.a934f0p+1f;
4241 const float cc_exp10 = 0x1.2f346ep-24f;
4243 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4244 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4245 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4246 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4248 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4249 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4251 const float ch_exp = 0x1.714000p+0f;
4252 const float cl_exp = 0x1.47652ap-12f;
4254 const float ch_exp10 = 0x1.a92000p+1f;
4255 const float cl_exp10 = 0x1.4f0978p-11f;
4258 auto XInt =
B.buildBitcast(I32,
X);
4259 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4260 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4261 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4263 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4264 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4266 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4267 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4270 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4271 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4274 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4277 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4278 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4280 auto IntE =
B.buildFPTOSI(I32, E);
4282 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4283 .addUse(
A.getReg(0))
4285 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4287 auto UnderflowCheckConst =
4288 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4289 auto Zero =
B.buildFConstant(Ty, 0.0);
4293 R =
B.buildSelect(Ty, Underflow, Zero, R);
4296 auto OverflowCheckConst =
4297 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4302 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4305 B.buildCopy(Dst, R);
4306 MI.eraseFromParent();
4317 unsigned Flags =
MI.getFlags();
4326 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4328 .setMIFlags(CoreFlags);
4329 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4331 .addUse(Log.getReg(0))
4332 .setMIFlags(CoreFlags);
4334 MI.eraseFromParent();
4338 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4339 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4340 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4342 .addUse(Log.getReg(0))
4343 .setMIFlags(CoreFlags);
4348 .signBitIsZeroOrNaN()) {
4349 B.buildFExp2(Dst,
Mul, CoreFlags);
4350 MI.eraseFromParent();
4356 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4358 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4359 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4360 auto YIsOdd =
B.buildAnd(
4364 auto Neg =
B.buildFCopysign(
F32, R,
X);
4366 B.buildSelect(Dst, YIsOdd, Neg, R);
4367 MI.eraseFromParent();
4370 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4377 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4379 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4381 B.buildSelect(Dst, NegNonInt, NaN, R);
4383 MI.eraseFromParent();
4391 ModSrc = SrcFNeg->getOperand(1).getReg();
4393 ModSrc = SrcFAbs->getOperand(1).getReg();
4395 ModSrc = SrcFAbs->getOperand(1).getReg();
4405 Register OrigSrc =
MI.getOperand(1).getReg();
4406 unsigned Flags =
MI.getFlags();
4408 "this should not have been custom lowered");
4418 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4438 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4440 B.buildFMinNum(Min, Fract, Const, Flags);
4445 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4448 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4449 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4451 MI.eraseFromParent();
4469 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4471 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4472 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4475 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4476 B.buildBitcast(Dst,
Merge);
4478 MI.eraseFromParent();
4495 bool UsePartialMad64_32,
4496 bool SeparateOddAlignedProducts)
const {
4511 auto getZero32 = [&]() ->
Register {
4513 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4516 auto getZero64 = [&]() ->
Register {
4518 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4523 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4534 if (CarryIn.empty())
4537 bool HaveCarryOut =
true;
4539 if (CarryIn.size() == 1) {
4541 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4545 CarryAccum = getZero32();
4547 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4548 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4550 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4555 LocalAccum = getZero32();
4556 HaveCarryOut =
false;
4561 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4562 LocalAccum =
Add.getReg(0);
4576 auto buildMadChain =
4579 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4580 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4587 if (LocalAccum.size() == 1 &&
4588 (!UsePartialMad64_32 || !CarryIn.empty())) {
4591 unsigned j1 = DstIndex - j0;
4592 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4596 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4598 LocalAccum[0] =
Mul.getReg(0);
4600 if (CarryIn.empty()) {
4601 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4604 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4610 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4614 if (j0 <= DstIndex) {
4615 bool HaveSmallAccum =
false;
4618 if (LocalAccum[0]) {
4619 if (LocalAccum.size() == 1) {
4620 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4621 HaveSmallAccum =
true;
4622 }
else if (LocalAccum[1]) {
4623 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4624 HaveSmallAccum =
false;
4626 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4627 HaveSmallAccum =
true;
4630 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4632 HaveSmallAccum =
true;
4636 unsigned j1 = DstIndex - j0;
4637 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4641 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4642 {Src0[j0], Src1[j1], Tmp});
4643 Tmp = Mad.getReg(0);
4644 if (!HaveSmallAccum)
4645 CarryOut.push_back(Mad.getReg(1));
4646 HaveSmallAccum =
false;
4649 }
while (j0 <= DstIndex);
4651 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4652 LocalAccum[0] = Unmerge.getReg(0);
4653 if (LocalAccum.size() > 1)
4654 LocalAccum[1] = Unmerge.getReg(1);
4661 LocalAccum[0] = getZero32();
4665 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4666 "Uninitialized accumulator part");
4692 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4693 Carry OddCarryIn = std::move(OddCarry);
4694 Carry EvenCarryIn = std::move(EvenCarry);
4699 if (2 * i < Accum.
size()) {
4700 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4701 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4706 if (!SeparateOddAlignedProducts) {
4707 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4708 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4710 bool IsHighest = 2 * i >= Accum.
size();
4713 .take_front(IsHighest ? 1 : 2);
4714 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4720 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4722 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4724 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4727 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4730 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4731 Lo->getOperand(1).getReg());
4732 Accum[2 * i] =
Hi.getReg(0);
4733 SeparateOddCarry =
Hi.getReg(1);
4740 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4741 EvenCarryIn.push_back(CarryOut);
4743 if (2 * i < Accum.
size()) {
4744 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4745 OddCarry.push_back(CarryOut);
4757 assert(ST.hasMad64_32());
4758 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4770 unsigned Size = Ty.getSizeInBits();
4771 if (ST.useVMulU64Inst() &&
Size == 64)
4774 unsigned NumParts =
Size / 32;
4786 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4790 for (
unsigned i = 0; i < NumParts; ++i) {
4794 B.buildUnmerge(Src0Parts, Src0);
4795 B.buildUnmerge(Src1Parts, Src1);
4798 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4799 SeparateOddAlignedProducts);
4801 B.buildMergeLikeInstr(DstReg, AccumRegs);
4802 MI.eraseFromParent();
4817 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4818 ? AMDGPU::G_AMDGPU_FFBH_U32
4819 : AMDGPU::G_AMDGPU_FFBL_B32;
4820 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4823 MI.eraseFromParent();
4833 TypeSize NumBits = SrcTy.getSizeInBits();
4838 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4839 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4840 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4841 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4842 B.buildTrunc(Dst, Ctlz);
4843 MI.eraseFromParent();
4854 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4855 unsigned BitWidth = SrcTy.getSizeInBits();
4857 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4858 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4859 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4860 MI.eraseFromParent();
4866 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4869 return ConstVal == -1;
4876 Register CondDef =
MI.getOperand(0).getReg();
4895 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4904 UncondBrTarget = &*NextMBB;
4906 if (
Next->getOpcode() != AMDGPU::G_BR)
4925 *ArgRC,
B.getDebugLoc(), ArgTy);
4929 const unsigned Mask = Arg->
getMask();
4937 auto ShiftAmt =
B.buildConstant(I32, Shift);
4938 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4941 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4943 B.buildCopy(DstReg, LiveIn);
4953 if (!ST.hasClusters()) {
4956 MI.eraseFromParent();
4976 auto One =
B.buildConstant(I32, 1);
4977 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4978 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4979 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4986 B.buildCopy(DstReg, GlobalIdXYZ);
4987 MI.eraseFromParent();
4991 B.buildCopy(DstReg, ClusterIdXYZ);
4992 MI.eraseFromParent();
4997 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4999 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5000 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5002 .addImm(ClusterIdField);
5003 auto Zero =
B.buildConstant(I32, 0);
5006 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5007 MI.eraseFromParent();
5049 auto LoadConstant = [&](
unsigned N) {
5050 B.buildConstant(DstReg,
N);
5054 if (ST.hasArchitectedSGPRs() &&
5061 Arg = &WorkGroupIDX;
5062 ArgRC = &AMDGPU::SReg_32RegClass;
5066 Arg = &WorkGroupIDY;
5067 ArgRC = &AMDGPU::SReg_32RegClass;
5071 Arg = &WorkGroupIDZ;
5072 ArgRC = &AMDGPU::SReg_32RegClass;
5076 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5077 return LoadConstant(0);
5078 Arg = &ClusterWorkGroupIDX;
5079 ArgRC = &AMDGPU::SReg_32RegClass;
5083 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5084 return LoadConstant(0);
5085 Arg = &ClusterWorkGroupIDY;
5086 ArgRC = &AMDGPU::SReg_32RegClass;
5090 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5091 return LoadConstant(0);
5092 Arg = &ClusterWorkGroupIDZ;
5093 ArgRC = &AMDGPU::SReg_32RegClass;
5098 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5099 Arg = &ClusterWorkGroupMaxIDX;
5100 ArgRC = &AMDGPU::SReg_32RegClass;
5105 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5106 Arg = &ClusterWorkGroupMaxIDY;
5107 ArgRC = &AMDGPU::SReg_32RegClass;
5112 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5113 Arg = &ClusterWorkGroupMaxIDZ;
5114 ArgRC = &AMDGPU::SReg_32RegClass;
5118 Arg = &ClusterWorkGroupMaxFlatID;
5119 ArgRC = &AMDGPU::SReg_32RegClass;
5134 return LoadConstant(0);
5139 B.buildUndef(DstReg);
5143 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5155 MI.eraseFromParent();
5161 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5162 MI.eraseFromParent();
5169 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5183 B.buildUndef(DstReg);
5184 MI.eraseFromParent();
5188 if (Arg->isMasked()) {
5202 MI.eraseFromParent();
5217 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5226 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5234 Align Alignment)
const {
5238 "unexpected kernarg parameter type");
5245 MI.eraseFromParent();
5277 auto FloatY =
B.buildUITOFP(
F32,
Y);
5278 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5280 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5281 auto Z =
B.buildFPTOUI(I32, ScaledY);
5284 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5285 auto NegYZ =
B.buildMul(I32, NegY, Z);
5286 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5289 auto Q =
B.buildUMulH(I32,
X, Z);
5290 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5293 auto One =
B.buildConstant(I32, 1);
5296 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5297 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5302 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5305 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5324 auto Unmerge =
B.buildUnmerge(I32, Val);
5326 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5327 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5329 auto Mad =
B.buildFMAD(
5333 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5334 auto Mul1 =
B.buildFMul(
5338 auto Mul2 =
B.buildFMul(
5340 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5343 auto Mad2 =
B.buildFMAD(
5347 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5348 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5350 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5365 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5367 auto Zero64 =
B.buildConstant(I64, 0);
5368 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5370 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5371 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5373 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5374 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5375 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5377 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5378 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5379 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5381 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5382 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5383 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5384 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5385 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5387 auto Zero32 =
B.buildConstant(I32, 0);
5388 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5389 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5390 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5392 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5393 Register NumerLo = UnmergeNumer.getReg(0);
5394 Register NumerHi = UnmergeNumer.getReg(1);
5396 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5397 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5398 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5399 Register Mul3_Lo = UnmergeMul3.getReg(0);
5400 Register Mul3_Hi = UnmergeMul3.getReg(1);
5401 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5402 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5403 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5404 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5406 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5407 Register DenomLo = UnmergeDenom.getReg(0);
5408 Register DenomHi = UnmergeDenom.getReg(1);
5411 auto C1 =
B.buildSExt(I32, CmpHi);
5414 auto C2 =
B.buildSExt(I32, CmpLo);
5417 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5424 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5425 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5426 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5427 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5429 auto One64 =
B.buildConstant(I64, 1);
5430 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5436 auto C6 =
B.buildSelect(
5440 auto Add4 =
B.buildAdd(I64, Add3, One64);
5441 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5443 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5444 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5445 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5451 auto Sel1 =
B.buildSelect(
5458 auto Sel2 =
B.buildSelect(
5469 switch (
MI.getOpcode()) {
5472 case AMDGPU::G_UDIV: {
5473 DstDivReg =
MI.getOperand(0).getReg();
5476 case AMDGPU::G_UREM: {
5477 DstRemReg =
MI.getOperand(0).getReg();
5480 case AMDGPU::G_UDIVREM: {
5481 DstDivReg =
MI.getOperand(0).getReg();
5482 DstRemReg =
MI.getOperand(1).getReg();
5489 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5490 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5491 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5501 MI.eraseFromParent();
5512 if (Ty != I32 && Ty != I64)
5515 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5516 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5517 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5519 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5520 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5521 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5523 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5524 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5526 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5527 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5529 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5530 switch (
MI.getOpcode()) {
5533 case AMDGPU::G_SDIV: {
5534 DstDivReg =
MI.getOperand(0).getReg();
5538 case AMDGPU::G_SREM: {
5539 DstRemReg =
MI.getOperand(0).getReg();
5543 case AMDGPU::G_SDIVREM: {
5544 DstDivReg =
MI.getOperand(0).getReg();
5545 DstRemReg =
MI.getOperand(1).getReg();
5558 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5559 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5560 B.buildSub(DstDivReg, SignXor, Sign);
5564 auto Sign = LHSign.getReg(0);
5565 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5566 B.buildSub(DstRemReg, SignXor, Sign);
5569 MI.eraseFromParent();
5579 uint16_t Flags =
MI.getFlags();
5585 if (!AllowInaccurateRcp && ResTy !=
F16)
5596 if (CLHS->isOne()) {
5597 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5601 MI.eraseFromParent();
5606 if (CLHS->isMinusOne()) {
5607 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5608 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5609 .addUse(FNeg.getReg(0))
5612 MI.eraseFromParent();
5619 if (!AllowInaccurateRcp &&
5624 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5627 B.buildFMul(Res, LHS, RCP, Flags);
5629 MI.eraseFromParent();
5639 uint16_t Flags =
MI.getFlags();
5644 if (!AllowInaccurateRcp)
5652 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5654 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5655 auto One =
B.buildFConstant(ResTy, 1.0);
5657 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5661 R =
B.buildFNeg(ResTy, R);
5663 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5664 R =
B.buildFMA(ResTy, Tmp0, R, R);
5666 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5667 R =
B.buildFMA(ResTy, Tmp1, R, R);
5670 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5671 B.buildCopy(Res, R);
5672 MI.eraseFromParent();
5676 auto Ret =
B.buildFMul(ResTy,
X, R);
5677 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5679 B.buildFMA(Res, Tmp2, R, Ret);
5680 MI.eraseFromParent();
5694 uint16_t Flags =
MI.getFlags();
5711 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5712 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5713 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5714 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5715 .addUse(RHSExt.getReg(0))
5717 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5719 if (ST.hasMadMacF32Insts()) {
5720 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5721 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5722 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5724 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5725 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5726 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5728 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5729 auto TmpInt =
B.buildBitcast(I32, Tmp);
5730 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5731 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5732 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5733 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5734 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5735 .addUse(RDst.getReg(0))
5740 MI.eraseFromParent();
5753 unsigned SPDenormMode =
5756 if (ST.hasDenormModeInst()) {
5758 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5760 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5761 B.buildInstr(AMDGPU::S_DENORM_MODE)
5762 .addImm(NewDenormModeValue);
5765 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5766 .addImm(SPDenormMode)
5783 uint16_t Flags =
MI.getFlags();
5787 auto One =
B.buildFConstant(
F32, 1.0f);
5789 auto DenominatorScaled =
5790 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5795 auto NumeratorScaled =
5796 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5802 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5803 .addUse(DenominatorScaled.getReg(0))
5805 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5808 const bool HasDynamicDenormals =
5813 if (!PreservesDenormals) {
5814 if (HasDynamicDenormals) {
5816 B.buildInstr(AMDGPU::S_GETREG_B32)
5817 .addDef(SavedSPDenormMode)
5823 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5824 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5825 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5826 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5827 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5828 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5830 if (!PreservesDenormals) {
5831 if (HasDynamicDenormals) {
5832 assert(SavedSPDenormMode);
5833 B.buildInstr(AMDGPU::S_SETREG_B32)
5834 .addReg(SavedSPDenormMode)
5840 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5841 .addUse(Fma4.getReg(0))
5842 .addUse(Fma1.getReg(0))
5843 .addUse(Fma3.getReg(0))
5844 .addUse(NumeratorScaled.getReg(1))
5847 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5848 .addUse(Fmas.getReg(0))
5853 MI.eraseFromParent();
5867 uint16_t Flags =
MI.getFlags();
5871 auto One =
B.buildFConstant(
F64, 1.0);
5873 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5879 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5881 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5882 .addUse(DivScale0.getReg(0))
5885 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5886 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5887 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5889 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5895 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5896 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5897 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5900 if (!ST.hasUsableDivScaleConditionOutput()) {
5907 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5908 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5909 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5910 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5913 Scale1Unmerge.getReg(1));
5915 Scale0Unmerge.getReg(1));
5916 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5918 Scale = DivScale1.getReg(1);
5921 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5922 .addUse(Fma4.getReg(0))
5923 .addUse(Fma3.getReg(0))
5924 .addUse(
Mul.getReg(0))
5928 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5929 .addUse(Fmas.getReg(0))
5934 MI.eraseFromParent();
5944 uint16_t Flags =
MI.getFlags();
5949 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5952 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5956 if (ST.hasFractBug()) {
5957 auto Fabs =
B.buildFAbs(Ty, Val);
5961 auto Zero =
B.buildConstant(InstrExpTy, 0);
5962 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5963 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5966 B.buildCopy(Res0, Mant);
5967 B.buildSExtOrTrunc(Res1, Exp);
5969 MI.eraseFromParent();
5979 uint16_t Flags =
MI.getFlags();
5983 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5986 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5987 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5988 auto C2 =
B.buildFConstant(
F32, 1.0f);
5991 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5993 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5995 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5996 .addUse(Mul0.getReg(0))
5999 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6001 B.buildFMul(Res, Sel, Mul1, Flags);
6003 MI.eraseFromParent();
6012 unsigned Flags =
MI.getFlags();
6013 assert(!ST.has16BitInsts());
6014 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6015 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6016 .addUse(Ext.getReg(0))
6018 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6019 MI.eraseFromParent();
6029 const unsigned Flags =
MI.getFlags();
6037 MI.eraseFromParent();
6041 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6043 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6044 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6045 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6050 .addUse(SqrtX.getReg(0))
6053 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6054 auto NegOne =
B.buildConstant(I32, -1);
6055 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6057 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6058 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6060 auto PosOne =
B.buildConstant(I32, 1);
6061 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6063 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6064 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6066 auto Zero =
B.buildFConstant(
F32, 0.0f);
6070 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6074 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6077 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6078 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6080 auto Half =
B.buildFConstant(
F32, 0.5f);
6081 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6082 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6083 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6084 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6085 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6086 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6087 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6088 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6091 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6093 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6095 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6098 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6100 MI.eraseFromParent();
6134 unsigned Flags =
MI.getFlags();
6139 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6141 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6145 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6146 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6147 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6150 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6152 auto Half =
B.buildFConstant(
F64, 0.5);
6153 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6154 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6156 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6157 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6159 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6160 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6162 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6163 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6165 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6167 Register SqrtRet = SqrtS2.getReg(0);
6169 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6170 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6171 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6174 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6175 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6176 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6181 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6184 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6190 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6192 MI.eraseFromParent();
6223 auto Flags =
MI.getFlags();
6235 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6245 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6246 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6251 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6253 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6254 MI.eraseFromParent();
6266 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6267 IID == Intrinsic::amdgcn_permlanex16;
6268 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6269 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6270 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6271 IID == Intrinsic::amdgcn_permlane_up ||
6272 IID == Intrinsic::amdgcn_permlane_down ||
6273 IID == Intrinsic::amdgcn_permlane_xor;
6277 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6279 case Intrinsic::amdgcn_readfirstlane:
6280 case Intrinsic::amdgcn_permlane64:
6281 return LaneOp.getReg(0);
6282 case Intrinsic::amdgcn_readlane:
6283 case Intrinsic::amdgcn_set_inactive:
6284 case Intrinsic::amdgcn_set_inactive_chain_arg:
6285 return LaneOp.addUse(Src1).getReg(0);
6286 case Intrinsic::amdgcn_writelane:
6287 case Intrinsic::amdgcn_permlane_bcast:
6288 case Intrinsic::amdgcn_permlane_up:
6289 case Intrinsic::amdgcn_permlane_down:
6290 case Intrinsic::amdgcn_permlane_xor:
6291 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6292 case Intrinsic::amdgcn_permlane16:
6293 case Intrinsic::amdgcn_permlanex16: {
6295 int64_t Src4 =
MI.getOperand(6).getImm();
6296 int64_t Src5 =
MI.getOperand(7).getImm();
6297 return LaneOp.addUse(Src1)
6304 case Intrinsic::amdgcn_mov_dpp8:
6305 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6306 case Intrinsic::amdgcn_update_dpp:
6307 return LaneOp.addUse(Src1)
6308 .addImm(
MI.getOperand(4).getImm())
6309 .addImm(
MI.getOperand(5).getImm())
6310 .addImm(
MI.getOperand(6).getImm())
6311 .addImm(
MI.getOperand(7).getImm())
6321 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6322 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6323 IsPermlaneShuffle) {
6324 Src1 =
MI.getOperand(3).getReg();
6325 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6326 IsPermlaneShuffle) {
6327 Src2 =
MI.getOperand(4).getReg();
6332 unsigned Size = Ty.getSizeInBits();
6334 unsigned SplitSize = 32;
6335 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6336 ST.hasDPALU_DPP() &&
6340 if (
Size == SplitSize) {
6347 bool IsFloat = Ty.getScalarType().isFloat();
6351 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6353 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6355 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6359 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6361 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6362 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6364 if (IID == Intrinsic::amdgcn_writelane)
6365 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6367 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6369 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6371 B.buildTrunc(DstReg, LaneOpDst);
6372 MI.eraseFromParent();
6376 if (
Size % SplitSize != 0)
6380 bool NeedsBitcast =
false;
6381 if (IntTy.isVector()) {
6384 if (EltSize == SplitSize) {
6385 PartialResTy = EltTy;
6386 }
else if (EltSize == 16 || EltSize == 32) {
6387 unsigned NElem = SplitSize / EltSize;
6390 NeedsBitcast =
true;
6395 unsigned NumParts =
Size / SplitSize;
6399 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6400 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6402 if (IID == Intrinsic::amdgcn_writelane)
6403 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6405 for (
unsigned i = 0; i < NumParts; ++i) {
6406 Src0 = Src0Parts.
getReg(i);
6408 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6409 Src1 = Src1Parts.
getReg(i);
6411 if (IID == Intrinsic::amdgcn_writelane)
6412 Src2 = Src2Parts.
getReg(i);
6414 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6417 if (NeedsBitcast || IsFloat)
6420 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6422 B.buildMergeLikeInstr(DstReg, PartialRes);
6424 MI.eraseFromParent();
6432 ST.getTargetLowering()->getImplicitParameterOffset(
6442 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6443 B.buildConstant(IdxTy,
Offset).getReg(0));
6454 Register Pointer =
MI.getOperand(2).getReg();
6456 Register NumRecords =
MI.getOperand(4).getReg();
6462 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6464 auto ExtStride =
B.buildAnyExt(I32, Stride);
6466 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6467 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6469 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6471 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6475 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6476 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6477 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6478 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6482 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6483 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6484 auto ExtShiftedStride =
6485 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6486 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6487 auto ExtShiftedFlags =
6488 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6489 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6491 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6492 B.buildMergeValues(Result, {LowHalf, HighHalf});
6494 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6495 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6496 auto LowHalf = Unmerge.getReg(0);
6497 auto HighHalf = Unmerge.getReg(1);
6499 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6500 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6501 auto ShiftConst =
B.buildConstant(I32, 16);
6502 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6503 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6504 Register NewHighHalfReg = NewHighHalf.getReg(0);
6505 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6508 MI.eraseFromParent();
6525 MI.eraseFromParent();
6533 std::optional<uint32_t> KnownSize =
6535 if (KnownSize.has_value())
6536 B.buildConstant(DstReg, *KnownSize);
6554 MI.eraseFromParent();
6561 unsigned AddrSpace)
const {
6563 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6567 ST.hasGloballyAddressableScratch()) {
6569 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6570 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6572 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6574 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6576 B.buildConstant(I32, 1u << 26));
6581 MI.eraseFromParent();
6591std::pair<Register, unsigned>
6603 bool CheckNUW = ST.hasGFX1250Insts();
6605 MRI, OrigOffset,
nullptr, CheckNUW);
6609 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6619 unsigned Overflow = ImmOffset & ~MaxImm;
6620 ImmOffset -= Overflow;
6621 if ((int32_t)Overflow < 0) {
6622 Overflow += ImmOffset;
6626 if (Overflow != 0) {
6628 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6630 auto OverflowVal =
B.buildConstant(I32, Overflow);
6631 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6636 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6638 return std::pair(BaseReg, ImmOffset);
6645 bool ImageStore)
const {
6653 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6655 if (ST.hasUnpackedD16VMem()) {
6656 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6659 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6660 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6668 if (ImageStore && ST.hasImageStoreD16Bug()) {
6671 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6673 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6680 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6681 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6683 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6691 auto Unmerge =
B.buildUnmerge(I32, Reg);
6692 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6694 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6704 Reg =
B.buildPadVectorWithUndefElements(
6713 bool IsFormat)
const {
6723 VData =
B.buildBitcast(Ty, VData).getReg(0);
6731 if (Ty.isVector()) {
6732 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6744 bool IsFormat)
const {
6751 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6758 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6759 const Function &Fn =
B.getMF().getFunction();
6761 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6762 MI.eraseFromParent();
6774 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6777 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6781 VIndex =
MI.getOperand(3).getReg();
6784 VIndex =
B.buildConstant(I32, 0).getReg(0);
6787 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6788 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6792 Format =
MI.getOperand(5 + OpOffset).getImm();
6796 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6802 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6803 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6804 }
else if (IsFormat) {
6805 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6806 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6810 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6813 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6816 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6821 auto MIB =
B.buildInstr(
Opc)
6832 MIB.addImm(AuxiliaryData)
6833 .addImm(HasVIndex ? -1 : 0)
6834 .addMemOperand(MMO);
6836 MI.eraseFromParent();
6842 unsigned ImmOffset,
unsigned Format,
6845 auto MIB =
B.buildInstr(
Opc)
6856 MIB.addImm(AuxiliaryData)
6857 .addImm(HasVIndex ? -1 : 0)
6858 .addMemOperand(MMO);
6864 Register SOffset,
unsigned ImmOffset,
6865 unsigned Format,
unsigned AuxiliaryData,
6869 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6871 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6874 B.buildUnmerge(Unmerge, LoadDstReg);
6880 bool IsTyped)
const {
6894 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6895 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6897 StatusDst =
MI.getOperand(1).getReg();
6902 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6905 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6908 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6911 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6914 VIndex =
B.buildConstant(I32, 0).getReg(0);
6917 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6918 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6922 Format =
MI.getOperand(5 + OpOffset).getImm();
6926 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6936 Dst =
MI.getOperand(0).getReg();
6937 B.setInsertPt(
B.getMBB(),
MI);
6944 Dst =
MI.getOperand(0).getReg();
6945 B.setInsertPt(
B.getMBB(),
MI);
6949 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6950 const bool Unpacked = ST.hasUnpackedD16VMem();
6952 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6953 const Function &Fn =
B.getMF().getFunction();
6955 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6958 B.buildUndef(StatusDst);
6959 MI.eraseFromParent();
6963 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6964 const Function &Fn =
B.getMF().getFunction();
6966 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6969 B.buildUndef(StatusDst);
6970 MI.eraseFromParent();
6982 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6983 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6984 }
else if (IsFormat) {
6986 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
6987 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6989 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6990 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6995 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6996 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6999 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7000 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7003 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7004 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7009 if (IsTFE && IsD16 && Ty.isVector()) {
7011 const unsigned NumElts = Ty.getNumElements();
7012 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7015 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7018 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7023 R =
B.buildTrunc(EltTy, R).getReg(0);
7024 B.buildMergeLikeInstr(Dst, ValueDWords);
7033 if (PackedTy == Ty) {
7034 B.buildBitcast(Dst, Merged);
7036 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7037 B.buildDeleteTrailingVectorElements(Dst, Packed);
7041 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7049 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7051 B.buildTrunc(DstInt, ExtDst);
7052 }
else if (NumValueDWords == 1) {
7054 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7058 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7061 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7062 IsTyped, HasVIndex,
B);
7063 B.buildMergeLikeInstr(DstInt, ValueDWords);
7066 B.buildBitcast(Dst, DstInt);
7068 (IsD16 && !Ty.isVector())) {
7069 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7071 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7072 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7073 B.buildTrunc(Dst, LoadDstReg);
7074 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7076 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7078 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7079 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7081 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7083 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7084 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7085 B.buildMergeLikeInstr(Dst, Repack);
7088 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7091 MI.eraseFromParent();
7097 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7098 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7099 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7100 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7101 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7102 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7103 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7104 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7105 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7106 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7107 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7108 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7109 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7110 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7111 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7112 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7113 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7114 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7115 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7116 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7117 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7118 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7119 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7120 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7121 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7122 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7123 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7124 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7125 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7126 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7127 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7129 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7130 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7131 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7132 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7133 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7134 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7135 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7136 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7137 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7138 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7139 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7140 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7141 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7142 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7144 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7145 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7146 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7147 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7148 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7149 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7150 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7151 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7152 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7153 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7154 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7155 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7156 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7157 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7158 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7159 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7160 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7161 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7162 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7163 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7164 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7166 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7167 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7168 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7169 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7170 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7171 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7172 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7173 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7174 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7175 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7176 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7177 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7179 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7180 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7181 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7182 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7183 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7184 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7185 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7186 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7195 const bool IsCmpSwap =
7196 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7197 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7198 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7199 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7210 CmpVal =
MI.getOperand(3).getReg();
7215 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7216 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7219 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7222 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7228 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7229 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7230 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7249 .addImm(AuxiliaryData)
7250 .addImm(HasVIndex ? -1 : 0)
7251 .addMemOperand(MMO);
7253 MI.eraseFromParent();
7263 bool IsA16,
bool IsG16) {
7277 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7282 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7286 "Bias needs to be converted to 16 bit in A16 mode");
7288 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7292 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7296 if (((
I + 1) >= EndIdx) ||
7303 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7305 B.buildBuildVector(V2EltTy,
7306 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7311 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7322 int DimIdx,
int NumVAddrs) {
7324 for (
int I = 0;
I != NumVAddrs; ++
I) {
7326 if (
SrcOp.isReg()) {
7329 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7330 if (
B.getMRI()->getType(
Reg) != I32)
7331 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7336 int NumAddrRegs = AddrRegs.
size();
7337 if (NumAddrRegs != 1) {
7338 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7341 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7344 for (
int I = 1;
I != NumVAddrs; ++
I) {
7347 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7369 const unsigned NumDefs =
MI.getNumExplicitDefs();
7370 const unsigned ArgOffset = NumDefs + 1;
7371 bool IsTFE = NumDefs == 2;
7389 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7393 const bool IsAtomicPacked16Bit =
7394 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7395 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7402 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7403 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7404 const bool DataTyIs16 =
7405 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7407 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7408 const bool IsA16 = AddrTyIs16;
7409 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7412 if (!BaseOpcode->
Atomic) {
7413 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7416 }
else if (DMask != 0) {
7418 }
else if (!IsTFE && !BaseOpcode->
Store) {
7420 B.buildUndef(
MI.getOperand(0));
7421 MI.eraseFromParent();
7429 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7430 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7431 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7432 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7433 unsigned NewOpcode = LoadOpcode;
7434 if (BaseOpcode->
Store)
7435 NewOpcode = StoreOpcode;
7437 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7440 MI.setDesc(
B.getTII().get(NewOpcode));
7444 if (IsTFE && DMask == 0) {
7447 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7450 if (BaseOpcode->
Atomic) {
7455 if (Ty.isVector() && !IsAtomicPacked16Bit)
7462 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7463 MI.getOperand(2).setReg(
Concat.getReg(0));
7464 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7468 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7471 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7477 if (IsA16 && !ST.hasA16()) {
7482 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7483 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7485 if (IsA16 || IsG16) {
7493 const bool UseNSA = ST.hasNSAEncoding() &&
7494 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7495 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7496 const bool UsePartialNSA =
7497 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7499 if (UsePartialNSA) {
7503 auto Concat =
B.buildConcatVectors(
7504 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7505 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7506 PackedRegs.
resize(NSAMaxSize);
7507 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7509 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7510 PackedRegs[0] =
Concat.getReg(0);
7514 const unsigned NumPacked = PackedRegs.
size();
7517 if (!
SrcOp.isReg()) {
7527 SrcOp.setReg(AMDGPU::NoRegister);
7544 const bool UseNSA = ST.hasNSAEncoding() &&
7545 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7546 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7547 const bool UsePartialNSA =
7548 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7550 if (UsePartialNSA) {
7552 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7554 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7569 if (!Ty.isVector() || !IsD16)
7573 if (RepackedReg != VData) {
7574 MI.getOperand(1).setReg(RepackedReg);
7582 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7585 if (NumElts < DMaskLanes)
7588 if (NumElts > 4 || DMaskLanes > 4)
7599 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7600 const LLT AdjustedTy =
7616 if (IsD16 && ST.hasUnpackedD16VMem()) {
7623 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7624 unsigned RoundedSize = 32 * RoundedElts;
7628 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7633 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7639 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7643 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7644 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7648 MI.getOperand(0).setReg(NewResultReg);
7656 Dst1Reg =
MI.getOperand(1).getReg();
7657 if (MRI->
getType(Dst1Reg) != I32)
7661 MI.removeOperand(1);
7664 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7665 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7666 B.buildBitcast(DstReg, Unmerge.getReg(0));
7667 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7676 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7678 if (ResultNumRegs == 1) {
7680 ResultRegs[0] = NewResultReg;
7683 for (
int I = 0;
I != NumDataRegs; ++
I)
7685 B.buildUnmerge(ResultRegs, NewResultReg);
7690 ResultRegs.
resize(NumDataRegs);
7695 if (IsD16 && !Ty.isVector()) {
7696 B.buildTrunc(DstReg, ResultRegs[0]);
7701 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7702 !ST.hasUnpackedD16VMem()) {
7703 B.buildBitcast(DstReg, ResultRegs[0]);
7715 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7717 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7718 }
else if (ST.hasUnpackedD16VMem()) {
7720 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7724 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7728 for (
int I = 0;
I != NumElts; ++
I)
7735 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7736 B.buildBuildVector(DstReg, ResultRegs);
7740 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7741 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7746 if (Ty == V3I16 || Ty == V3F16) {
7748 if (ResultRegs.
size() == 1) {
7749 NewResultReg = ResultRegs[0];
7750 }
else if (ResultRegs.
size() == 2) {
7752 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7767 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7769 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7771 if (ResizeDst != DstReg)
7772 B.buildBitcast(DstReg, ResizeDst);
7776 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7777 B.buildConcatVectors(DstReg, ResultRegs);
7786 Register OrigDst =
MI.getOperand(0).getReg();
7788 LLT Ty =
B.getMRI()->getType(OrigDst);
7789 unsigned Size = Ty.getSizeInBits();
7791 bool HasMMO = !
MI.memoperands_empty();
7796 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7797 if (
Size % 32 != 0 && !IsSubwordLoad) {
7800 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7801 B.buildUndef(OrigDst);
7802 MI.eraseFromParent();
7807 if (IsSubwordLoad) {
7809 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7810 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7813 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7815 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7824 B.setInsertPt(
B.getMBB(),
MI);
7829 B.setInsertPt(
B.getMBB(),
MI);
7832 MI.setDesc(
B.getTII().get(
Opc));
7833 MI.removeOperand(1);
7839 const unsigned MemSize = (
Size + 7) / 8;
7840 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7847 MI.addMemOperand(MF, MMO);
7849 if (Dst != OrigDst) {
7850 MI.getOperand(0).setReg(Dst);
7851 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7852 B.buildTrunc(OrigDst, Dst);
7874 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7875 MI.removeOperand(0);
7886 if (!ST.hasTrapHandler() ||
7890 return ST.supportsGetDoorbellID() ?
7905 MI.eraseFromParent();
7917 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7926 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7928 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7932 MI.eraseFromParent();
7941 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7948 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7968 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7971 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7972 B.buildCopy(SGPR01, Temp);
7973 B.buildInstr(AMDGPU::S_TRAP)
7976 MI.eraseFromParent();
7987 B.buildCopy(SGPR01, LiveIn);
7988 B.buildInstr(AMDGPU::S_TRAP)
7992 MI.eraseFromParent();
8001 if (ST.hasPrivEnabledTrap2NopBug()) {
8002 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
8004 MI.eraseFromParent();
8008 B.buildInstr(AMDGPU::S_TRAP)
8010 MI.eraseFromParent();
8019 if (!ST.hasTrapHandler() ||
8023 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8026 B.buildInstr(AMDGPU::S_TRAP)
8030 MI.eraseFromParent();
8044 Register NodePtr =
MI.getOperand(2).getReg();
8045 Register RayExtent =
MI.getOperand(3).getReg();
8046 Register RayOrigin =
MI.getOperand(4).getReg();
8048 Register RayInvDir =
MI.getOperand(6).getReg();
8051 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8058 const unsigned NumVDataDwords = 4;
8059 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8060 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8062 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8064 const unsigned BaseOpcodes[2][2] = {
8065 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8066 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8067 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8071 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8072 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8073 : AMDGPU::MIMGEncGfx10NSA,
8074 NumVDataDwords, NumVAddrDwords);
8078 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8079 : AMDGPU::MIMGEncGfx10Default,
8080 NumVDataDwords, NumVAddrDwords);
8085 if (UseNSA && IsGFX11Plus) {
8086 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8087 auto SrcInt =
B.buildBitcast(V3I32, Src);
8088 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8089 auto Merged =
B.buildMergeLikeInstr(
8090 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8091 Ops.push_back(Merged.getReg(0));
8094 Ops.push_back(NodePtr);
8095 Ops.push_back(RayExtent);
8096 packLanes(RayOrigin);
8099 auto UnmergeRayDir =
8100 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8101 auto UnmergeRayInvDir =
8102 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8103 auto MergedDir =
B.buildMergeLikeInstr(
8106 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8107 UnmergeRayDir.getReg(0)}))
8110 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8111 UnmergeRayDir.getReg(1)}))
8114 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8115 UnmergeRayDir.getReg(2)}))
8117 Ops.push_back(MergedDir.getReg(0));
8120 packLanes(RayInvDir);
8124 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8125 Ops.push_back(Unmerge.getReg(0));
8126 Ops.push_back(Unmerge.getReg(1));
8128 Ops.push_back(NodePtr);
8130 Ops.push_back(RayExtent);
8132 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8133 auto SrcInt =
B.buildBitcast(V3I32, Src);
8134 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8135 Ops.push_back(Unmerge.getReg(0));
8136 Ops.push_back(Unmerge.getReg(1));
8137 Ops.push_back(Unmerge.getReg(2));
8140 packLanes(RayOrigin);
8142 auto UnmergeRayDir =
8143 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8144 auto UnmergeRayInvDir =
8145 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8149 B.buildMergeLikeInstr(R1,
8150 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8151 B.buildMergeLikeInstr(
8152 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8153 B.buildMergeLikeInstr(
8154 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8160 packLanes(RayInvDir);
8169 Ops.push_back(MergedOps);
8172 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8181 .addImm(IsA16 ? 1 : 0)
8184 MI.eraseFromParent();
8194 Register DstOrigin =
MI.getOperand(1).getReg();
8196 Register NodePtr =
MI.getOperand(4).getReg();
8197 Register RayExtent =
MI.getOperand(5).getReg();
8198 Register InstanceMask =
MI.getOperand(6).getReg();
8199 Register RayOrigin =
MI.getOperand(7).getReg();
8201 Register Offsets =
MI.getOperand(9).getReg();
8202 Register TDescr =
MI.getOperand(10).getReg();
8205 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8206 const unsigned NumVDataDwords = 10;
8207 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8209 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8210 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8211 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8214 auto RayExtentInstanceMaskVec =
8215 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8216 B.buildAnyExt(I32, InstanceMask)});
8218 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8219 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8225 .addUse(RayExtentInstanceMaskVec.getReg(0))
8232 MI.eraseFromParent();
8241 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8242 MI.eraseFromParent();
8249 if (!ST.hasArchitectedSGPRs())
8253 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8254 auto LSB =
B.buildConstant(I32, 25);
8255 auto Width =
B.buildConstant(I32, 5);
8256 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8257 MI.eraseFromParent();
8265 unsigned Width)
const {
8269 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8270 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8273 B.buildCopy(DstReg, Result);
8274 MI.eraseFromParent();
8294 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8298 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8301 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8302 MI.eraseFromParent();
8315 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8319 .addReg(Unmerge.getReg(0));
8323 .addReg(Unmerge.getReg(1));
8324 MI.eraseFromParent();
8336 case Intrinsic::sponentry:
8342 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8345 B.buildIntToPtr(DstReg, TmpReg);
8346 MI.eraseFromParent();
8348 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8350 B.buildFrameIndex(
MI.getOperand(0), FI);
8351 MI.eraseFromParent();
8354 case Intrinsic::amdgcn_if:
8355 case Intrinsic::amdgcn_else: {
8358 bool Negated =
false;
8375 std::swap(CondBrTarget, UncondBrTarget);
8377 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8378 B.buildCopy(NewUse,
Use);
8379 if (IntrID == Intrinsic::amdgcn_if) {
8380 B.buildInstr(AMDGPU::SI_IF)
8383 .addMBB(UncondBrTarget)
8386 B.buildInstr(AMDGPU::SI_ELSE)
8389 .addMBB(UncondBrTarget)
8399 B.buildBr(*CondBrTarget);
8402 MI.eraseFromParent();
8403 BrCond->eraseFromParent();
8414 case Intrinsic::amdgcn_loop: {
8417 bool Negated =
false;
8426 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8429 std::swap(CondBrTarget, UncondBrTarget);
8431 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8432 B.buildCopy(NewReg, Reg);
8433 B.buildInstr(AMDGPU::SI_LOOP)
8435 .addMBB(UncondBrTarget)
8441 B.buildBr(*CondBrTarget);
8443 MI.eraseFromParent();
8444 BrCond->eraseFromParent();
8450 case Intrinsic::amdgcn_wave_reduce_min:
8451 case Intrinsic::amdgcn_wave_reduce_umin:
8452 case Intrinsic::amdgcn_wave_reduce_fmin:
8453 case Intrinsic::amdgcn_wave_reduce_max:
8454 case Intrinsic::amdgcn_wave_reduce_umax:
8455 case Intrinsic::amdgcn_wave_reduce_fmax:
8456 case Intrinsic::amdgcn_wave_reduce_add:
8457 case Intrinsic::amdgcn_wave_reduce_fadd:
8458 case Intrinsic::amdgcn_wave_reduce_sub:
8459 case Intrinsic::amdgcn_wave_reduce_fsub:
8460 case Intrinsic::amdgcn_wave_reduce_and:
8461 case Intrinsic::amdgcn_wave_reduce_or:
8462 case Intrinsic::amdgcn_wave_reduce_xor: {
8467 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8468 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8469 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8470 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8471 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8472 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8473 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8474 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8475 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8482 .addUse(Ext.getReg(0))
8483 .addImm(
MI.getOperand(3).getImm());
8485 B.buildFPTrunc(DstReg, NewDst);
8487 B.buildTrunc(DstReg, NewDst);
8488 MI.eraseFromParent();
8491 case Intrinsic::amdgcn_make_buffer_rsrc:
8493 case Intrinsic::amdgcn_kernarg_segment_ptr:
8496 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8497 MI.eraseFromParent();
8503 case Intrinsic::amdgcn_implicitarg_ptr:
8505 case Intrinsic::amdgcn_workitem_id_x:
8508 case Intrinsic::amdgcn_workitem_id_y:
8511 case Intrinsic::amdgcn_workitem_id_z:
8514 case Intrinsic::amdgcn_workgroup_id_x:
8519 case Intrinsic::amdgcn_workgroup_id_y:
8524 case Intrinsic::amdgcn_workgroup_id_z:
8529 case Intrinsic::amdgcn_cluster_id_x:
8530 return ST.hasClusters() &&
8533 case Intrinsic::amdgcn_cluster_id_y:
8534 return ST.hasClusters() &&
8537 case Intrinsic::amdgcn_cluster_id_z:
8538 return ST.hasClusters() &&
8541 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8542 return ST.hasClusters() &&
8545 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8546 return ST.hasClusters() &&
8549 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8550 return ST.hasClusters() &&
8553 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8554 return ST.hasClusters() &&
8556 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8557 return ST.hasClusters() &&
8560 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8561 return ST.hasClusters() &&
8564 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8565 return ST.hasClusters() &&
8568 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8569 return ST.hasClusters() &&
8573 case Intrinsic::amdgcn_wave_id:
8575 case Intrinsic::amdgcn_lds_kernel_id:
8578 case Intrinsic::amdgcn_dispatch_ptr:
8581 case Intrinsic::amdgcn_queue_ptr:
8584 case Intrinsic::amdgcn_implicit_buffer_ptr:
8587 case Intrinsic::amdgcn_dispatch_id:
8590 case Intrinsic::r600_read_ngroups_x:
8594 case Intrinsic::r600_read_ngroups_y:
8597 case Intrinsic::r600_read_ngroups_z:
8600 case Intrinsic::r600_read_local_size_x:
8603 case Intrinsic::r600_read_local_size_y:
8607 case Intrinsic::r600_read_local_size_z:
8610 case Intrinsic::amdgcn_fdiv_fast:
8612 case Intrinsic::amdgcn_is_shared:
8614 case Intrinsic::amdgcn_is_private:
8616 case Intrinsic::amdgcn_wavefrontsize: {
8617 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8618 MI.eraseFromParent();
8621 case Intrinsic::amdgcn_s_buffer_load:
8622 case Intrinsic::amdgcn_ptr_s_buffer_load:
8624 case Intrinsic::amdgcn_raw_buffer_store:
8625 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8626 case Intrinsic::amdgcn_struct_buffer_store:
8627 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8629 case Intrinsic::amdgcn_raw_buffer_store_format:
8630 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8631 case Intrinsic::amdgcn_struct_buffer_store_format:
8632 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8634 case Intrinsic::amdgcn_raw_tbuffer_store:
8635 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8636 case Intrinsic::amdgcn_struct_tbuffer_store:
8637 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8639 case Intrinsic::amdgcn_raw_buffer_load:
8640 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8641 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8642 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8643 case Intrinsic::amdgcn_struct_buffer_load:
8644 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8645 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8646 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8648 case Intrinsic::amdgcn_raw_buffer_load_format:
8649 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8650 case Intrinsic::amdgcn_struct_buffer_load_format:
8651 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8653 case Intrinsic::amdgcn_raw_tbuffer_load:
8654 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8655 case Intrinsic::amdgcn_struct_tbuffer_load:
8656 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8658 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8659 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8660 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8661 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8662 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8663 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8664 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8665 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8666 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8667 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8668 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8669 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8670 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8671 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8672 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8673 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8674 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8675 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8676 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8677 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8678 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8679 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8680 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8681 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8682 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8683 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8684 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8685 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8686 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8687 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8688 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8689 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8690 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8691 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8692 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8693 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8694 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8695 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8696 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8697 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8698 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8699 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8700 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8701 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8702 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8703 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8704 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8705 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8706 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8707 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8708 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8709 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8710 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8711 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8712 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8713 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8714 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8715 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8716 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8717 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8718 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8719 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8720 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8721 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8722 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8723 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8724 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8725 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8726 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8727 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8728 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8729 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8731 case Intrinsic::amdgcn_rsq_clamp:
8733 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8735 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8736 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8738 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8739 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8740 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8741 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8742 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8743 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8744 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8745 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8749 if (IndexArgTy != I64) {
8750 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8751 :
B.buildAnyExt(I64, Index);
8752 MI.getOperand(5).setReg(NewIndex.getReg(0));
8756 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8757 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8758 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8759 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8760 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8761 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8762 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8763 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8766 if (MRI.
getType(Index) != I32)
8767 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8770 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8771 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8772 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8773 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8774 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8775 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8776 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8777 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8778 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8780 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8784 if (IndexArgTy != IdxTy) {
8785 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8786 :
B.buildAnyExt(IdxTy, Index);
8787 MI.getOperand(7).setReg(NewIndex.getReg(0));
8792 case Intrinsic::amdgcn_fmed3: {
8798 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8799 MI.removeOperand(1);
8803 case Intrinsic::amdgcn_readlane:
8804 case Intrinsic::amdgcn_writelane:
8805 case Intrinsic::amdgcn_readfirstlane:
8806 case Intrinsic::amdgcn_permlane16:
8807 case Intrinsic::amdgcn_permlanex16:
8808 case Intrinsic::amdgcn_permlane64:
8809 case Intrinsic::amdgcn_set_inactive:
8810 case Intrinsic::amdgcn_set_inactive_chain_arg:
8811 case Intrinsic::amdgcn_mov_dpp8:
8812 case Intrinsic::amdgcn_update_dpp:
8813 case Intrinsic::amdgcn_permlane_bcast:
8814 case Intrinsic::amdgcn_permlane_up:
8815 case Intrinsic::amdgcn_permlane_down:
8816 case Intrinsic::amdgcn_permlane_xor:
8818 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8820 case Intrinsic::amdgcn_dead: {
8824 MI.eraseFromParent();
8827 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8828 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8829 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8830 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8831 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8832 MI.eraseFromParent();
8834 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8835 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8836 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8837 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8838 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8839 MI.eraseFromParent();
8841 case Intrinsic::amdgcn_av_load_b128:
8842 case Intrinsic::amdgcn_av_store_b128: {
8843 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8844 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8845 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8847 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8848 **
MI.memoperands_begin());
8849 MI.eraseFromParent();
8852 case Intrinsic::amdgcn_flat_load_monitor_b32:
8853 case Intrinsic::amdgcn_flat_load_monitor_b64:
8854 case Intrinsic::amdgcn_flat_load_monitor_b128:
8855 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8856 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8857 .add(
MI.getOperand(0))
8858 .add(
MI.getOperand(2))
8859 .addMemOperand(*
MI.memoperands_begin());
8860 MI.eraseFromParent();
8862 case Intrinsic::amdgcn_global_load_monitor_b32:
8863 case Intrinsic::amdgcn_global_load_monitor_b64:
8864 case Intrinsic::amdgcn_global_load_monitor_b128:
8865 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8866 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8867 .add(
MI.getOperand(0))
8868 .add(
MI.getOperand(2))
8869 .addMemOperand(*
MI.memoperands_begin());
8870 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(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.