36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
39#define DEBUG_TYPE "amdgpu-legalinfo"
49 "amdgpu-global-isel-new-legality",
50 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
51 "rules compatible with selection patterns"),
66 unsigned Bits = Ty.getSizeInBits();
76 const LLT Ty = Query.Types[TypeIdx];
82 return Ty.getNumElements() % 2 != 0 &&
83 EltSize > 1 && EltSize < 32 &&
84 Ty.getSizeInBits() % 32 != 0;
90 const LLT Ty = Query.Types[TypeIdx];
97 const LLT Ty = Query.Types[TypeIdx];
99 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
105 const LLT Ty = Query.Types[TypeIdx];
107 return std::pair(TypeIdx,
114 const LLT Ty = Query.Types[TypeIdx];
116 unsigned Size = Ty.getSizeInBits();
117 unsigned Pieces = (
Size + 63) / 64;
118 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
128 const LLT Ty = Query.Types[TypeIdx];
131 const int Size = Ty.getSizeInBits();
133 const int NextMul32 = (
Size + 31) / 32;
137 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
145 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
153 const LLT Ty = Query.Types[TypeIdx];
155 const unsigned EltSize = Ty.getElementType().getSizeInBits();
158 assert(EltSize == 32 || EltSize == 64);
163 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
167 return std::pair(TypeIdx,
182 const unsigned NumElems = Ty.getElementCount().getFixedValue();
187 const unsigned Size = Ty.getSizeInBits();
200 const LLT Ty = Query.Types[TypeIdx];
207 const LLT Ty = Query.Types[TypeIdx];
208 unsigned Size = Ty.getSizeInBits();
210 return std::pair(TypeIdx,
218 const LLT QueryTy = Query.Types[TypeIdx];
225 const LLT QueryTy = Query.Types[TypeIdx];
232 const LLT QueryTy = Query.Types[TypeIdx];
238 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
244 return EltSize == 16 || EltSize % 32 == 0;
248 const int EltSize = Ty.getElementType().getSizeInBits();
249 return EltSize == 32 || EltSize == 64 ||
250 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
251 EltSize == 128 || EltSize == 256;
280 LLT Ty = Query.Types[TypeIdx];
288 const LLT QueryTy = Query.Types[TypeIdx];
376 if (Ty.isPointerOrPointerVector())
377 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
381 (ST.useRealTrue16Insts() && Ty ==
S16) ||
396 const LLT Ty = Query.Types[TypeIdx];
397 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
398 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
406 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
416 bool IsLoad,
bool IsAtomic) {
420 return ST.hasFlatScratchEnabled() ? 128 : 32;
422 return ST.useDS128() ? 128 : 64;
433 return IsLoad ? 512 : 128;
438 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
447 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
449 unsigned RegSize = Ty.getSizeInBits();
452 unsigned AS = Query.
Types[1].getAddressSpace();
459 if (Ty.isVector() && MemSize !=
RegSize)
466 if (IsLoad && MemSize <
Size)
467 MemSize = std::max(MemSize,
Align);
487 if (!ST.hasDwordx3LoadStores())
500 if (AlignBits < MemSize) {
503 Align(AlignBits / 8)))
533 const unsigned Size = Ty.getSizeInBits();
534 if (Ty.isPointerVector())
544 unsigned EltSize = Ty.getScalarSizeInBits();
545 return EltSize != 32 && EltSize != 64;
559 const unsigned Size = Ty.getSizeInBits();
560 if (
Size != MemSizeInBits)
561 return Size <= 32 && Ty.isVector();
567 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
576 uint64_t AlignInBits,
unsigned AddrSpace,
586 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
597 if (AlignInBits < RoundedSize)
604 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
616 Query.
Types[1].getAddressSpace(), Opcode);
636 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
640 std::array<Register, 4> VectorElems;
641 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
642 for (
unsigned I = 0;
I < NumParts; ++
I)
644 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
645 B.buildMergeValues(MO, VectorElems);
650 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
651 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
652 B.buildIntToPtr(MO, Scalar);
672 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
674 for (
unsigned I = 0;
I < NumParts; ++
I)
676 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
678 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
679 return B.buildBitcast(VectorTy, Scalar).getReg(0);
698 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
711 const LLT BufferStridedPtr =
714 const LLT CodePtr = FlatPtr;
716 const std::initializer_list<LLT> AddrSpaces64 = {
717 GlobalPtr, ConstantPtr, FlatPtr
720 const std::initializer_list<LLT> AddrSpaces32 = {
721 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
724 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
726 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
727 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
728 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
729 const std::initializer_list<LLT> FPTypesPK16_64 = {
F32,
F64,
F16,
V2F16,
732 const LLT MinExtendedFPTy = ST.has16BitInsts() ?
F16 :
F32;
760 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
762 if (ST.hasAnyPackedU64Ops()) {
765 .clampMaxNumElementsStrict(0,
S16, 2)
771 }
else if (ST.hasScalarAddSub64()) {
774 .clampMaxNumElementsStrict(0,
S16, 2)
782 .clampMaxNumElementsStrict(0,
S16, 2)
789 if (ST.hasScalarSMulU64()) {
792 .clampMaxNumElementsStrict(0,
S16, 2)
800 .clampMaxNumElementsStrict(0,
S16, 2)
810 .minScalarOrElt(0,
S16)
815 }
else if (ST.has16BitInsts()) {
849 .widenScalarToNextMultipleOf(0, 32)
859 if (ST.hasMad64_32())
864 if (ST.hasIntClamp()) {
887 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
897 if (ST.hasVOP3PInsts()) {
899 .clampMaxNumElements(0,
S8, 2)
920 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
936 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
977 auto &FCanonicalizeActions =
979 auto &StrictFPOpActions =
986 if (ST.has16BitInsts()) {
987 if (ST.hasVOP3PInsts()) {
989 FCanonicalizeActions.legalFor({
F16,
V2F16});
990 StrictFPOpActions.legalFor({
F16,
V2F16});
992 FPOpActions.legalFor({
F16});
993 FCanonicalizeActions.legalFor({
F16});
994 StrictFPOpActions.legalFor({
F16});
997 TrigActions.customFor({
F16});
998 FDIVActions.customFor({
F16});
1004 if (ST.hasAnyPackedFP32Ops()) {
1005 FPOpActions.legalFor({
V2F32});
1006 FCanonicalizeActions.legalFor({
V2F32});
1007 StrictFPOpActions.legalFor({
V2F32});
1008 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1009 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1010 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1013 if (ST.hasAnyPackedFP64Ops()) {
1014 FPOpActions.legalFor({
V2F64});
1015 FCanonicalizeActions.legalFor({
V2F64});
1016 StrictFPOpActions.legalFor({
V2F64});
1017 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1018 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1019 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1022 auto &MinNumMaxNumIeee =
1025 if (ST.hasVOP3PInsts()) {
1026 MinNumMaxNumIeee.legalFor(FPTypesPK16)
1028 .clampMaxNumElements(0,
F16, 2)
1030 }
else if (ST.has16BitInsts()) {
1031 MinNumMaxNumIeee.legalFor(FPTypes16).scalarize(0);
1033 MinNumMaxNumIeee.legalFor(FPTypesBase).scalarize(0);
1037 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1039 if (ST.hasAnyPackedFP64Ops()) {
1040 MinNumMaxNum.customFor(FPTypesPK16_64)
1042 .clampMaxNumElements(0,
F16, 2)
1043 .clampMaxNumElements(0,
F64, 2)
1045 }
else if (ST.hasVOP3PInsts()) {
1046 MinNumMaxNum.customFor(FPTypesPK16)
1048 .clampMaxNumElements(0,
F16, 2)
1050 }
else if (ST.has16BitInsts()) {
1051 MinNumMaxNum.customFor(FPTypes16).scalarize(0);
1053 MinNumMaxNum.customFor(FPTypesBase).scalarize(0);
1056 if (!ST.has16BitInsts()) {
1057 MinNumMaxNumIeee.minScalar(0,
F32);
1058 MinNumMaxNum.minScalar(0,
F32);
1061 if (ST.hasVOP3PInsts()) {
1062 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1063 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1064 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1072 if (!ST.has16BitInsts()) {
1083 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1086 if (ST.hasAnyPackedFP32Ops())
1090 if (ST.has16BitInsts()) {
1093 .legalFor(ST.hasBF16TransInsts(), {BF16})
1103 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1125 if (ST.hasFractBug()) {
1139 .legalFor({{
F32, I32}, {
F64, I32}})
1159 if (ST.hasCvtPkF16F32Inst()) {
1161 .clampMaxNumElements(0,
F16, 2);
1174 if (ST.has16BitInsts()) {
1188 if (ST.hasAnyPackedFP32Ops())
1196 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1197 FMad.customFor({
F32,
F16});
1198 else if (ST.hasMadMacF32Insts())
1199 FMad.customFor({
F32});
1200 else if (ST.hasMadF16())
1201 FMad.customFor({
F16});
1206 if (ST.has16BitInsts()) {
1209 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1217 .clampMaxNumElements(0,
S16, 2)
1233 .legalFor({{
F32, I32}, {
F64, I32}})
1237 if (ST.has16BitInsts())
1245 .legalFor({{I32,
F32}, {I32,
F64}})
1246 .customFor({{I64,
F32}, {I64,
F64}})
1249 if (ST.has16BitInsts())
1258 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1259 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1260 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1264 if (
ST.has16BitInsts())
1267 if (
ST.hasVCvtPkIU16F32())
1277 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1278 .clampScalar(0, I16, I64)
1282 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1288 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1292 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1293 .clampScalar(0, I16, I64)
1297 auto &RoundingActions = getActionDefinitionsBuilder(
1298 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1299 if (
ST.has16BitInsts())
1307 if (!
ST.has16BitInsts())
1310 getActionDefinitionsBuilder(G_PTR_ADD)
1316 getActionDefinitionsBuilder(G_PTRMASK)
1318 .scalarSameSizeAs(1, 0)
1322 getActionDefinitionsBuilder(G_ICMP)
1334 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1335 .legalForCartesianProduct(
1336 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1337 if (
ST.has16BitInsts()) {
1338 CmpBuilder.legalFor({{
S1,
S16}});
1347 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1350 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1351 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1353 if (
ST.hasSALUFloatInsts())
1354 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1356 FCmpBuilder.widenScalarToNextPow2(1).minScalar(1,
F32).scalarize(0);
1359 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1360 if (
ST.has16BitInsts())
1361 ExpOps.customFor({{
F32}, {
F16}});
1363 ExpOps.customFor({
F32});
1364 ExpOps.clampScalar(0, MinExtendedFPTy,
F32).scalarize(0);
1366 getActionDefinitionsBuilder(G_FPOWI)
1367 .clampScalar(0, MinExtendedFPTy,
F32)
1370 getActionDefinitionsBuilder(G_FLOG2)
1371 .legalFor(
ST.has16BitInsts(), {F16})
1372 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1378 getActionDefinitionsBuilder(G_FEXP2)
1379 .legalFor(
ST.has16BitInsts(), {F16})
1380 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1386 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1390 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1395 getActionDefinitionsBuilder(G_CTPOP)
1397 .clampScalar(0,
S32,
S32)
1398 .widenScalarToNextPow2(1, 32)
1399 .clampScalar(1,
S32,
S64)
1401 .widenScalarToNextPow2(0, 32);
1404 if (
ST.has16BitInsts())
1405 getActionDefinitionsBuilder(G_IS_FPCLASS)
1406 .legalForCartesianProduct({
I1}, FPTypes16)
1407 .widenScalarToNextPow2(1)
1411 getActionDefinitionsBuilder(G_IS_FPCLASS)
1412 .legalForCartesianProduct({
I1}, FPTypesBase)
1413 .lowerFor({
I1,
F16})
1414 .widenScalarToNextPow2(1)
1421 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1423 .clampScalar(0,
S32,
S32)
1424 .clampScalar(1,
S32,
S64)
1425 .widenScalarToNextPow2(0, 32)
1426 .widenScalarToNextPow2(1, 32)
1430 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1433 .clampScalar(0,
S32,
S32)
1434 .clampScalar(1,
S32,
S64)
1436 .widenScalarToNextPow2(0, 32)
1437 .widenScalarToNextPow2(1, 32);
1439 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1441 .clampScalar(0,
S32,
S32)
1442 .clampScalar(1,
S32,
S64)
1444 .widenScalarToNextPow2(0, 32)
1445 .widenScalarToNextPow2(1, 32);
1447 getActionDefinitionsBuilder(G_CTLS)
1450 .clampScalar(0,
S32,
S32)
1451 .clampScalar(1,
S32,
S32);
1455 getActionDefinitionsBuilder(G_BITREVERSE)
1457 .clampScalar(0,
S32,
S64)
1459 .widenScalarToNextPow2(0);
1461 if (
ST.has16BitInsts()) {
1462 getActionDefinitionsBuilder(G_BSWAP)
1464 .clampMaxNumElementsStrict(0,
S16, 2)
1467 .widenScalarToNextPow2(0)
1468 .clampScalar(0,
S16,
S32)
1471 if (
ST.hasVOP3PInsts()) {
1472 getActionDefinitionsBuilder(G_ABS)
1474 .clampMaxNumElements(0,
S16, 2)
1476 .widenScalarToNextPow2(0)
1479 if (
ST.useMinMaxI64Insts()) {
1480 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1482 .clampMaxNumElements(0,
S16, 2)
1484 .widenScalarToNextPow2(0)
1488 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1490 .clampMaxNumElements(0,
S16, 2)
1492 .widenScalarToNextPow2(0)
1497 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1499 .widenScalarToNextPow2(0)
1506 getActionDefinitionsBuilder(G_BSWAP)
1511 .widenScalarToNextPow2(0)
1516 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1519 .widenScalarToNextPow2(0)
1524 getActionDefinitionsBuilder(G_INTTOPTR)
1526 .legalForCartesianProduct(AddrSpaces64, {
S64})
1527 .legalForCartesianProduct(AddrSpaces32, {
S32})
1540 getActionDefinitionsBuilder(G_PTRTOINT)
1542 .legalForCartesianProduct(AddrSpaces64, {
S64})
1543 .legalForCartesianProduct(AddrSpaces32, {
S32})
1556 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1560 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1561 bool IsLoad) ->
bool {
1565 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1579 unsigned NumRegs = (MemSize + 31) / 32;
1581 if (!
ST.hasDwordx3LoadStores())
1592 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1593 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1594 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1600 for (
unsigned Op : {G_LOAD, G_STORE}) {
1601 const bool IsStore =
Op == G_STORE;
1603 auto &Actions = getActionDefinitionsBuilder(
Op);
1606 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1609 {
S64, GlobalPtr,
S64, GlobalAlign32},
1612 {
S32, GlobalPtr,
S8, GlobalAlign8},
1613 {
S32, GlobalPtr,
S16, GlobalAlign16},
1615 {
S32, LocalPtr,
S32, 32},
1616 {
S64, LocalPtr,
S64, 32},
1618 {
S32, LocalPtr,
S8, 8},
1619 {
S32, LocalPtr,
S16, 16},
1622 {
S32, PrivatePtr,
S32, 32},
1623 {
S32, PrivatePtr,
S8, 8},
1624 {
S32, PrivatePtr,
S16, 16},
1627 {
S32, ConstantPtr,
S32, GlobalAlign32},
1630 {
S64, ConstantPtr,
S64, GlobalAlign32},
1631 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1633 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1634 {{S16, GlobalPtr, S8, GlobalAlign8},
1635 {S16, GlobalPtr, S16, GlobalAlign16},
1636 {S16, LocalPtr, S8, 8},
1637 {S16, LocalPtr, S16, 16},
1638 {S16, PrivatePtr, S8, 8},
1639 {S16, PrivatePtr, S16, 16}});
1649 Actions.unsupportedIf(
1650 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1664 Actions.customIf(
typeIs(1, Constant32Ptr));
1690 return !Query.
Types[0].isVector() &&
1691 needToSplitMemOp(Query,
Op == G_LOAD);
1693 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1698 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1701 if (DstSize > MemSize)
1707 if (MemSize > MaxSize)
1715 return Query.
Types[0].isVector() &&
1716 needToSplitMemOp(Query,
Op == G_LOAD);
1718 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1732 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1733 if (MemSize > MaxSize) {
1737 if (MaxSize % EltSize == 0) {
1743 unsigned NumPieces = MemSize / MaxSize;
1747 if (NumPieces == 1 || NumPieces >= NumElts ||
1748 NumElts % NumPieces != 0)
1749 return std::pair(0, EltTy);
1757 return std::pair(0, EltTy);
1772 return std::pair(0, EltTy);
1777 .widenScalarToNextPow2(0)
1784 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1785 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1786 {
S32, GlobalPtr,
S16, 2 * 8},
1787 {
S32, LocalPtr,
S8, 8},
1788 {
S32, LocalPtr,
S16, 16},
1789 {
S32, PrivatePtr,
S8, 8},
1790 {
S32, PrivatePtr,
S16, 16},
1791 {
S32, ConstantPtr,
S8, 8},
1792 {
S32, ConstantPtr,
S16, 2 * 8}})
1793 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1794 {{S16, GlobalPtr, S8, GlobalAlign8},
1795 {S16, LocalPtr, S8, GlobalAlign8},
1796 {S16, PrivatePtr, S8, GlobalAlign8},
1797 {S16, ConstantPtr, S8, GlobalAlign8}})
1802 if (
ST.hasFlatAddressSpace()) {
1803 ExtLoads.legalForTypesWithMemDesc(
1804 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1806 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1807 {{S16, FlatPtr, S8, GlobalAlign8}});
1815 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1817 ExtLoads.narrowScalarIf(
1824 ExtLoads.clampScalar(0,
S32,
S32)
1825 .widenScalarToNextPow2(0)
1828 auto &Atomics = getActionDefinitionsBuilder(
1829 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1830 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1831 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1832 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1833 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1834 {
S64, GlobalPtr}, {
S64, LocalPtr},
1835 {
S32, RegionPtr}, {
S64, RegionPtr}});
1836 if (
ST.hasFlatAddressSpace()) {
1837 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1841 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1842 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1843 if (
ST.hasFlatAddressSpace()) {
1844 Atomics32.legalFor({{
S32, FlatPtr}});
1848 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1849 if (
ST.hasLDSFPAtomicAddF32()) {
1850 Atomic.legalFor({{
F32, LocalPtr}, {
F32, RegionPtr}});
1851 if (
ST.hasLdsAtomicAddF64())
1852 Atomic.legalFor({{
F64, LocalPtr}});
1853 if (
ST.hasAtomicDsPkAdd16Insts())
1854 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1856 if (
ST.hasAtomicFaddInsts())
1857 Atomic.legalFor({{
F32, GlobalPtr}});
1858 if (
ST.hasFlatAtomicFaddF32Inst())
1859 Atomic.legalFor({{
F32, FlatPtr}});
1861 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1865 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1868 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1869 ST.hasAtomicBufferGlobalPkAddF16Insts())
1870 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1871 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1872 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1873 if (
ST.hasAtomicFlatPkAdd16Insts())
1874 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1879 auto &AtomicFMinFMax =
1880 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1881 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1883 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1884 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1885 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1886 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1887 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1888 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1889 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1890 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1894 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1895 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1896 {
S32, FlatPtr}, {
S64, FlatPtr}})
1897 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1898 {
S32, RegionPtr}, {
S64, RegionPtr}});
1902 getActionDefinitionsBuilder(G_SELECT)
1904 LocalPtr, FlatPtr, PrivatePtr,
1908 .clampScalar(0,
S16,
S64)
1912 .clampMaxNumElements(0,
S32, 2)
1913 .clampMaxNumElements(0, LocalPtr, 2)
1914 .clampMaxNumElements(0, PrivatePtr, 2)
1916 .widenScalarToNextPow2(0)
1921 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1923 if (
ST.has16BitInsts()) {
1924 if (
ST.hasVOP3PInsts()) {
1926 .clampMaxNumElements(0,
S16, 2);
1928 Shifts.legalFor({{
S16,
S16}});
1931 Shifts.widenScalarIf(
1936 const LLT AmountTy = Query.
Types[1];
1942 Shifts.clampScalar(1,
S32,
S32);
1943 Shifts.widenScalarToNextPow2(0, 16);
1944 Shifts.clampScalar(0,
S16,
S64);
1946 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1954 Shifts.clampScalar(1,
S32,
S32);
1955 Shifts.widenScalarToNextPow2(0, 32);
1956 Shifts.clampScalar(0,
S32,
S64);
1958 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1963 Shifts.scalarize(0);
1965 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1966 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1967 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1968 unsigned IdxTypeIdx = 2;
1970 getActionDefinitionsBuilder(
Op)
1972 const LLT EltTy = Query.
Types[EltTypeIdx];
1973 const LLT VecTy = Query.
Types[VecTypeIdx];
1974 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1976 const bool isLegalVecType =
1986 return (EltSize == 32 || EltSize == 64) &&
2002 const LLT EltTy = Query.
Types[EltTypeIdx];
2003 const LLT VecTy = Query.
Types[VecTypeIdx];
2007 const unsigned TargetEltSize =
2008 DstEltSize % 64 == 0 ? 64 : 32;
2009 return std::pair(VecTypeIdx,
2013 .clampScalar(EltTypeIdx,
S32,
S64)
2014 .clampScalar(VecTypeIdx,
S32,
S64)
2015 .clampScalar(IdxTypeIdx,
S32,
S32)
2016 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2025 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2027 const LLT &EltTy = Query.
Types[1].getElementType();
2028 return Query.
Types[0] != EltTy;
2031 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2032 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2033 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2034 getActionDefinitionsBuilder(
Op)
2037 const LLT BigTy = Query.
Types[BigTyIdx];
2043 const LLT LitTy = Query.
Types[LitTyIdx];
2048 .widenScalarToNextPow2(BigTyIdx, 32)
2056 const LLT BigTy = Query.
Types[BigTyIdx];
2057 const LLT LitTy = Query.
Types[LitTyIdx];
2065 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2075 if (
ST.hasScalarPackInsts()) {
2078 .minScalarOrElt(0,
S16)
2081 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2085 BuildVector.customFor({
V2S16,
S16});
2086 BuildVector.minScalarOrElt(0,
S32);
2088 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2096 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2098 .clampMaxNumElements(0,
S32, 32)
2099 .clampMaxNumElements(1,
S16, 2)
2100 .clampMaxNumElements(0,
S16, 64);
2102 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2105 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2106 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2107 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2109 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2110 const LLT Ty = Query.
Types[TypeIdx];
2122 getActionDefinitionsBuilder(
Op)
2126 const LLT BigTy = Query.
Types[BigTyIdx];
2132 .widenScalarToNextPow2(LitTyIdx, 16)
2141 .clampScalar(LitTyIdx,
S32,
S512)
2142 .widenScalarToNextPow2(LitTyIdx, 32)
2146 return notValidElt(Query, LitTyIdx);
2151 return notValidElt(Query, BigTyIdx);
2156 if (
Op == G_MERGE_VALUES) {
2157 Builder.widenScalarIf(
2160 const LLT Ty = Query.
Types[LitTyIdx];
2166 Builder.widenScalarIf(
2168 const LLT Ty = Query.
Types[BigTyIdx];
2174 const LLT &Ty = Query.
Types[BigTyIdx];
2176 if (NewSizeInBits >= 256) {
2178 if (RoundedTo < NewSizeInBits)
2179 NewSizeInBits = RoundedTo;
2181 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2190 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2191 .legalFor({{
S32}, {
S64}})
2192 .clampScalar(0,
S32,
S64);
2194 if (
ST.hasVOP3PInsts()) {
2195 SextInReg.lowerFor({{
V2S16}})
2199 .clampMaxNumElementsStrict(0,
S16, 2);
2200 }
else if (
ST.has16BitInsts()) {
2201 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2205 SextInReg.lowerFor({{
S32}, {
S64}});
2210 .clampScalar(0,
S32,
S64)
2213 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2217 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2218 FSHRActionDefs.legalFor({{
S32,
S32}})
2219 .clampMaxNumElementsStrict(0,
S16, 2);
2220 if (
ST.hasVOP3PInsts())
2222 FSHRActionDefs.scalarize(0).lower();
2224 if (
ST.hasVOP3PInsts()) {
2225 getActionDefinitionsBuilder(G_FSHL)
2227 .clampMaxNumElementsStrict(0,
S16, 2)
2231 getActionDefinitionsBuilder(G_FSHL)
2236 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2239 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2241 getActionDefinitionsBuilder(G_FENCE)
2244 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2249 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2251 .clampScalar(1,
S32,
S32)
2252 .clampScalar(0,
S32,
S64)
2253 .widenScalarToNextPow2(0)
2256 getActionDefinitionsBuilder(
2260 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2261 G_READ_REGISTER, G_WRITE_REGISTER,
2266 if (
ST.hasIEEEMinimumMaximumInsts()) {
2267 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2268 .legalFor(FPTypesPK16)
2269 .clampMaxNumElements(0,
F16, 2)
2271 }
else if (
ST.hasVOP3PInsts()) {
2272 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2274 .clampMaxNumElementsStrict(0,
F16, 2)
2278 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2280 .clampScalar(0,
F32,
F64)
2284 getActionDefinitionsBuilder(
2285 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2288 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2290 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2291 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2292 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2295 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2297 getActionDefinitionsBuilder(
2298 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2299 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2300 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2301 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2306 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2307 G_INTRINSIC_CONVERGENT,
2308 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2320 switch (
MI.getOpcode()) {
2321 case TargetOpcode::G_ADDRSPACE_CAST:
2323 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2325 case TargetOpcode::G_FCEIL:
2327 case TargetOpcode::G_FREM:
2329 case TargetOpcode::G_INTRINSIC_TRUNC:
2331 case TargetOpcode::G_SITOFP:
2333 case TargetOpcode::G_UITOFP:
2335 case TargetOpcode::G_FPTOSI:
2337 case TargetOpcode::G_FPTOUI:
2339 case TargetOpcode::G_FMINNUM:
2340 case TargetOpcode::G_FMAXNUM:
2341 case TargetOpcode::G_FMINIMUMNUM:
2342 case TargetOpcode::G_FMAXIMUMNUM:
2344 case TargetOpcode::G_EXTRACT:
2346 case TargetOpcode::G_INSERT:
2348 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2350 case TargetOpcode::G_INSERT_VECTOR_ELT:
2352 case TargetOpcode::G_FSIN:
2353 case TargetOpcode::G_FCOS:
2355 case TargetOpcode::G_GLOBAL_VALUE:
2357 case TargetOpcode::G_LOAD:
2358 case TargetOpcode::G_SEXTLOAD:
2359 case TargetOpcode::G_ZEXTLOAD:
2361 case TargetOpcode::G_STORE:
2363 case TargetOpcode::G_FMAD:
2365 case TargetOpcode::G_FDIV:
2367 case TargetOpcode::G_FFREXP:
2369 case TargetOpcode::G_FSQRT:
2371 case TargetOpcode::G_UDIV:
2372 case TargetOpcode::G_UREM:
2373 case TargetOpcode::G_UDIVREM:
2375 case TargetOpcode::G_SDIV:
2376 case TargetOpcode::G_SREM:
2377 case TargetOpcode::G_SDIVREM:
2379 case TargetOpcode::G_ATOMIC_CMPXCHG:
2381 case TargetOpcode::G_FLOG2:
2383 case TargetOpcode::G_FLOG:
2384 case TargetOpcode::G_FLOG10:
2386 case TargetOpcode::G_FEXP2:
2388 case TargetOpcode::G_FEXP:
2389 case TargetOpcode::G_FEXP10:
2391 case TargetOpcode::G_FPOW:
2393 case TargetOpcode::G_FFLOOR:
2395 case TargetOpcode::G_BUILD_VECTOR:
2396 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2398 case TargetOpcode::G_MUL:
2400 case TargetOpcode::G_CTLZ:
2401 case TargetOpcode::G_CTTZ:
2403 case TargetOpcode::G_CTLS:
2405 case TargetOpcode::G_CTLZ_ZERO_POISON:
2407 case TargetOpcode::G_STACKSAVE:
2409 case TargetOpcode::G_GET_FPENV:
2411 case TargetOpcode::G_SET_FPENV:
2413 case TargetOpcode::G_TRAP:
2415 case TargetOpcode::G_DEBUGTRAP:
2435 if (ST.hasApertureRegs()) {
2440 ? AMDGPU::SRC_SHARED_BASE
2441 : AMDGPU::SRC_PRIVATE_BASE;
2442 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2443 !ST.hasGloballyAddressableScratch()) &&
2444 "Cannot use src_private_base with globally addressable scratch!");
2447 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2448 return B.buildUnmerge(I32, Dst).getReg(1);
2463 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2479 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2482 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2504 B.buildObjectPtrOffset(
2507 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2515 switch (Def->getOpcode()) {
2516 case AMDGPU::G_FRAME_INDEX:
2517 case AMDGPU::G_GLOBAL_VALUE:
2518 case AMDGPU::G_BLOCK_ADDR:
2520 case AMDGPU::G_CONSTANT: {
2521 const ConstantInt *CI = Def->getOperand(1).getCImm();
2538 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2540 Intrinsic::amdgcn_addrspacecast_nonnull));
2546 :
MI.getOperand(1).getReg();
2550 unsigned SrcAS = SrcTy.getAddressSpace();
2560 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2567 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2569 ST.hasGloballyAddressableScratch()) {
2572 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2574 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2575 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2577 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2578 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2579 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2583 return B.buildExtract(Dst, Src, 0).getReg(0);
2589 castFlatToLocalOrPrivate(Dst);
2590 MI.eraseFromParent();
2596 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2597 auto FlatNull =
B.buildConstant(SrcTy, 0);
2600 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2604 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2606 MI.eraseFromParent();
2613 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2616 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2619 ST.hasGloballyAddressableScratch()) {
2623 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2624 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2628 if (ST.isWave64()) {
2629 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2635 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2636 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2638 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2642 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2643 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2645 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2646 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2655 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2661 castLocalOrPrivateToFlat(Dst);
2662 MI.eraseFromParent();
2666 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2673 SegmentNull.getReg(0));
2675 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2677 MI.eraseFromParent();
2682 SrcTy.getSizeInBits() == 64) {
2684 B.buildExtract(Dst, Src, 0);
2685 MI.eraseFromParent();
2692 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2693 auto PtrLo =
B.buildPtrToInt(I32, Src);
2694 if (AddrHiVal == 0) {
2695 auto Zext =
B.buildZExt(I64, PtrLo);
2696 B.buildIntToPtr(Dst, Zext);
2698 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2699 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2702 MI.eraseFromParent();
2709 MI.eraseFromParent();
2718 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2723 auto C1 =
B.buildFConstant(Ty, C1Val);
2724 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2727 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2728 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2730 auto C2 =
B.buildFConstant(Ty, C2Val);
2731 auto Fabs =
B.buildFAbs(Ty, Src);
2734 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2735 MI.eraseFromParent();
2752 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2754 const auto Zero =
B.buildFConstant(
F64, 0.0);
2755 const auto One =
B.buildFConstant(
F64, 1.0);
2758 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2759 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2762 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2763 MI.eraseFromParent();
2771 Register Src0Reg =
MI.getOperand(1).getReg();
2772 Register Src1Reg =
MI.getOperand(2).getReg();
2773 auto Flags =
MI.getFlags();
2776 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2777 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2778 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2779 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2780 MI.eraseFromParent();
2786 const unsigned FractBits = 52;
2787 const unsigned ExpBits = 11;
2790 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2791 auto Const1 =
B.buildConstant(I32, ExpBits);
2793 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2795 .addUse(Const0.getReg(0))
2796 .addUse(Const1.getReg(0));
2798 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2811 auto SrcInt =
B.buildBitcast(I64, Src);
2814 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2821 const unsigned FractBits = 52;
2824 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2825 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2827 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2829 const auto Zero32 =
B.buildConstant(I32, 0);
2832 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2834 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2835 auto Not =
B.buildNot(I64, Shr);
2836 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2837 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2842 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2843 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2844 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2845 MI.eraseFromParent();
2861 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2862 auto ThirtyTwo =
B.buildConstant(I32, 32);
2865 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2866 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2868 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2869 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2872 B.buildFAdd(Dst, LdExp, CvtLo);
2873 MI.eraseFromParent();
2879 auto One =
B.buildConstant(I32, 1);
2883 auto ThirtyOne =
B.buildConstant(I32, 31);
2884 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2885 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2886 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2887 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2888 .addUse(Unmerge.getReg(1));
2889 auto LS2 =
B.buildSub(I32, LS, One);
2890 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2892 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2893 auto Norm =
B.buildShl(I64, Src, ShAmt);
2894 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2895 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2896 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2897 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2898 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2899 B.buildFLdexp(Dst, FVal, Scale);
2900 MI.eraseFromParent();
2920 unsigned Flags =
MI.getFlags();
2931 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2939 auto SrcInt =
B.buildBitcast(I32, Src);
2940 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2941 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2945 K0 =
B.buildFConstant(
2947 K1 =
B.buildFConstant(
2950 K0 =
B.buildFConstant(
2952 K1 =
B.buildFConstant(
2956 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2957 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2958 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2960 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2961 :
B.buildFPTOUI(I32, FloorMul);
2962 auto Lo =
B.buildFPTOUI(I32, Fma);
2966 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2968 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2971 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2972 MI.eraseFromParent();
2995 uint64_t
Offset =
MI.getOperand(2).getImm();
3004 unsigned StartIdx =
Offset / 32;
3008 if (DstCount == 1) {
3010 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3015 for (
unsigned I = 0;
I < DstCount; ++
I)
3016 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3017 B.buildMergeLikeInstr(DstReg, MergeVec);
3020 MI.eraseFromParent();
3030 Register InsertSrc =
MI.getOperand(2).getReg();
3031 uint64_t
Offset =
MI.getOperand(3).getImm();
3039 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3043 unsigned DstCount = DstSize / 32;
3044 unsigned InsertCount = InsertSize / 32;
3045 unsigned StartIdx =
Offset / 32;
3047 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3050 for (
unsigned I = 0;
I < StartIdx; ++
I)
3053 if (InsertCount == 1) {
3057 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3060 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3061 for (
unsigned I = 0;
I < InsertCount; ++
I)
3065 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3068 B.buildMergeLikeInstr(DstReg, MergeVec);
3070 MI.eraseFromParent();
3097 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3098 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3099 B.buildIntToPtr(Dst, IntElt);
3101 MI.eraseFromParent();
3108 std::optional<ValueAndVReg> MaybeIdxVal =
3112 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3115 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3116 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3121 MI.eraseFromParent();
3150 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3151 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3152 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3154 B.buildIntToPtr(Dst, IntVecDest);
3155 MI.eraseFromParent();
3162 std::optional<ValueAndVReg> MaybeIdxVal =
3167 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3170 if (IdxVal < NumElts) {
3172 for (
unsigned i = 0; i < NumElts; ++i)
3174 B.buildUnmerge(SrcRegs, Vec);
3176 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3177 B.buildMergeLikeInstr(Dst, SrcRegs);
3182 MI.eraseFromParent();
3193 unsigned Flags =
MI.getFlags();
3197 if (ST.hasTrigReducedRange()) {
3198 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3199 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3200 .addUse(MulVal.getReg(0))
3204 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3207 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3211 MI.eraseFromParent();
3219 unsigned GAFlags)
const {
3248 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3250 if (ST.has64BitLiterals()) {
3254 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3258 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3267 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3268 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3271 B.buildExtract(DstReg, PCReg, 0);
3281 if (RequiresHighHalf && ST.has64BitLiterals()) {
3283 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3284 B.buildInstr(AMDGPU::S_MOV_B64)
3299 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3302 B.buildInstr(AMDGPU::S_MOV_B32)
3307 if (RequiresHighHalf) {
3309 "Must provide a 64-bit pointer type!");
3312 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3314 B.buildInstr(AMDGPU::S_MOV_B32)
3325 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3327 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3331 if (AddrDst != DstReg)
3332 B.buildCast(DstReg, AddrDst);
3333 }
else if (AddrLo != DstReg) {
3336 B.buildCast(DstReg, AddrLo);
3345 unsigned AS = Ty.getAddressSpace();
3353 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3357 Fn,
"local memory global used by non-kernel function",
3366 B.buildUndef(DstReg);
3367 MI.eraseFromParent();
3391 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3392 B.buildIntToPtr(DstReg, Sz);
3393 MI.eraseFromParent();
3399 MI.eraseFromParent();
3403 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3405 MI.eraseFromParent();
3413 MI.eraseFromParent();
3419 MI.eraseFromParent();
3435 if (Ty.getSizeInBits() == 32) {
3437 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3438 B.buildExtract(DstReg,
Load, 0);
3440 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3442 MI.eraseFromParent();
3465 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3467 MI.getOperand(1).setReg(Cast.getReg(0));
3472 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3490 const uint64_t AlignInBits = 8 * MemAlign.
value();
3498 if (WideMemSize == ValSize) {
3504 MI.setMemRefs(MF, {WideMMO});
3510 if (ValSize > WideMemSize)
3517 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3518 B.buildTrunc(ValReg, WideLoad).getReg(0);
3525 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3526 B.buildExtract(ValReg, WideLoad, 0);
3530 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3531 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3535 MI.eraseFromParent();
3548 Register DataReg =
MI.getOperand(0).getReg();
3593 "this should not have been custom lowered");
3598 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3600 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3604 .setMemRefs(
MI.memoperands());
3606 MI.eraseFromParent();
3614 switch (
DefMI->getOpcode()) {
3615 case TargetOpcode::G_INTRINSIC: {
3617 case Intrinsic::amdgcn_frexp_mant:
3618 case Intrinsic::amdgcn_log:
3619 case Intrinsic::amdgcn_log_clamp:
3620 case Intrinsic::amdgcn_exp2:
3621 case Intrinsic::amdgcn_sqrt:
3629 case TargetOpcode::G_FSQRT:
3631 case TargetOpcode::G_FFREXP: {
3632 if (
DefMI->getOperand(0).getReg() == Src)
3636 case TargetOpcode::G_FPEXT: {
3657std::pair<Register, Register>
3659 unsigned Flags)
const {
3663 auto SmallestNormal =
B.buildFConstant(
3665 auto IsLtSmallestNormal =
3668 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3669 auto One =
B.buildFConstant(
F32, 1.0);
3671 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3672 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3674 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3687 LLT Ty =
B.getMRI()->getType(Dst);
3688 unsigned Flags =
MI.getFlags();
3692 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3693 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3694 .addUse(Ext.getReg(0))
3696 B.buildFPTrunc(Dst,
Log2, Flags);
3697 MI.eraseFromParent();
3705 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3708 MI.eraseFromParent();
3712 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3713 .addUse(ScaledInput)
3716 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3717 auto Zero =
B.buildFConstant(Ty, 0.0);
3719 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3720 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3722 MI.eraseFromParent();
3728 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3729 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3734 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3735 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3740 unsigned Flags =
MI.getFlags();
3750 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3752 B.buildFPTrunc(Dst, LogVal, Flags);
3757 MI.eraseFromParent();
3766 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3769 if (ST.hasFastFMAF32()) {
3771 const float c_log10 = 0x1.344134p-2f;
3772 const float cc_log10 = 0x1.09f79ep-26f;
3775 const float c_log = 0x1.62e42ep-1f;
3776 const float cc_log = 0x1.efa39ep-25f;
3778 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3779 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3783 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3784 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3785 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3786 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3787 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3790 const float ch_log10 = 0x1.344000p-2f;
3791 const float ct_log10 = 0x1.3509f6p-18f;
3794 const float ch_log = 0x1.62e000p-1f;
3795 const float ct_log = 0x1.0bfbe8p-15f;
3797 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3798 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3801 auto YInt =
B.buildBitcast(I32,
Y);
3802 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3803 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3804 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3808 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3811 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3813 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3816 const bool IsFiniteOnly =
3819 if (!IsFiniteOnly) {
3822 auto Fabs =
B.buildFAbs(Ty,
Y);
3825 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3829 auto Zero =
B.buildFConstant(Ty, 0.0);
3831 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3832 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3833 B.buildFSub(Dst, R, Shift, Flags);
3835 B.buildCopy(Dst, R);
3838 MI.eraseFromParent();
3844 unsigned Flags)
const {
3845 const double Log2BaseInverted =
3848 LLT Ty =
B.getMRI()->getType(Dst);
3853 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3854 .addUse(ScaledInput)
3856 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3857 auto Zero =
B.buildFConstant(Ty, 0.0);
3859 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3860 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3862 if (ST.hasFastFMAF32())
3863 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3865 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3866 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3873 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3874 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3877 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3878 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3889 unsigned Flags =
MI.getFlags();
3890 LLT Ty =
B.getMRI()->getType(Dst);
3897 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3898 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3899 .addUse(Ext.getReg(0))
3901 B.buildFPTrunc(Dst,
Log2, Flags);
3902 MI.eraseFromParent();
3912 MI.eraseFromParent();
3920 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3922 RangeCheckConst, Flags);
3924 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3925 auto Zero =
B.buildFConstant(Ty, 0.0);
3926 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3927 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3929 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3930 .addUse(AddInput.getReg(0))
3933 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3934 auto One =
B.buildFConstant(Ty, 1.0);
3935 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3936 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3937 MI.eraseFromParent();
3942 const SrcOp &Src,
unsigned Flags) {
3943 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3946 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3947 .addUse(Src.getReg())
3950 return B.buildFExp2(Dst, Src, Flags);
3956 bool IsExp10)
const {
3957 LLT Ty =
B.getMRI()->getType(
X);
3961 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3962 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3969 LLT Ty =
B.getMRI()->getType(Dst);
3975 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3978 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3979 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3980 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3983 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3985 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3986 .addUse(ExpInput.getReg(0))
3989 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3990 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3991 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3997 unsigned Flags)
const {
3998 LLT Ty =
B.getMRI()->getType(Dst);
4002 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4003 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4005 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4006 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4007 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4008 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4009 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4019 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4023 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4024 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4025 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4027 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4028 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4030 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4031 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4032 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4033 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4035 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4036 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4037 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4039 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4057 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4059 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4061 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4063 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4064 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4065 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4066 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4068 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4069 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4070 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4071 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4073 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4074 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4075 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4076 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4077 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4079 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4080 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4081 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4082 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4085 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4086 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4087 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4089 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4090 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4091 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4092 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4093 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4097 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4098 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4100 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4102 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4104 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4106 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4108 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4109 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4110 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4111 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4113 auto One =
B.buildFConstant(
F64, 1.0);
4114 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4115 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4118 auto DnInt =
B.buildFPTOSI(I32, Dn);
4119 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4126 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4133 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4135 MI.eraseFromParent();
4143 const unsigned Flags =
MI.getFlags();
4151 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4159 MI.eraseFromParent();
4170 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4173 B.buildFPTrunc(Dst, Lowered, Flags);
4174 MI.eraseFromParent();
4185 MI.eraseFromParent();
4213 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4216 if (ST.hasFastFMAF32()) {
4218 const float cc_exp = 0x1.4ae0bep-26f;
4219 const float c_exp10 = 0x1.a934f0p+1f;
4220 const float cc_exp10 = 0x1.2f346ep-24f;
4222 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4223 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4224 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4225 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4227 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4228 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4230 const float ch_exp = 0x1.714000p+0f;
4231 const float cl_exp = 0x1.47652ap-12f;
4233 const float ch_exp10 = 0x1.a92000p+1f;
4234 const float cl_exp10 = 0x1.4f0978p-11f;
4237 auto XInt =
B.buildBitcast(I32,
X);
4238 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4239 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4240 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4242 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4243 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4245 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4246 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4249 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4250 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4253 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4256 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4257 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4259 auto IntE =
B.buildFPTOSI(I32, E);
4261 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4262 .addUse(
A.getReg(0))
4264 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4266 auto UnderflowCheckConst =
4267 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4268 auto Zero =
B.buildFConstant(Ty, 0.0);
4272 R =
B.buildSelect(Ty, Underflow, Zero, R);
4275 auto OverflowCheckConst =
4276 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4281 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4284 B.buildCopy(Dst, R);
4285 MI.eraseFromParent();
4294 unsigned Flags =
MI.getFlags();
4295 LLT Ty =
B.getMRI()->getType(Dst);
4298 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4299 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4300 .addUse(Log.getReg(0))
4303 B.buildFExp2(Dst,
Mul, Flags);
4304 }
else if (Ty ==
F16) {
4306 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4307 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4308 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4309 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4310 .addUse(Ext0.getReg(0))
4311 .addUse(Ext1.getReg(0))
4317 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul, FlagsNoNInf), FlagsNoNInf);
4321 MI.eraseFromParent();
4329 ModSrc = SrcFNeg->getOperand(1).getReg();
4331 ModSrc = SrcFAbs->getOperand(1).getReg();
4333 ModSrc = SrcFAbs->getOperand(1).getReg();
4343 Register OrigSrc =
MI.getOperand(1).getReg();
4344 unsigned Flags =
MI.getFlags();
4346 "this should not have been custom lowered");
4356 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4376 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4378 B.buildFMinNum(Min, Fract, Const, Flags);
4383 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4386 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4387 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4389 MI.eraseFromParent();
4407 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4409 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4410 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4413 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4414 B.buildBitcast(Dst,
Merge);
4416 MI.eraseFromParent();
4433 bool UsePartialMad64_32,
4434 bool SeparateOddAlignedProducts)
const {
4449 auto getZero32 = [&]() ->
Register {
4451 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4454 auto getZero64 = [&]() ->
Register {
4456 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4461 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4472 if (CarryIn.empty())
4475 bool HaveCarryOut =
true;
4477 if (CarryIn.size() == 1) {
4479 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4483 CarryAccum = getZero32();
4485 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4486 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4488 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4493 LocalAccum = getZero32();
4494 HaveCarryOut =
false;
4499 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4500 LocalAccum =
Add.getReg(0);
4514 auto buildMadChain =
4517 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4518 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4525 if (LocalAccum.size() == 1 &&
4526 (!UsePartialMad64_32 || !CarryIn.empty())) {
4529 unsigned j1 = DstIndex - j0;
4530 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4534 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4536 LocalAccum[0] =
Mul.getReg(0);
4538 if (CarryIn.empty()) {
4539 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4542 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4548 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4552 if (j0 <= DstIndex) {
4553 bool HaveSmallAccum =
false;
4556 if (LocalAccum[0]) {
4557 if (LocalAccum.size() == 1) {
4558 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4559 HaveSmallAccum =
true;
4560 }
else if (LocalAccum[1]) {
4561 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4562 HaveSmallAccum =
false;
4564 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4565 HaveSmallAccum =
true;
4568 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4570 HaveSmallAccum =
true;
4574 unsigned j1 = DstIndex - j0;
4575 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4579 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4580 {Src0[j0], Src1[j1], Tmp});
4581 Tmp = Mad.getReg(0);
4582 if (!HaveSmallAccum)
4583 CarryOut.push_back(Mad.getReg(1));
4584 HaveSmallAccum =
false;
4587 }
while (j0 <= DstIndex);
4589 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4590 LocalAccum[0] = Unmerge.getReg(0);
4591 if (LocalAccum.size() > 1)
4592 LocalAccum[1] = Unmerge.getReg(1);
4599 LocalAccum[0] = getZero32();
4603 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4604 "Uninitialized accumulator part");
4630 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4631 Carry OddCarryIn = std::move(OddCarry);
4632 Carry EvenCarryIn = std::move(EvenCarry);
4637 if (2 * i < Accum.
size()) {
4638 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4639 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4644 if (!SeparateOddAlignedProducts) {
4645 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4646 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4648 bool IsHighest = 2 * i >= Accum.
size();
4651 .take_front(IsHighest ? 1 : 2);
4652 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4658 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4660 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4662 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4665 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4668 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4669 Lo->getOperand(1).getReg());
4670 Accum[2 * i] =
Hi.getReg(0);
4671 SeparateOddCarry =
Hi.getReg(1);
4678 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4679 EvenCarryIn.push_back(CarryOut);
4681 if (2 * i < Accum.
size()) {
4682 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4683 OddCarry.push_back(CarryOut);
4695 assert(ST.hasMad64_32());
4696 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4708 unsigned Size = Ty.getSizeInBits();
4709 if (ST.useVMulU64Inst() &&
Size == 64)
4712 unsigned NumParts =
Size / 32;
4724 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4728 for (
unsigned i = 0; i < NumParts; ++i) {
4732 B.buildUnmerge(Src0Parts, Src0);
4733 B.buildUnmerge(Src1Parts, Src1);
4736 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4737 SeparateOddAlignedProducts);
4739 B.buildMergeLikeInstr(DstReg, AccumRegs);
4740 MI.eraseFromParent();
4755 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4756 ? AMDGPU::G_AMDGPU_FFBH_U32
4757 : AMDGPU::G_AMDGPU_FFBL_B32;
4758 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4761 MI.eraseFromParent();
4771 TypeSize NumBits = SrcTy.getSizeInBits();
4776 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4777 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4778 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4779 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4780 B.buildTrunc(Dst, Ctlz);
4781 MI.eraseFromParent();
4792 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4793 unsigned BitWidth = SrcTy.getSizeInBits();
4795 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4796 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4797 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4798 MI.eraseFromParent();
4804 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4807 return ConstVal == -1;
4814 Register CondDef =
MI.getOperand(0).getReg();
4833 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4842 UncondBrTarget = &*NextMBB;
4844 if (
Next->getOpcode() != AMDGPU::G_BR)
4863 *ArgRC,
B.getDebugLoc(), ArgTy);
4867 const unsigned Mask = Arg->
getMask();
4875 auto ShiftAmt =
B.buildConstant(I32, Shift);
4876 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4879 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4881 B.buildCopy(DstReg, LiveIn);
4891 if (!ST.hasClusters()) {
4894 MI.eraseFromParent();
4914 auto One =
B.buildConstant(I32, 1);
4915 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4916 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4917 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4924 B.buildCopy(DstReg, GlobalIdXYZ);
4925 MI.eraseFromParent();
4929 B.buildCopy(DstReg, ClusterIdXYZ);
4930 MI.eraseFromParent();
4935 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4937 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4938 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4940 .addImm(ClusterIdField);
4941 auto Zero =
B.buildConstant(I32, 0);
4944 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4945 MI.eraseFromParent();
4987 auto LoadConstant = [&](
unsigned N) {
4988 B.buildConstant(DstReg,
N);
4992 if (ST.hasArchitectedSGPRs() &&
4999 Arg = &WorkGroupIDX;
5000 ArgRC = &AMDGPU::SReg_32RegClass;
5004 Arg = &WorkGroupIDY;
5005 ArgRC = &AMDGPU::SReg_32RegClass;
5009 Arg = &WorkGroupIDZ;
5010 ArgRC = &AMDGPU::SReg_32RegClass;
5014 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5015 return LoadConstant(0);
5016 Arg = &ClusterWorkGroupIDX;
5017 ArgRC = &AMDGPU::SReg_32RegClass;
5021 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5022 return LoadConstant(0);
5023 Arg = &ClusterWorkGroupIDY;
5024 ArgRC = &AMDGPU::SReg_32RegClass;
5028 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5029 return LoadConstant(0);
5030 Arg = &ClusterWorkGroupIDZ;
5031 ArgRC = &AMDGPU::SReg_32RegClass;
5036 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5037 Arg = &ClusterWorkGroupMaxIDX;
5038 ArgRC = &AMDGPU::SReg_32RegClass;
5043 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5044 Arg = &ClusterWorkGroupMaxIDY;
5045 ArgRC = &AMDGPU::SReg_32RegClass;
5050 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5051 Arg = &ClusterWorkGroupMaxIDZ;
5052 ArgRC = &AMDGPU::SReg_32RegClass;
5056 Arg = &ClusterWorkGroupMaxFlatID;
5057 ArgRC = &AMDGPU::SReg_32RegClass;
5072 return LoadConstant(0);
5077 B.buildUndef(DstReg);
5081 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5093 MI.eraseFromParent();
5099 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5100 MI.eraseFromParent();
5107 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5121 B.buildUndef(DstReg);
5122 MI.eraseFromParent();
5126 if (Arg->isMasked()) {
5140 MI.eraseFromParent();
5155 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5164 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5172 Align Alignment)
const {
5176 "unexpected kernarg parameter type");
5183 MI.eraseFromParent();
5215 auto FloatY =
B.buildUITOFP(
F32,
Y);
5216 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5218 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5219 auto Z =
B.buildFPTOUI(I32, ScaledY);
5222 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5223 auto NegYZ =
B.buildMul(I32, NegY, Z);
5224 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5227 auto Q =
B.buildUMulH(I32,
X, Z);
5228 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5231 auto One =
B.buildConstant(I32, 1);
5234 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5235 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5240 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5243 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5262 auto Unmerge =
B.buildUnmerge(I32, Val);
5264 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5265 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5267 auto Mad =
B.buildFMAD(
5271 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5272 auto Mul1 =
B.buildFMul(
5276 auto Mul2 =
B.buildFMul(
5278 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5281 auto Mad2 =
B.buildFMAD(
5285 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5286 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5288 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5303 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5305 auto Zero64 =
B.buildConstant(I64, 0);
5306 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5308 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5309 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5311 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5312 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5313 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5315 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5316 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5317 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5319 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5320 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5321 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5322 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5323 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5325 auto Zero32 =
B.buildConstant(I32, 0);
5326 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5327 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5328 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5330 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5331 Register NumerLo = UnmergeNumer.getReg(0);
5332 Register NumerHi = UnmergeNumer.getReg(1);
5334 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5335 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5336 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5337 Register Mul3_Lo = UnmergeMul3.getReg(0);
5338 Register Mul3_Hi = UnmergeMul3.getReg(1);
5339 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5340 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5341 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5342 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5344 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5345 Register DenomLo = UnmergeDenom.getReg(0);
5346 Register DenomHi = UnmergeDenom.getReg(1);
5349 auto C1 =
B.buildSExt(I32, CmpHi);
5352 auto C2 =
B.buildSExt(I32, CmpLo);
5355 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5362 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5363 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5364 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5365 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5367 auto One64 =
B.buildConstant(I64, 1);
5368 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5374 auto C6 =
B.buildSelect(
5378 auto Add4 =
B.buildAdd(I64, Add3, One64);
5379 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5381 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5382 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5383 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5389 auto Sel1 =
B.buildSelect(
5396 auto Sel2 =
B.buildSelect(
5407 switch (
MI.getOpcode()) {
5410 case AMDGPU::G_UDIV: {
5411 DstDivReg =
MI.getOperand(0).getReg();
5414 case AMDGPU::G_UREM: {
5415 DstRemReg =
MI.getOperand(0).getReg();
5418 case AMDGPU::G_UDIVREM: {
5419 DstDivReg =
MI.getOperand(0).getReg();
5420 DstRemReg =
MI.getOperand(1).getReg();
5427 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5428 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5429 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5439 MI.eraseFromParent();
5450 if (Ty != I32 && Ty != I64)
5453 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5454 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5455 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5457 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5458 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5459 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5461 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5462 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5464 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5465 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5467 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5468 switch (
MI.getOpcode()) {
5471 case AMDGPU::G_SDIV: {
5472 DstDivReg =
MI.getOperand(0).getReg();
5476 case AMDGPU::G_SREM: {
5477 DstRemReg =
MI.getOperand(0).getReg();
5481 case AMDGPU::G_SDIVREM: {
5482 DstDivReg =
MI.getOperand(0).getReg();
5483 DstRemReg =
MI.getOperand(1).getReg();
5496 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5497 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5498 B.buildSub(DstDivReg, SignXor, Sign);
5502 auto Sign = LHSign.getReg(0);
5503 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5504 B.buildSub(DstRemReg, SignXor, Sign);
5507 MI.eraseFromParent();
5517 uint16_t Flags =
MI.getFlags();
5523 if (!AllowInaccurateRcp && ResTy !=
F16)
5534 if (CLHS->isOne()) {
5535 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5539 MI.eraseFromParent();
5544 if (CLHS->isMinusOne()) {
5545 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5546 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5547 .addUse(FNeg.getReg(0))
5550 MI.eraseFromParent();
5557 if (!AllowInaccurateRcp &&
5562 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5565 B.buildFMul(Res, LHS, RCP, Flags);
5567 MI.eraseFromParent();
5577 uint16_t Flags =
MI.getFlags();
5582 if (!AllowInaccurateRcp)
5590 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5592 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5593 auto One =
B.buildFConstant(ResTy, 1.0);
5595 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5599 R =
B.buildFNeg(ResTy, R);
5601 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5602 R =
B.buildFMA(ResTy, Tmp0, R, R);
5604 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5605 R =
B.buildFMA(ResTy, Tmp1, R, R);
5608 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5609 B.buildCopy(Res, R);
5610 MI.eraseFromParent();
5614 auto Ret =
B.buildFMul(ResTy,
X, R);
5615 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5617 B.buildFMA(Res, Tmp2, R, Ret);
5618 MI.eraseFromParent();
5632 uint16_t Flags =
MI.getFlags();
5649 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5650 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5651 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5652 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5653 .addUse(RHSExt.getReg(0))
5655 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5657 if (ST.hasMadMacF32Insts()) {
5658 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5659 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5660 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5662 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5663 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5664 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5666 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5667 auto TmpInt =
B.buildBitcast(I32, Tmp);
5668 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5669 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5670 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5671 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5672 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5673 .addUse(RDst.getReg(0))
5678 MI.eraseFromParent();
5691 unsigned SPDenormMode =
5694 if (ST.hasDenormModeInst()) {
5696 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5698 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5699 B.buildInstr(AMDGPU::S_DENORM_MODE)
5700 .addImm(NewDenormModeValue);
5703 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5704 .addImm(SPDenormMode)
5721 uint16_t Flags =
MI.getFlags();
5725 auto One =
B.buildFConstant(
F32, 1.0f);
5727 auto DenominatorScaled =
5728 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5733 auto NumeratorScaled =
5734 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5740 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5741 .addUse(DenominatorScaled.getReg(0))
5743 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5746 const bool HasDynamicDenormals =
5751 if (!PreservesDenormals) {
5752 if (HasDynamicDenormals) {
5754 B.buildInstr(AMDGPU::S_GETREG_B32)
5755 .addDef(SavedSPDenormMode)
5761 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5762 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5763 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5764 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5765 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5766 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5768 if (!PreservesDenormals) {
5769 if (HasDynamicDenormals) {
5770 assert(SavedSPDenormMode);
5771 B.buildInstr(AMDGPU::S_SETREG_B32)
5772 .addReg(SavedSPDenormMode)
5778 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5779 .addUse(Fma4.getReg(0))
5780 .addUse(Fma1.getReg(0))
5781 .addUse(Fma3.getReg(0))
5782 .addUse(NumeratorScaled.getReg(1))
5785 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5786 .addUse(Fmas.getReg(0))
5791 MI.eraseFromParent();
5805 uint16_t Flags =
MI.getFlags();
5809 auto One =
B.buildFConstant(
F64, 1.0);
5811 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5817 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5819 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5820 .addUse(DivScale0.getReg(0))
5823 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5824 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5825 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5827 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5833 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5834 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5835 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5838 if (!ST.hasUsableDivScaleConditionOutput()) {
5845 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5846 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5847 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5848 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5851 Scale1Unmerge.getReg(1));
5853 Scale0Unmerge.getReg(1));
5854 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5856 Scale = DivScale1.getReg(1);
5859 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5860 .addUse(Fma4.getReg(0))
5861 .addUse(Fma3.getReg(0))
5862 .addUse(
Mul.getReg(0))
5866 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5867 .addUse(Fmas.getReg(0))
5872 MI.eraseFromParent();
5882 uint16_t Flags =
MI.getFlags();
5887 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5890 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5894 if (ST.hasFractBug()) {
5895 auto Fabs =
B.buildFAbs(Ty, Val);
5899 auto Zero =
B.buildConstant(InstrExpTy, 0);
5900 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5901 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5904 B.buildCopy(Res0, Mant);
5905 B.buildSExtOrTrunc(Res1, Exp);
5907 MI.eraseFromParent();
5917 uint16_t Flags =
MI.getFlags();
5921 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5924 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5925 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5926 auto C2 =
B.buildFConstant(
F32, 1.0f);
5929 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5931 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5933 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5934 .addUse(Mul0.getReg(0))
5937 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5939 B.buildFMul(Res, Sel, Mul1, Flags);
5941 MI.eraseFromParent();
5950 unsigned Flags =
MI.getFlags();
5951 assert(!ST.has16BitInsts());
5952 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5953 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5954 .addUse(Ext.getReg(0))
5956 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5957 MI.eraseFromParent();
5967 const unsigned Flags =
MI.getFlags();
5975 MI.eraseFromParent();
5979 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5981 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5982 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5983 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5988 .addUse(SqrtX.getReg(0))
5991 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5992 auto NegOne =
B.buildConstant(I32, -1);
5993 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5995 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5996 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5998 auto PosOne =
B.buildConstant(I32, 1);
5999 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6001 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6002 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6004 auto Zero =
B.buildFConstant(
F32, 0.0f);
6008 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6012 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6015 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6016 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6018 auto Half =
B.buildFConstant(
F32, 0.5f);
6019 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6020 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6021 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6022 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6023 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6024 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6025 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6026 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6029 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6031 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6033 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6036 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6038 MI.eraseFromParent();
6072 unsigned Flags =
MI.getFlags();
6077 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6079 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6083 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6084 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6085 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6088 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6090 auto Half =
B.buildFConstant(
F64, 0.5);
6091 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6092 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6094 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6095 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6097 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6098 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6100 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6101 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6103 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6105 Register SqrtRet = SqrtS2.getReg(0);
6107 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6108 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6109 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6112 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6113 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6114 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6119 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6122 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6128 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6130 MI.eraseFromParent();
6161 auto Flags =
MI.getFlags();
6173 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6183 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6184 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6189 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6191 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6192 MI.eraseFromParent();
6204 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6205 IID == Intrinsic::amdgcn_permlanex16;
6206 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6207 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6208 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6209 IID == Intrinsic::amdgcn_permlane_up ||
6210 IID == Intrinsic::amdgcn_permlane_down ||
6211 IID == Intrinsic::amdgcn_permlane_xor;
6215 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6217 case Intrinsic::amdgcn_readfirstlane:
6218 case Intrinsic::amdgcn_permlane64:
6219 return LaneOp.getReg(0);
6220 case Intrinsic::amdgcn_readlane:
6221 case Intrinsic::amdgcn_set_inactive:
6222 case Intrinsic::amdgcn_set_inactive_chain_arg:
6223 return LaneOp.addUse(Src1).getReg(0);
6224 case Intrinsic::amdgcn_writelane:
6225 case Intrinsic::amdgcn_permlane_bcast:
6226 case Intrinsic::amdgcn_permlane_up:
6227 case Intrinsic::amdgcn_permlane_down:
6228 case Intrinsic::amdgcn_permlane_xor:
6229 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6230 case Intrinsic::amdgcn_permlane16:
6231 case Intrinsic::amdgcn_permlanex16: {
6233 int64_t Src4 =
MI.getOperand(6).getImm();
6234 int64_t Src5 =
MI.getOperand(7).getImm();
6235 return LaneOp.addUse(Src1)
6242 case Intrinsic::amdgcn_mov_dpp8:
6243 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6244 case Intrinsic::amdgcn_update_dpp:
6245 return LaneOp.addUse(Src1)
6246 .addImm(
MI.getOperand(4).getImm())
6247 .addImm(
MI.getOperand(5).getImm())
6248 .addImm(
MI.getOperand(6).getImm())
6249 .addImm(
MI.getOperand(7).getImm())
6259 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6260 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6261 IsPermlaneShuffle) {
6262 Src1 =
MI.getOperand(3).getReg();
6263 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6264 IsPermlaneShuffle) {
6265 Src2 =
MI.getOperand(4).getReg();
6270 unsigned Size = Ty.getSizeInBits();
6272 unsigned SplitSize = 32;
6273 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6274 ST.hasDPALU_DPP() &&
6278 if (
Size == SplitSize) {
6285 bool IsFloat = Ty.getScalarType().isFloat();
6289 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6291 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6293 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6297 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6299 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6300 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6302 if (IID == Intrinsic::amdgcn_writelane)
6303 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6305 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6307 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6309 B.buildTrunc(DstReg, LaneOpDst);
6310 MI.eraseFromParent();
6314 if (
Size % SplitSize != 0)
6318 bool NeedsBitcast =
false;
6319 if (IntTy.isVector()) {
6322 if (EltSize == SplitSize) {
6323 PartialResTy = EltTy;
6324 }
else if (EltSize == 16 || EltSize == 32) {
6325 unsigned NElem = SplitSize / EltSize;
6328 NeedsBitcast =
true;
6333 unsigned NumParts =
Size / SplitSize;
6337 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6338 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6340 if (IID == Intrinsic::amdgcn_writelane)
6341 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6343 for (
unsigned i = 0; i < NumParts; ++i) {
6344 Src0 = Src0Parts.
getReg(i);
6346 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6347 Src1 = Src1Parts.
getReg(i);
6349 if (IID == Intrinsic::amdgcn_writelane)
6350 Src2 = Src2Parts.
getReg(i);
6352 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6355 if (NeedsBitcast || IsFloat)
6358 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6360 B.buildMergeLikeInstr(DstReg, PartialRes);
6362 MI.eraseFromParent();
6370 ST.getTargetLowering()->getImplicitParameterOffset(
6380 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6381 B.buildConstant(IdxTy,
Offset).getReg(0));
6392 Register Pointer =
MI.getOperand(2).getReg();
6394 Register NumRecords =
MI.getOperand(4).getReg();
6400 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6402 auto ExtStride =
B.buildAnyExt(I32, Stride);
6404 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6405 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6407 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6409 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6413 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6414 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6415 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6416 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6420 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6421 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6422 auto ExtShiftedStride =
6423 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6424 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6425 auto ExtShiftedFlags =
6426 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6427 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6429 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6430 B.buildMergeValues(Result, {LowHalf, HighHalf});
6432 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6433 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6434 auto LowHalf = Unmerge.getReg(0);
6435 auto HighHalf = Unmerge.getReg(1);
6437 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6438 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6439 auto ShiftConst =
B.buildConstant(I32, 16);
6440 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6441 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6442 Register NewHighHalfReg = NewHighHalf.getReg(0);
6443 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6446 MI.eraseFromParent();
6463 MI.eraseFromParent();
6471 std::optional<uint32_t> KnownSize =
6473 if (KnownSize.has_value())
6474 B.buildConstant(DstReg, *KnownSize);
6492 MI.eraseFromParent();
6499 unsigned AddrSpace)
const {
6501 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6505 ST.hasGloballyAddressableScratch()) {
6507 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6508 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6510 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6512 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6514 B.buildConstant(I32, 1u << 26));
6519 MI.eraseFromParent();
6529std::pair<Register, unsigned>
6541 bool CheckNUW = ST.hasGFX1250Insts();
6543 MRI, OrigOffset,
nullptr, CheckNUW);
6547 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6557 unsigned Overflow = ImmOffset & ~MaxImm;
6558 ImmOffset -= Overflow;
6559 if ((int32_t)Overflow < 0) {
6560 Overflow += ImmOffset;
6564 if (Overflow != 0) {
6566 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6568 auto OverflowVal =
B.buildConstant(I32, Overflow);
6569 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6574 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6576 return std::pair(BaseReg, ImmOffset);
6583 bool ImageStore)
const {
6591 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6593 if (ST.hasUnpackedD16VMem()) {
6594 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6597 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6598 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6606 if (ImageStore && ST.hasImageStoreD16Bug()) {
6609 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6611 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6618 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6619 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6621 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6629 auto Unmerge =
B.buildUnmerge(I32, Reg);
6630 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6632 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6642 Reg =
B.buildPadVectorWithUndefElements(
6651 bool IsFormat)
const {
6661 VData =
B.buildBitcast(Ty, VData).getReg(0);
6669 if (Ty.isVector()) {
6670 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6682 bool IsFormat)
const {
6689 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6696 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6697 const Function &Fn =
B.getMF().getFunction();
6699 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6700 MI.eraseFromParent();
6712 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6715 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6719 VIndex =
MI.getOperand(3).getReg();
6722 VIndex =
B.buildConstant(I32, 0).getReg(0);
6725 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6726 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6730 Format =
MI.getOperand(5 + OpOffset).getImm();
6734 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6740 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6741 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6742 }
else if (IsFormat) {
6743 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6744 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6748 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6751 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6754 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6759 auto MIB =
B.buildInstr(
Opc)
6770 MIB.addImm(AuxiliaryData)
6771 .addImm(HasVIndex ? -1 : 0)
6772 .addMemOperand(MMO);
6774 MI.eraseFromParent();
6780 unsigned ImmOffset,
unsigned Format,
6783 auto MIB =
B.buildInstr(
Opc)
6794 MIB.addImm(AuxiliaryData)
6795 .addImm(HasVIndex ? -1 : 0)
6796 .addMemOperand(MMO);
6802 bool IsTyped)
const {
6816 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6817 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6819 StatusDst =
MI.getOperand(1).getReg();
6824 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6827 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6830 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6833 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6836 VIndex =
B.buildConstant(I32, 0).getReg(0);
6839 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6840 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6844 Format =
MI.getOperand(5 + OpOffset).getImm();
6848 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6858 Dst =
MI.getOperand(0).getReg();
6859 B.setInsertPt(
B.getMBB(),
MI);
6866 Dst =
MI.getOperand(0).getReg();
6867 B.setInsertPt(
B.getMBB(),
MI);
6871 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6872 const bool Unpacked = ST.hasUnpackedD16VMem();
6874 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6875 const Function &Fn =
B.getMF().getFunction();
6877 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6880 B.buildUndef(StatusDst);
6881 MI.eraseFromParent();
6893 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6894 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6895 }
else if (IsFormat) {
6899 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6901 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6902 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6907 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6908 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6911 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6912 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6915 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6916 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6922 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6923 unsigned NumLoadDWords = NumValueDWords + 1;
6925 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6927 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6928 bool IsFloat = Ty.getScalarType().isFloat();
6933 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6935 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6936 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6937 B.buildTrunc(DstInt, ExtDst);
6938 }
else if (NumValueDWords == 1) {
6939 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6942 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6943 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6945 B.buildUnmerge(LoadElts, LoadDstReg);
6947 B.buildMergeLikeInstr(DstInt, LoadElts);
6950 B.buildBitcast(Dst, DstInt);
6952 (IsD16 && !Ty.isVector())) {
6953 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6955 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6956 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6957 B.buildTrunc(Dst, LoadDstReg);
6958 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6960 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6962 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6963 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6965 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6967 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6968 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6969 B.buildMergeLikeInstr(Dst, Repack);
6972 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6975 MI.eraseFromParent();
6981 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6982 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6983 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6984 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6985 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6986 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6987 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6988 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6989 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6990 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6991 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6992 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6993 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6994 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6995 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6996 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6997 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6998 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6999 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7000 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7001 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7002 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7003 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7004 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7005 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7006 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7007 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7008 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7009 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7010 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7011 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7012 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7013 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7014 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7015 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7016 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7017 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7018 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7019 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7020 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7021 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7022 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7023 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7024 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7025 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7026 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7027 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7028 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7029 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7030 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7031 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7032 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7033 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7034 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7035 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7036 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7037 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7038 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7039 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7040 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7041 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7042 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7043 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7044 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7045 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7046 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7047 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7048 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7049 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7050 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7051 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7052 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7053 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7054 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7055 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7056 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7057 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7058 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7059 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7060 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7061 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7062 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7063 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7064 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7065 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7066 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7067 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7068 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7069 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7070 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7079 const bool IsCmpSwap =
7080 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7081 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7082 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7083 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7094 CmpVal =
MI.getOperand(3).getReg();
7099 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7100 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7103 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7106 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7112 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7113 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7114 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7133 .addImm(AuxiliaryData)
7134 .addImm(HasVIndex ? -1 : 0)
7135 .addMemOperand(MMO);
7137 MI.eraseFromParent();
7147 bool IsA16,
bool IsG16) {
7161 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7166 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7170 "Bias needs to be converted to 16 bit in A16 mode");
7172 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7176 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7180 if (((
I + 1) >= EndIdx) ||
7187 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7189 B.buildBuildVector(V2EltTy,
7190 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7195 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7206 int DimIdx,
int NumVAddrs) {
7208 for (
int I = 0;
I != NumVAddrs; ++
I) {
7210 if (
SrcOp.isReg()) {
7213 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7214 if (
B.getMRI()->getType(
Reg) != I32)
7215 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7220 int NumAddrRegs = AddrRegs.
size();
7221 if (NumAddrRegs != 1) {
7222 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7225 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7228 for (
int I = 1;
I != NumVAddrs; ++
I) {
7231 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7253 const unsigned NumDefs =
MI.getNumExplicitDefs();
7254 const unsigned ArgOffset = NumDefs + 1;
7255 bool IsTFE = NumDefs == 2;
7273 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7277 const bool IsAtomicPacked16Bit =
7278 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7279 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7286 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7287 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7288 const bool DataTyIs16 =
7289 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7291 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7292 const bool IsA16 = AddrTyIs16;
7293 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7296 if (!BaseOpcode->
Atomic) {
7297 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7300 }
else if (DMask != 0) {
7302 }
else if (!IsTFE && !BaseOpcode->
Store) {
7304 B.buildUndef(
MI.getOperand(0));
7305 MI.eraseFromParent();
7313 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7314 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7315 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7316 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7317 unsigned NewOpcode = LoadOpcode;
7318 if (BaseOpcode->
Store)
7319 NewOpcode = StoreOpcode;
7321 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7324 MI.setDesc(
B.getTII().get(NewOpcode));
7328 if (IsTFE && DMask == 0) {
7331 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7334 if (BaseOpcode->
Atomic) {
7339 if (Ty.isVector() && !IsAtomicPacked16Bit)
7346 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7347 MI.getOperand(2).setReg(
Concat.getReg(0));
7348 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7352 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7355 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7361 if (IsA16 && !ST.hasA16()) {
7366 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7367 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7369 if (IsA16 || IsG16) {
7377 const bool UseNSA = ST.hasNSAEncoding() &&
7378 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7379 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7380 const bool UsePartialNSA =
7381 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7383 if (UsePartialNSA) {
7387 auto Concat =
B.buildConcatVectors(
7388 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7389 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7390 PackedRegs.
resize(NSAMaxSize);
7391 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7393 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7394 PackedRegs[0] =
Concat.getReg(0);
7398 const unsigned NumPacked = PackedRegs.
size();
7401 if (!
SrcOp.isReg()) {
7411 SrcOp.setReg(AMDGPU::NoRegister);
7428 const bool UseNSA = ST.hasNSAEncoding() &&
7429 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7430 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7431 const bool UsePartialNSA =
7432 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7434 if (UsePartialNSA) {
7436 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7438 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7453 if (!Ty.isVector() || !IsD16)
7457 if (RepackedReg != VData) {
7458 MI.getOperand(1).setReg(RepackedReg);
7466 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7469 if (NumElts < DMaskLanes)
7472 if (NumElts > 4 || DMaskLanes > 4)
7483 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7484 const LLT AdjustedTy =
7500 if (IsD16 && ST.hasUnpackedD16VMem()) {
7507 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7508 unsigned RoundedSize = 32 * RoundedElts;
7512 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7517 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7523 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7527 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7528 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7532 MI.getOperand(0).setReg(NewResultReg);
7540 Dst1Reg =
MI.getOperand(1).getReg();
7541 if (MRI->
getType(Dst1Reg) != I32)
7545 MI.removeOperand(1);
7548 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7549 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7550 B.buildBitcast(DstReg, Unmerge.getReg(0));
7551 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7560 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7562 if (ResultNumRegs == 1) {
7564 ResultRegs[0] = NewResultReg;
7567 for (
int I = 0;
I != NumDataRegs; ++
I)
7569 B.buildUnmerge(ResultRegs, NewResultReg);
7574 ResultRegs.
resize(NumDataRegs);
7579 if (IsD16 && !Ty.isVector()) {
7580 B.buildTrunc(DstReg, ResultRegs[0]);
7585 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7586 !ST.hasUnpackedD16VMem()) {
7587 B.buildBitcast(DstReg, ResultRegs[0]);
7599 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7601 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7602 }
else if (ST.hasUnpackedD16VMem()) {
7604 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7608 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7612 for (
int I = 0;
I != NumElts; ++
I)
7619 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7620 B.buildBuildVector(DstReg, ResultRegs);
7624 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7625 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7630 if (Ty == V3I16 || Ty == V3F16) {
7632 if (ResultRegs.
size() == 1) {
7633 NewResultReg = ResultRegs[0];
7634 }
else if (ResultRegs.
size() == 2) {
7636 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7651 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7653 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7655 if (ResizeDst != DstReg)
7656 B.buildBitcast(DstReg, ResizeDst);
7660 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7661 B.buildConcatVectors(DstReg, ResultRegs);
7670 Register OrigDst =
MI.getOperand(0).getReg();
7672 LLT Ty =
B.getMRI()->getType(OrigDst);
7673 unsigned Size = Ty.getSizeInBits();
7675 bool HasMMO = !
MI.memoperands_empty();
7677 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7679 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7680 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7683 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7685 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7694 B.setInsertPt(
B.getMBB(),
MI);
7699 B.setInsertPt(
B.getMBB(),
MI);
7702 MI.setDesc(
B.getTII().get(
Opc));
7703 MI.removeOperand(1);
7709 const unsigned MemSize = (
Size + 7) / 8;
7710 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7717 MI.addMemOperand(MF, MMO);
7719 if (Dst != OrigDst) {
7720 MI.getOperand(0).setReg(Dst);
7721 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7722 B.buildTrunc(OrigDst, Dst);
7744 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7745 MI.removeOperand(0);
7755 if (!ST.hasTrapHandler() ||
7759 return ST.supportsGetDoorbellID() ?
7772 MI.eraseFromParent();
7782 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7784 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7788 MI.eraseFromParent();
7797 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7804 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7824 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7827 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7828 B.buildCopy(SGPR01, Temp);
7829 B.buildInstr(AMDGPU::S_TRAP)
7832 MI.eraseFromParent();
7843 B.buildCopy(SGPR01, LiveIn);
7844 B.buildInstr(AMDGPU::S_TRAP)
7848 MI.eraseFromParent();
7857 if (ST.hasPrivEnabledTrap2NopBug()) {
7858 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7860 MI.eraseFromParent();
7864 B.buildInstr(AMDGPU::S_TRAP)
7866 MI.eraseFromParent();
7875 if (!ST.hasTrapHandler() ||
7879 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7882 B.buildInstr(AMDGPU::S_TRAP)
7886 MI.eraseFromParent();
7900 Register NodePtr =
MI.getOperand(2).getReg();
7901 Register RayExtent =
MI.getOperand(3).getReg();
7902 Register RayOrigin =
MI.getOperand(4).getReg();
7904 Register RayInvDir =
MI.getOperand(6).getReg();
7907 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7914 const unsigned NumVDataDwords = 4;
7915 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7916 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7918 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7920 const unsigned BaseOpcodes[2][2] = {
7921 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7922 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7923 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7927 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7928 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7929 : AMDGPU::MIMGEncGfx10NSA,
7930 NumVDataDwords, NumVAddrDwords);
7934 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7935 : AMDGPU::MIMGEncGfx10Default,
7936 NumVDataDwords, NumVAddrDwords);
7941 if (UseNSA && IsGFX11Plus) {
7942 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7943 auto SrcInt =
B.buildBitcast(V3I32, Src);
7944 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7945 auto Merged =
B.buildMergeLikeInstr(
7946 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7947 Ops.push_back(Merged.getReg(0));
7950 Ops.push_back(NodePtr);
7951 Ops.push_back(RayExtent);
7952 packLanes(RayOrigin);
7955 auto UnmergeRayDir =
7956 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7957 auto UnmergeRayInvDir =
7958 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7959 auto MergedDir =
B.buildMergeLikeInstr(
7962 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7963 UnmergeRayDir.getReg(0)}))
7966 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7967 UnmergeRayDir.getReg(1)}))
7970 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7971 UnmergeRayDir.getReg(2)}))
7973 Ops.push_back(MergedDir.getReg(0));
7976 packLanes(RayInvDir);
7980 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7981 Ops.push_back(Unmerge.getReg(0));
7982 Ops.push_back(Unmerge.getReg(1));
7984 Ops.push_back(NodePtr);
7986 Ops.push_back(RayExtent);
7988 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7989 auto SrcInt =
B.buildBitcast(V3I32, Src);
7990 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7991 Ops.push_back(Unmerge.getReg(0));
7992 Ops.push_back(Unmerge.getReg(1));
7993 Ops.push_back(Unmerge.getReg(2));
7996 packLanes(RayOrigin);
7998 auto UnmergeRayDir =
7999 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8000 auto UnmergeRayInvDir =
8001 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8005 B.buildMergeLikeInstr(R1,
8006 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8007 B.buildMergeLikeInstr(
8008 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8009 B.buildMergeLikeInstr(
8010 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8016 packLanes(RayInvDir);
8025 Ops.push_back(MergedOps);
8028 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8037 .addImm(IsA16 ? 1 : 0)
8040 MI.eraseFromParent();
8050 Register DstOrigin =
MI.getOperand(1).getReg();
8052 Register NodePtr =
MI.getOperand(4).getReg();
8053 Register RayExtent =
MI.getOperand(5).getReg();
8054 Register InstanceMask =
MI.getOperand(6).getReg();
8055 Register RayOrigin =
MI.getOperand(7).getReg();
8057 Register Offsets =
MI.getOperand(9).getReg();
8058 Register TDescr =
MI.getOperand(10).getReg();
8061 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8062 const unsigned NumVDataDwords = 10;
8063 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8065 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8066 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8067 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8070 auto RayExtentInstanceMaskVec =
8071 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8072 B.buildAnyExt(I32, InstanceMask)});
8074 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8075 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8081 .addUse(RayExtentInstanceMaskVec.getReg(0))
8088 MI.eraseFromParent();
8097 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8098 MI.eraseFromParent();
8105 if (!ST.hasArchitectedSGPRs())
8109 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8110 auto LSB =
B.buildConstant(I32, 25);
8111 auto Width =
B.buildConstant(I32, 5);
8112 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8113 MI.eraseFromParent();
8121 unsigned Width)
const {
8125 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8126 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8129 MI.eraseFromParent();
8149 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8153 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8156 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8157 MI.eraseFromParent();
8170 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8174 .addReg(Unmerge.getReg(0));
8178 .addReg(Unmerge.getReg(1));
8179 MI.eraseFromParent();
8191 case Intrinsic::sponentry:
8197 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8200 B.buildIntToPtr(DstReg, TmpReg);
8201 MI.eraseFromParent();
8203 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8205 B.buildFrameIndex(
MI.getOperand(0), FI);
8206 MI.eraseFromParent();
8209 case Intrinsic::amdgcn_if:
8210 case Intrinsic::amdgcn_else: {
8213 bool Negated =
false;
8225 std::swap(CondBrTarget, UncondBrTarget);
8227 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8228 if (IntrID == Intrinsic::amdgcn_if) {
8229 B.buildInstr(AMDGPU::SI_IF)
8232 .addMBB(UncondBrTarget);
8234 B.buildInstr(AMDGPU::SI_ELSE)
8237 .addMBB(UncondBrTarget);
8246 B.buildBr(*CondBrTarget);
8251 MI.eraseFromParent();
8252 BrCond->eraseFromParent();
8258 case Intrinsic::amdgcn_loop: {
8261 bool Negated =
false;
8271 std::swap(CondBrTarget, UncondBrTarget);
8273 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8274 B.buildInstr(AMDGPU::SI_LOOP)
8276 .addMBB(UncondBrTarget);
8281 B.buildBr(*CondBrTarget);
8283 MI.eraseFromParent();
8284 BrCond->eraseFromParent();
8291 case Intrinsic::amdgcn_wave_reduce_min:
8292 case Intrinsic::amdgcn_wave_reduce_umin:
8293 case Intrinsic::amdgcn_wave_reduce_fmin:
8294 case Intrinsic::amdgcn_wave_reduce_max:
8295 case Intrinsic::amdgcn_wave_reduce_umax:
8296 case Intrinsic::amdgcn_wave_reduce_fmax:
8297 case Intrinsic::amdgcn_wave_reduce_add:
8298 case Intrinsic::amdgcn_wave_reduce_fadd:
8299 case Intrinsic::amdgcn_wave_reduce_sub:
8300 case Intrinsic::amdgcn_wave_reduce_fsub:
8301 case Intrinsic::amdgcn_wave_reduce_and:
8302 case Intrinsic::amdgcn_wave_reduce_or:
8303 case Intrinsic::amdgcn_wave_reduce_xor: {
8308 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8309 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8310 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8311 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8312 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8313 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8314 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8315 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8316 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8323 .addUse(Ext.getReg(0))
8324 .addImm(
MI.getOperand(3).getImm());
8326 B.buildFPTrunc(DstReg, NewDst);
8328 B.buildTrunc(DstReg, NewDst);
8329 MI.eraseFromParent();
8332 case Intrinsic::amdgcn_addrspacecast_nonnull:
8334 case Intrinsic::amdgcn_make_buffer_rsrc:
8336 case Intrinsic::amdgcn_kernarg_segment_ptr:
8339 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8340 MI.eraseFromParent();
8346 case Intrinsic::amdgcn_implicitarg_ptr:
8348 case Intrinsic::amdgcn_workitem_id_x:
8351 case Intrinsic::amdgcn_workitem_id_y:
8354 case Intrinsic::amdgcn_workitem_id_z:
8357 case Intrinsic::amdgcn_workgroup_id_x:
8362 case Intrinsic::amdgcn_workgroup_id_y:
8367 case Intrinsic::amdgcn_workgroup_id_z:
8372 case Intrinsic::amdgcn_cluster_id_x:
8373 return ST.hasClusters() &&
8376 case Intrinsic::amdgcn_cluster_id_y:
8377 return ST.hasClusters() &&
8380 case Intrinsic::amdgcn_cluster_id_z:
8381 return ST.hasClusters() &&
8384 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8385 return ST.hasClusters() &&
8388 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8389 return ST.hasClusters() &&
8392 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8393 return ST.hasClusters() &&
8396 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8397 return ST.hasClusters() &&
8399 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8400 return ST.hasClusters() &&
8403 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8404 return ST.hasClusters() &&
8407 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8408 return ST.hasClusters() &&
8411 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8412 return ST.hasClusters() &&
8416 case Intrinsic::amdgcn_wave_id:
8418 case Intrinsic::amdgcn_lds_kernel_id:
8421 case Intrinsic::amdgcn_dispatch_ptr:
8424 case Intrinsic::amdgcn_queue_ptr:
8427 case Intrinsic::amdgcn_implicit_buffer_ptr:
8430 case Intrinsic::amdgcn_dispatch_id:
8433 case Intrinsic::r600_read_ngroups_x:
8437 case Intrinsic::r600_read_ngroups_y:
8440 case Intrinsic::r600_read_ngroups_z:
8443 case Intrinsic::r600_read_local_size_x:
8446 case Intrinsic::r600_read_local_size_y:
8450 case Intrinsic::r600_read_local_size_z:
8453 case Intrinsic::amdgcn_fdiv_fast:
8455 case Intrinsic::amdgcn_is_shared:
8457 case Intrinsic::amdgcn_is_private:
8459 case Intrinsic::amdgcn_wavefrontsize: {
8460 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8461 MI.eraseFromParent();
8464 case Intrinsic::amdgcn_s_buffer_load:
8465 case Intrinsic::amdgcn_ptr_s_buffer_load:
8467 case Intrinsic::amdgcn_raw_buffer_store:
8468 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8469 case Intrinsic::amdgcn_struct_buffer_store:
8470 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8472 case Intrinsic::amdgcn_raw_buffer_store_format:
8473 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8474 case Intrinsic::amdgcn_struct_buffer_store_format:
8475 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8477 case Intrinsic::amdgcn_raw_tbuffer_store:
8478 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8479 case Intrinsic::amdgcn_struct_tbuffer_store:
8480 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8482 case Intrinsic::amdgcn_raw_buffer_load:
8483 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8484 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8485 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8486 case Intrinsic::amdgcn_struct_buffer_load:
8487 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8488 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8489 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8491 case Intrinsic::amdgcn_raw_buffer_load_format:
8492 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8493 case Intrinsic::amdgcn_struct_buffer_load_format:
8494 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8496 case Intrinsic::amdgcn_raw_tbuffer_load:
8497 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8498 case Intrinsic::amdgcn_struct_tbuffer_load:
8499 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8501 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8502 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8503 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8504 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8505 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8506 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8507 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8508 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8509 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8510 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8511 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8512 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8513 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8514 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8515 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8516 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8517 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8518 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8519 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8520 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8521 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8522 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8523 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8524 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8525 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8526 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8527 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8528 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8529 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8530 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8531 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8532 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8533 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8534 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8535 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8536 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8537 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8538 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8539 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8540 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8541 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8542 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8543 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8544 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8545 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8546 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8547 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8548 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8549 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8550 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8551 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8552 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8553 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8554 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8555 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8556 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8557 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8558 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8559 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8560 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8561 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8562 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8563 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8564 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8565 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8566 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8567 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8568 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8569 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8570 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8571 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8572 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8574 case Intrinsic::amdgcn_rsq_clamp:
8576 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8578 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8579 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8581 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8582 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8583 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8584 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8585 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8586 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8587 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8588 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8592 if (IndexArgTy != I64) {
8593 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8594 :
B.buildAnyExt(I64, Index);
8595 MI.getOperand(5).setReg(NewIndex.getReg(0));
8599 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8600 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8601 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8602 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8603 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8604 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8605 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8606 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8609 if (MRI.
getType(Index) != I32)
8610 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8613 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8614 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8615 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8616 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8617 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8618 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8619 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8620 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8621 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8623 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8627 if (IndexArgTy != IdxTy) {
8628 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8629 :
B.buildAnyExt(IdxTy, Index);
8630 MI.getOperand(7).setReg(NewIndex.getReg(0));
8635 case Intrinsic::amdgcn_fmed3: {
8641 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8642 MI.removeOperand(1);
8646 case Intrinsic::amdgcn_readlane:
8647 case Intrinsic::amdgcn_writelane:
8648 case Intrinsic::amdgcn_readfirstlane:
8649 case Intrinsic::amdgcn_permlane16:
8650 case Intrinsic::amdgcn_permlanex16:
8651 case Intrinsic::amdgcn_permlane64:
8652 case Intrinsic::amdgcn_set_inactive:
8653 case Intrinsic::amdgcn_set_inactive_chain_arg:
8654 case Intrinsic::amdgcn_mov_dpp8:
8655 case Intrinsic::amdgcn_update_dpp:
8656 case Intrinsic::amdgcn_permlane_bcast:
8657 case Intrinsic::amdgcn_permlane_up:
8658 case Intrinsic::amdgcn_permlane_down:
8659 case Intrinsic::amdgcn_permlane_xor:
8661 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8663 case Intrinsic::amdgcn_dead: {
8667 MI.eraseFromParent();
8670 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8671 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8672 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8673 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8674 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8675 MI.eraseFromParent();
8677 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8678 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8679 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8680 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8681 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8682 MI.eraseFromParent();
8684 case Intrinsic::amdgcn_av_load_b128:
8685 case Intrinsic::amdgcn_av_store_b128: {
8686 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8687 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8688 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8690 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8691 **
MI.memoperands_begin());
8692 MI.eraseFromParent();
8695 case Intrinsic::amdgcn_flat_load_monitor_b32:
8696 case Intrinsic::amdgcn_flat_load_monitor_b64:
8697 case Intrinsic::amdgcn_flat_load_monitor_b128:
8698 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8699 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8700 .add(
MI.getOperand(0))
8701 .add(
MI.getOperand(2))
8702 .addMemOperand(*
MI.memoperands_begin());
8703 MI.eraseFromParent();
8705 case Intrinsic::amdgcn_global_load_monitor_b32:
8706 case Intrinsic::amdgcn_global_load_monitor_b64:
8707 case Intrinsic::amdgcn_global_load_monitor_b128:
8708 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8709 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8710 .add(
MI.getOperand(0))
8711 .add(
MI.getOperand(2))
8712 .addMemOperand(*
MI.memoperands_begin());
8713 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFPow(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void truncate(size_type N)
Like resize, but requires that N is less than size().
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
unsigned getPointerSizeInBits(unsigned AS) const
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ 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.