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();
2536 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2545 unsigned SrcAS = SrcTy.getAddressSpace();
2559 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2566 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2568 ST.hasGloballyAddressableScratch()) {
2571 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2573 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2574 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2576 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2577 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2578 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2582 return B.buildExtract(Dst, Src, 0).getReg(0);
2586 castFlatToLocalOrPrivate(Dst);
2587 MI.eraseFromParent();
2593 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2594 auto FlatNull =
B.buildConstant(SrcTy, 0);
2597 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2601 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2603 MI.eraseFromParent();
2610 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2613 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2616 ST.hasGloballyAddressableScratch()) {
2620 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2621 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2625 if (ST.isWave64()) {
2626 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2632 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2633 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2635 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2639 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2640 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2642 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2643 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2652 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2656 castLocalOrPrivateToFlat(Dst);
2657 MI.eraseFromParent();
2661 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2668 SegmentNull.getReg(0));
2670 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2672 MI.eraseFromParent();
2677 SrcTy.getSizeInBits() == 64) {
2679 B.buildExtract(Dst, Src, 0);
2680 MI.eraseFromParent();
2687 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2688 auto PtrLo =
B.buildPtrToInt(I32, Src);
2689 if (AddrHiVal == 0) {
2690 auto Zext =
B.buildZExt(I64, PtrLo);
2691 B.buildIntToPtr(Dst, Zext);
2693 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2694 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2697 MI.eraseFromParent();
2704 MI.eraseFromParent();
2713 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2718 auto C1 =
B.buildFConstant(Ty, C1Val);
2719 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2722 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2723 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2725 auto C2 =
B.buildFConstant(Ty, C2Val);
2726 auto Fabs =
B.buildFAbs(Ty, Src);
2729 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2730 MI.eraseFromParent();
2747 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2749 const auto Zero =
B.buildFConstant(
F64, 0.0);
2750 const auto One =
B.buildFConstant(
F64, 1.0);
2753 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2754 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2757 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2758 MI.eraseFromParent();
2766 Register Src0Reg =
MI.getOperand(1).getReg();
2767 Register Src1Reg =
MI.getOperand(2).getReg();
2768 auto Flags =
MI.getFlags();
2771 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2772 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2773 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2774 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2775 MI.eraseFromParent();
2781 const unsigned FractBits = 52;
2782 const unsigned ExpBits = 11;
2785 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2786 auto Const1 =
B.buildConstant(I32, ExpBits);
2788 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2790 .addUse(Const0.getReg(0))
2791 .addUse(Const1.getReg(0));
2793 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2806 auto SrcInt =
B.buildBitcast(I64, Src);
2809 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2816 const unsigned FractBits = 52;
2819 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2820 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2822 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2824 const auto Zero32 =
B.buildConstant(I32, 0);
2827 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2829 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2830 auto Not =
B.buildNot(I64, Shr);
2831 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2832 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2837 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2838 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2839 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2840 MI.eraseFromParent();
2856 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2857 auto ThirtyTwo =
B.buildConstant(I32, 32);
2860 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2861 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2863 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2864 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2867 B.buildFAdd(Dst, LdExp, CvtLo);
2868 MI.eraseFromParent();
2874 auto One =
B.buildConstant(I32, 1);
2878 auto ThirtyOne =
B.buildConstant(I32, 31);
2879 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2880 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2881 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2882 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2883 .addUse(Unmerge.getReg(1));
2884 auto LS2 =
B.buildSub(I32, LS, One);
2885 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2887 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2888 auto Norm =
B.buildShl(I64, Src, ShAmt);
2889 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2890 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2891 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2892 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2893 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2894 B.buildFLdexp(Dst, FVal, Scale);
2895 MI.eraseFromParent();
2915 unsigned Flags =
MI.getFlags();
2926 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2934 auto SrcInt =
B.buildBitcast(I32, Src);
2935 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2936 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2940 K0 =
B.buildFConstant(
2942 K1 =
B.buildFConstant(
2945 K0 =
B.buildFConstant(
2947 K1 =
B.buildFConstant(
2951 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2952 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2953 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2955 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2956 :
B.buildFPTOUI(I32, FloorMul);
2957 auto Lo =
B.buildFPTOUI(I32, Fma);
2961 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2963 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2966 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2967 MI.eraseFromParent();
2990 uint64_t
Offset =
MI.getOperand(2).getImm();
2999 unsigned StartIdx =
Offset / 32;
3003 if (DstCount == 1) {
3005 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3010 for (
unsigned I = 0;
I < DstCount; ++
I)
3011 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3012 B.buildMergeLikeInstr(DstReg, MergeVec);
3015 MI.eraseFromParent();
3025 Register InsertSrc =
MI.getOperand(2).getReg();
3026 uint64_t
Offset =
MI.getOperand(3).getImm();
3034 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3038 unsigned DstCount = DstSize / 32;
3039 unsigned InsertCount = InsertSize / 32;
3040 unsigned StartIdx =
Offset / 32;
3042 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3045 for (
unsigned I = 0;
I < StartIdx; ++
I)
3048 if (InsertCount == 1) {
3052 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3055 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3056 for (
unsigned I = 0;
I < InsertCount; ++
I)
3060 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3063 B.buildMergeLikeInstr(DstReg, MergeVec);
3065 MI.eraseFromParent();
3092 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3093 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3094 B.buildIntToPtr(Dst, IntElt);
3096 MI.eraseFromParent();
3103 std::optional<ValueAndVReg> MaybeIdxVal =
3107 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3110 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3111 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3116 MI.eraseFromParent();
3145 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3146 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3147 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3149 B.buildIntToPtr(Dst, IntVecDest);
3150 MI.eraseFromParent();
3157 std::optional<ValueAndVReg> MaybeIdxVal =
3162 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3165 if (IdxVal < NumElts) {
3167 for (
unsigned i = 0; i < NumElts; ++i)
3169 B.buildUnmerge(SrcRegs, Vec);
3171 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3172 B.buildMergeLikeInstr(Dst, SrcRegs);
3177 MI.eraseFromParent();
3188 unsigned Flags =
MI.getFlags();
3192 if (ST.hasTrigReducedRange()) {
3193 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3194 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3195 .addUse(MulVal.getReg(0))
3199 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3202 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3206 MI.eraseFromParent();
3214 unsigned GAFlags)
const {
3243 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3245 if (ST.has64BitLiterals()) {
3249 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3253 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3262 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3263 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3266 B.buildExtract(DstReg, PCReg, 0);
3276 if (RequiresHighHalf && ST.has64BitLiterals()) {
3278 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3279 B.buildInstr(AMDGPU::S_MOV_B64)
3294 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3297 B.buildInstr(AMDGPU::S_MOV_B32)
3302 if (RequiresHighHalf) {
3304 "Must provide a 64-bit pointer type!");
3307 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3309 B.buildInstr(AMDGPU::S_MOV_B32)
3320 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3322 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3326 if (AddrDst != DstReg)
3327 B.buildCast(DstReg, AddrDst);
3328 }
else if (AddrLo != DstReg) {
3331 B.buildCast(DstReg, AddrLo);
3340 unsigned AS = Ty.getAddressSpace();
3348 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3352 Fn,
"local memory global used by non-kernel function",
3361 B.buildUndef(DstReg);
3362 MI.eraseFromParent();
3386 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3387 B.buildIntToPtr(DstReg, Sz);
3388 MI.eraseFromParent();
3394 MI.eraseFromParent();
3398 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3400 MI.eraseFromParent();
3408 MI.eraseFromParent();
3414 MI.eraseFromParent();
3430 if (Ty.getSizeInBits() == 32) {
3432 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3433 B.buildExtract(DstReg,
Load, 0);
3435 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3437 MI.eraseFromParent();
3460 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3462 MI.getOperand(1).setReg(Cast.getReg(0));
3467 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3485 const uint64_t AlignInBits = 8 * MemAlign.
value();
3493 if (WideMemSize == ValSize) {
3499 MI.setMemRefs(MF, {WideMMO});
3505 if (ValSize > WideMemSize)
3512 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3513 B.buildTrunc(ValReg, WideLoad).getReg(0);
3520 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3521 B.buildExtract(ValReg, WideLoad, 0);
3525 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3526 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3530 MI.eraseFromParent();
3543 Register DataReg =
MI.getOperand(0).getReg();
3588 "this should not have been custom lowered");
3593 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3595 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3599 .setMemRefs(
MI.memoperands());
3601 MI.eraseFromParent();
3609 switch (
DefMI->getOpcode()) {
3610 case TargetOpcode::G_INTRINSIC: {
3612 case Intrinsic::amdgcn_frexp_mant:
3613 case Intrinsic::amdgcn_log:
3614 case Intrinsic::amdgcn_log_clamp:
3615 case Intrinsic::amdgcn_exp2:
3616 case Intrinsic::amdgcn_sqrt:
3624 case TargetOpcode::G_FSQRT:
3626 case TargetOpcode::G_FFREXP: {
3627 if (
DefMI->getOperand(0).getReg() == Src)
3631 case TargetOpcode::G_FPEXT: {
3652std::pair<Register, Register>
3654 unsigned Flags)
const {
3658 auto SmallestNormal =
B.buildFConstant(
3660 auto IsLtSmallestNormal =
3663 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3664 auto One =
B.buildFConstant(
F32, 1.0);
3666 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3667 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3669 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3682 LLT Ty =
B.getMRI()->getType(Dst);
3683 unsigned Flags =
MI.getFlags();
3687 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3688 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3689 .addUse(Ext.getReg(0))
3691 B.buildFPTrunc(Dst,
Log2, Flags);
3692 MI.eraseFromParent();
3700 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3703 MI.eraseFromParent();
3707 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3708 .addUse(ScaledInput)
3711 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3712 auto Zero =
B.buildFConstant(Ty, 0.0);
3714 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3715 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3717 MI.eraseFromParent();
3723 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3724 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3729 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3730 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3735 unsigned Flags =
MI.getFlags();
3745 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3747 B.buildFPTrunc(Dst, LogVal, Flags);
3752 MI.eraseFromParent();
3761 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3764 if (ST.hasFastFMAF32()) {
3766 const float c_log10 = 0x1.344134p-2f;
3767 const float cc_log10 = 0x1.09f79ep-26f;
3770 const float c_log = 0x1.62e42ep-1f;
3771 const float cc_log = 0x1.efa39ep-25f;
3773 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3774 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3778 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3779 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3780 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3781 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3782 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3785 const float ch_log10 = 0x1.344000p-2f;
3786 const float ct_log10 = 0x1.3509f6p-18f;
3789 const float ch_log = 0x1.62e000p-1f;
3790 const float ct_log = 0x1.0bfbe8p-15f;
3792 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3793 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3796 auto YInt =
B.buildBitcast(I32,
Y);
3797 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3798 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3799 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3803 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3806 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3808 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3811 const bool IsFiniteOnly =
3814 if (!IsFiniteOnly) {
3817 auto Fabs =
B.buildFAbs(Ty,
Y);
3820 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3824 auto Zero =
B.buildFConstant(Ty, 0.0);
3826 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3827 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3828 B.buildFSub(Dst, R, Shift, Flags);
3830 B.buildCopy(Dst, R);
3833 MI.eraseFromParent();
3839 unsigned Flags)
const {
3840 const double Log2BaseInverted =
3843 LLT Ty =
B.getMRI()->getType(Dst);
3848 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3849 .addUse(ScaledInput)
3851 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3852 auto Zero =
B.buildFConstant(Ty, 0.0);
3854 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3855 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3857 if (ST.hasFastFMAF32())
3858 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3860 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3861 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3868 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3869 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3872 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3873 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3884 unsigned Flags =
MI.getFlags();
3885 LLT Ty =
B.getMRI()->getType(Dst);
3892 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3893 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3894 .addUse(Ext.getReg(0))
3896 B.buildFPTrunc(Dst,
Log2, Flags);
3897 MI.eraseFromParent();
3907 MI.eraseFromParent();
3915 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3917 RangeCheckConst, Flags);
3919 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3920 auto Zero =
B.buildFConstant(Ty, 0.0);
3921 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3922 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3924 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3925 .addUse(AddInput.getReg(0))
3928 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3929 auto One =
B.buildFConstant(Ty, 1.0);
3930 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3931 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3932 MI.eraseFromParent();
3937 const SrcOp &Src,
unsigned Flags) {
3938 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3941 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3942 .addUse(Src.getReg())
3945 return B.buildFExp2(Dst, Src, Flags);
3951 bool IsExp10)
const {
3952 LLT Ty =
B.getMRI()->getType(
X);
3956 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3957 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3964 LLT Ty =
B.getMRI()->getType(Dst);
3970 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3973 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3974 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3975 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3978 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3980 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3981 .addUse(ExpInput.getReg(0))
3984 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3985 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3986 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3992 unsigned Flags)
const {
3993 LLT Ty =
B.getMRI()->getType(Dst);
3997 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
3998 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4000 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4001 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4002 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4003 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4004 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4014 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4018 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4019 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4020 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4022 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4023 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4025 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4026 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4027 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4028 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4030 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4031 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4032 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4034 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4052 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4054 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4056 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4058 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4059 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4060 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4061 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4063 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4064 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4065 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4066 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4068 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4069 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4070 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4071 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4072 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4074 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4075 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4076 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4077 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4080 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4081 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4082 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4084 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4085 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4086 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4087 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4088 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4092 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4093 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4095 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4097 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4099 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4101 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4103 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4104 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4105 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4106 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4108 auto One =
B.buildFConstant(
F64, 1.0);
4109 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4110 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4113 auto DnInt =
B.buildFPTOSI(I32, Dn);
4114 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4121 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4128 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4130 MI.eraseFromParent();
4138 const unsigned Flags =
MI.getFlags();
4146 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4154 MI.eraseFromParent();
4165 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4168 B.buildFPTrunc(Dst, Lowered, Flags);
4169 MI.eraseFromParent();
4180 MI.eraseFromParent();
4208 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4211 if (ST.hasFastFMAF32()) {
4213 const float cc_exp = 0x1.4ae0bep-26f;
4214 const float c_exp10 = 0x1.a934f0p+1f;
4215 const float cc_exp10 = 0x1.2f346ep-24f;
4217 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4218 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4219 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4220 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4222 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4223 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4225 const float ch_exp = 0x1.714000p+0f;
4226 const float cl_exp = 0x1.47652ap-12f;
4228 const float ch_exp10 = 0x1.a92000p+1f;
4229 const float cl_exp10 = 0x1.4f0978p-11f;
4232 auto XInt =
B.buildBitcast(I32,
X);
4233 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4234 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4235 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4237 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4238 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4240 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4241 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4244 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4245 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4248 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4251 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4252 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4254 auto IntE =
B.buildFPTOSI(I32, E);
4256 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4257 .addUse(
A.getReg(0))
4259 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4261 auto UnderflowCheckConst =
4262 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4263 auto Zero =
B.buildFConstant(Ty, 0.0);
4267 R =
B.buildSelect(Ty, Underflow, Zero, R);
4270 auto OverflowCheckConst =
4271 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4276 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4279 B.buildCopy(Dst, R);
4280 MI.eraseFromParent();
4289 unsigned Flags =
MI.getFlags();
4290 LLT Ty =
B.getMRI()->getType(Dst);
4293 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4294 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4295 .addUse(Log.getReg(0))
4298 B.buildFExp2(Dst,
Mul, Flags);
4299 }
else if (Ty ==
F16) {
4301 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4302 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4303 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4304 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4305 .addUse(Ext0.getReg(0))
4306 .addUse(Ext1.getReg(0))
4312 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul, FlagsNoNInf), FlagsNoNInf);
4316 MI.eraseFromParent();
4324 ModSrc = SrcFNeg->getOperand(1).getReg();
4326 ModSrc = SrcFAbs->getOperand(1).getReg();
4328 ModSrc = SrcFAbs->getOperand(1).getReg();
4338 Register OrigSrc =
MI.getOperand(1).getReg();
4339 unsigned Flags =
MI.getFlags();
4341 "this should not have been custom lowered");
4351 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4371 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4373 B.buildFMinNum(Min, Fract, Const, Flags);
4378 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4381 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4382 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4384 MI.eraseFromParent();
4402 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4404 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4405 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4408 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4409 B.buildBitcast(Dst,
Merge);
4411 MI.eraseFromParent();
4428 bool UsePartialMad64_32,
4429 bool SeparateOddAlignedProducts)
const {
4444 auto getZero32 = [&]() ->
Register {
4446 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4449 auto getZero64 = [&]() ->
Register {
4451 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4456 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4467 if (CarryIn.empty())
4470 bool HaveCarryOut =
true;
4472 if (CarryIn.size() == 1) {
4474 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4478 CarryAccum = getZero32();
4480 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4481 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4483 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4488 LocalAccum = getZero32();
4489 HaveCarryOut =
false;
4494 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4495 LocalAccum =
Add.getReg(0);
4509 auto buildMadChain =
4512 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4513 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4520 if (LocalAccum.size() == 1 &&
4521 (!UsePartialMad64_32 || !CarryIn.empty())) {
4524 unsigned j1 = DstIndex - j0;
4525 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4529 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4531 LocalAccum[0] =
Mul.getReg(0);
4533 if (CarryIn.empty()) {
4534 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4537 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4543 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4547 if (j0 <= DstIndex) {
4548 bool HaveSmallAccum =
false;
4551 if (LocalAccum[0]) {
4552 if (LocalAccum.size() == 1) {
4553 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4554 HaveSmallAccum =
true;
4555 }
else if (LocalAccum[1]) {
4556 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4557 HaveSmallAccum =
false;
4559 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4560 HaveSmallAccum =
true;
4563 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4565 HaveSmallAccum =
true;
4569 unsigned j1 = DstIndex - j0;
4570 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4574 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4575 {Src0[j0], Src1[j1], Tmp});
4576 Tmp = Mad.getReg(0);
4577 if (!HaveSmallAccum)
4578 CarryOut.push_back(Mad.getReg(1));
4579 HaveSmallAccum =
false;
4582 }
while (j0 <= DstIndex);
4584 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4585 LocalAccum[0] = Unmerge.getReg(0);
4586 if (LocalAccum.size() > 1)
4587 LocalAccum[1] = Unmerge.getReg(1);
4594 LocalAccum[0] = getZero32();
4598 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4599 "Uninitialized accumulator part");
4625 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4626 Carry OddCarryIn = std::move(OddCarry);
4627 Carry EvenCarryIn = std::move(EvenCarry);
4632 if (2 * i < Accum.
size()) {
4633 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4634 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4639 if (!SeparateOddAlignedProducts) {
4640 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4641 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4643 bool IsHighest = 2 * i >= Accum.
size();
4646 .take_front(IsHighest ? 1 : 2);
4647 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4653 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4655 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4657 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4660 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4663 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4664 Lo->getOperand(1).getReg());
4665 Accum[2 * i] =
Hi.getReg(0);
4666 SeparateOddCarry =
Hi.getReg(1);
4673 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4674 EvenCarryIn.push_back(CarryOut);
4676 if (2 * i < Accum.
size()) {
4677 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4678 OddCarry.push_back(CarryOut);
4690 assert(ST.hasMad64_32());
4691 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4703 unsigned Size = Ty.getSizeInBits();
4704 if (ST.useVMulU64Inst() &&
Size == 64)
4707 unsigned NumParts =
Size / 32;
4719 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4723 for (
unsigned i = 0; i < NumParts; ++i) {
4727 B.buildUnmerge(Src0Parts, Src0);
4728 B.buildUnmerge(Src1Parts, Src1);
4731 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4732 SeparateOddAlignedProducts);
4734 B.buildMergeLikeInstr(DstReg, AccumRegs);
4735 MI.eraseFromParent();
4750 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4751 ? AMDGPU::G_AMDGPU_FFBH_U32
4752 : AMDGPU::G_AMDGPU_FFBL_B32;
4753 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4756 MI.eraseFromParent();
4766 TypeSize NumBits = SrcTy.getSizeInBits();
4771 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4772 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4773 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4774 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4775 B.buildTrunc(Dst, Ctlz);
4776 MI.eraseFromParent();
4787 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4788 unsigned BitWidth = SrcTy.getSizeInBits();
4790 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4791 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4792 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4793 MI.eraseFromParent();
4799 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4802 return ConstVal == -1;
4809 Register CondDef =
MI.getOperand(0).getReg();
4828 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4837 UncondBrTarget = &*NextMBB;
4839 if (
Next->getOpcode() != AMDGPU::G_BR)
4858 *ArgRC,
B.getDebugLoc(), ArgTy);
4862 const unsigned Mask = Arg->
getMask();
4870 auto ShiftAmt =
B.buildConstant(I32, Shift);
4871 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4874 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4876 B.buildCopy(DstReg, LiveIn);
4886 if (!ST.hasClusters()) {
4889 MI.eraseFromParent();
4909 auto One =
B.buildConstant(I32, 1);
4910 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4911 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4912 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4919 B.buildCopy(DstReg, GlobalIdXYZ);
4920 MI.eraseFromParent();
4924 B.buildCopy(DstReg, ClusterIdXYZ);
4925 MI.eraseFromParent();
4930 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4932 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4933 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4935 .addImm(ClusterIdField);
4936 auto Zero =
B.buildConstant(I32, 0);
4939 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4940 MI.eraseFromParent();
4982 auto LoadConstant = [&](
unsigned N) {
4983 B.buildConstant(DstReg,
N);
4987 if (ST.hasArchitectedSGPRs() &&
4994 Arg = &WorkGroupIDX;
4995 ArgRC = &AMDGPU::SReg_32RegClass;
4999 Arg = &WorkGroupIDY;
5000 ArgRC = &AMDGPU::SReg_32RegClass;
5004 Arg = &WorkGroupIDZ;
5005 ArgRC = &AMDGPU::SReg_32RegClass;
5009 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5010 return LoadConstant(0);
5011 Arg = &ClusterWorkGroupIDX;
5012 ArgRC = &AMDGPU::SReg_32RegClass;
5016 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5017 return LoadConstant(0);
5018 Arg = &ClusterWorkGroupIDY;
5019 ArgRC = &AMDGPU::SReg_32RegClass;
5023 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5024 return LoadConstant(0);
5025 Arg = &ClusterWorkGroupIDZ;
5026 ArgRC = &AMDGPU::SReg_32RegClass;
5031 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5032 Arg = &ClusterWorkGroupMaxIDX;
5033 ArgRC = &AMDGPU::SReg_32RegClass;
5038 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5039 Arg = &ClusterWorkGroupMaxIDY;
5040 ArgRC = &AMDGPU::SReg_32RegClass;
5045 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5046 Arg = &ClusterWorkGroupMaxIDZ;
5047 ArgRC = &AMDGPU::SReg_32RegClass;
5051 Arg = &ClusterWorkGroupMaxFlatID;
5052 ArgRC = &AMDGPU::SReg_32RegClass;
5067 return LoadConstant(0);
5072 B.buildUndef(DstReg);
5076 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5088 MI.eraseFromParent();
5094 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5095 MI.eraseFromParent();
5102 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5116 B.buildUndef(DstReg);
5117 MI.eraseFromParent();
5121 if (Arg->isMasked()) {
5135 MI.eraseFromParent();
5150 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5159 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5167 Align Alignment)
const {
5171 "unexpected kernarg parameter type");
5178 MI.eraseFromParent();
5210 auto FloatY =
B.buildUITOFP(
F32,
Y);
5211 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5213 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5214 auto Z =
B.buildFPTOUI(I32, ScaledY);
5217 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5218 auto NegYZ =
B.buildMul(I32, NegY, Z);
5219 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5222 auto Q =
B.buildUMulH(I32,
X, Z);
5223 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5226 auto One =
B.buildConstant(I32, 1);
5229 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5230 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5235 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5238 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5257 auto Unmerge =
B.buildUnmerge(I32, Val);
5259 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5260 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5262 auto Mad =
B.buildFMAD(
5266 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5267 auto Mul1 =
B.buildFMul(
5271 auto Mul2 =
B.buildFMul(
5273 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5276 auto Mad2 =
B.buildFMAD(
5280 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5281 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5283 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5298 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5300 auto Zero64 =
B.buildConstant(I64, 0);
5301 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5303 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5304 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5306 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5307 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5308 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5310 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5311 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5312 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5314 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5315 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5316 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5317 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5318 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5320 auto Zero32 =
B.buildConstant(I32, 0);
5321 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5322 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5323 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5325 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5326 Register NumerLo = UnmergeNumer.getReg(0);
5327 Register NumerHi = UnmergeNumer.getReg(1);
5329 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5330 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5331 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5332 Register Mul3_Lo = UnmergeMul3.getReg(0);
5333 Register Mul3_Hi = UnmergeMul3.getReg(1);
5334 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5335 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5336 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5337 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5339 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5340 Register DenomLo = UnmergeDenom.getReg(0);
5341 Register DenomHi = UnmergeDenom.getReg(1);
5344 auto C1 =
B.buildSExt(I32, CmpHi);
5347 auto C2 =
B.buildSExt(I32, CmpLo);
5350 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5357 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5358 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5359 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5360 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5362 auto One64 =
B.buildConstant(I64, 1);
5363 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5369 auto C6 =
B.buildSelect(
5373 auto Add4 =
B.buildAdd(I64, Add3, One64);
5374 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5376 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5377 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5378 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5384 auto Sel1 =
B.buildSelect(
5391 auto Sel2 =
B.buildSelect(
5402 switch (
MI.getOpcode()) {
5405 case AMDGPU::G_UDIV: {
5406 DstDivReg =
MI.getOperand(0).getReg();
5409 case AMDGPU::G_UREM: {
5410 DstRemReg =
MI.getOperand(0).getReg();
5413 case AMDGPU::G_UDIVREM: {
5414 DstDivReg =
MI.getOperand(0).getReg();
5415 DstRemReg =
MI.getOperand(1).getReg();
5422 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5423 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5424 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5434 MI.eraseFromParent();
5445 if (Ty != I32 && Ty != I64)
5448 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5449 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5450 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5452 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5453 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5454 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5456 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5457 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5459 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5460 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5462 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5463 switch (
MI.getOpcode()) {
5466 case AMDGPU::G_SDIV: {
5467 DstDivReg =
MI.getOperand(0).getReg();
5471 case AMDGPU::G_SREM: {
5472 DstRemReg =
MI.getOperand(0).getReg();
5476 case AMDGPU::G_SDIVREM: {
5477 DstDivReg =
MI.getOperand(0).getReg();
5478 DstRemReg =
MI.getOperand(1).getReg();
5491 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5492 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5493 B.buildSub(DstDivReg, SignXor, Sign);
5497 auto Sign = LHSign.getReg(0);
5498 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5499 B.buildSub(DstRemReg, SignXor, Sign);
5502 MI.eraseFromParent();
5512 uint16_t Flags =
MI.getFlags();
5518 if (!AllowInaccurateRcp && ResTy !=
F16)
5529 if (CLHS->isOne()) {
5530 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5534 MI.eraseFromParent();
5539 if (CLHS->isMinusOne()) {
5540 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5541 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5542 .addUse(FNeg.getReg(0))
5545 MI.eraseFromParent();
5552 if (!AllowInaccurateRcp &&
5557 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5560 B.buildFMul(Res, LHS, RCP, Flags);
5562 MI.eraseFromParent();
5572 uint16_t Flags =
MI.getFlags();
5577 if (!AllowInaccurateRcp)
5585 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5587 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5588 auto One =
B.buildFConstant(ResTy, 1.0);
5590 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5594 R =
B.buildFNeg(ResTy, R);
5596 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5597 R =
B.buildFMA(ResTy, Tmp0, R, R);
5599 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5600 R =
B.buildFMA(ResTy, Tmp1, R, R);
5603 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5604 B.buildCopy(Res, R);
5605 MI.eraseFromParent();
5609 auto Ret =
B.buildFMul(ResTy,
X, R);
5610 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5612 B.buildFMA(Res, Tmp2, R, Ret);
5613 MI.eraseFromParent();
5627 uint16_t Flags =
MI.getFlags();
5644 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5645 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5646 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5647 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5648 .addUse(RHSExt.getReg(0))
5650 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5652 if (ST.hasMadMacF32Insts()) {
5653 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5654 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5655 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5657 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5658 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5659 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5661 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5662 auto TmpInt =
B.buildBitcast(I32, Tmp);
5663 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5664 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5665 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5666 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5667 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5668 .addUse(RDst.getReg(0))
5673 MI.eraseFromParent();
5686 unsigned SPDenormMode =
5689 if (ST.hasDenormModeInst()) {
5691 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5693 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5694 B.buildInstr(AMDGPU::S_DENORM_MODE)
5695 .addImm(NewDenormModeValue);
5698 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5699 .addImm(SPDenormMode)
5716 uint16_t Flags =
MI.getFlags();
5720 auto One =
B.buildFConstant(
F32, 1.0f);
5722 auto DenominatorScaled =
5723 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5728 auto NumeratorScaled =
5729 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5735 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5736 .addUse(DenominatorScaled.getReg(0))
5738 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5741 const bool HasDynamicDenormals =
5746 if (!PreservesDenormals) {
5747 if (HasDynamicDenormals) {
5749 B.buildInstr(AMDGPU::S_GETREG_B32)
5750 .addDef(SavedSPDenormMode)
5756 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5757 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5758 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5759 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5760 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5761 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5763 if (!PreservesDenormals) {
5764 if (HasDynamicDenormals) {
5765 assert(SavedSPDenormMode);
5766 B.buildInstr(AMDGPU::S_SETREG_B32)
5767 .addReg(SavedSPDenormMode)
5773 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5774 .addUse(Fma4.getReg(0))
5775 .addUse(Fma1.getReg(0))
5776 .addUse(Fma3.getReg(0))
5777 .addUse(NumeratorScaled.getReg(1))
5780 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5781 .addUse(Fmas.getReg(0))
5786 MI.eraseFromParent();
5800 uint16_t Flags =
MI.getFlags();
5804 auto One =
B.buildFConstant(
F64, 1.0);
5806 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5812 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5814 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5815 .addUse(DivScale0.getReg(0))
5818 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5819 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5820 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5822 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5828 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5829 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5830 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5833 if (!ST.hasUsableDivScaleConditionOutput()) {
5840 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5841 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5842 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5843 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5846 Scale1Unmerge.getReg(1));
5848 Scale0Unmerge.getReg(1));
5849 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5851 Scale = DivScale1.getReg(1);
5854 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5855 .addUse(Fma4.getReg(0))
5856 .addUse(Fma3.getReg(0))
5857 .addUse(
Mul.getReg(0))
5861 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5862 .addUse(Fmas.getReg(0))
5867 MI.eraseFromParent();
5877 uint16_t Flags =
MI.getFlags();
5882 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5885 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5889 if (ST.hasFractBug()) {
5890 auto Fabs =
B.buildFAbs(Ty, Val);
5894 auto Zero =
B.buildConstant(InstrExpTy, 0);
5895 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5896 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5899 B.buildCopy(Res0, Mant);
5900 B.buildSExtOrTrunc(Res1, Exp);
5902 MI.eraseFromParent();
5912 uint16_t Flags =
MI.getFlags();
5916 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5919 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5920 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5921 auto C2 =
B.buildFConstant(
F32, 1.0f);
5924 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5926 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5928 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5929 .addUse(Mul0.getReg(0))
5932 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5934 B.buildFMul(Res, Sel, Mul1, Flags);
5936 MI.eraseFromParent();
5945 unsigned Flags =
MI.getFlags();
5946 assert(!ST.has16BitInsts());
5947 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5948 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5949 .addUse(Ext.getReg(0))
5951 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5952 MI.eraseFromParent();
5962 const unsigned Flags =
MI.getFlags();
5970 MI.eraseFromParent();
5974 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5976 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5977 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5978 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5983 .addUse(SqrtX.getReg(0))
5986 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5987 auto NegOne =
B.buildConstant(I32, -1);
5988 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5990 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5991 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5993 auto PosOne =
B.buildConstant(I32, 1);
5994 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5996 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5997 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
5999 auto Zero =
B.buildFConstant(
F32, 0.0f);
6003 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6007 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6010 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6011 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6013 auto Half =
B.buildFConstant(
F32, 0.5f);
6014 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6015 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6016 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6017 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6018 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6019 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6020 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6021 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6024 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6026 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6028 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6031 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6033 MI.eraseFromParent();
6067 unsigned Flags =
MI.getFlags();
6072 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6074 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6078 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6079 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6080 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6083 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6085 auto Half =
B.buildFConstant(
F64, 0.5);
6086 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6087 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6089 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6090 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6092 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6093 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6095 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6096 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6098 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6100 Register SqrtRet = SqrtS2.getReg(0);
6102 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6103 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6104 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6107 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6108 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6109 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6114 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6117 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6123 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6125 MI.eraseFromParent();
6156 auto Flags =
MI.getFlags();
6168 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6178 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6179 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6184 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6186 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6187 MI.eraseFromParent();
6199 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6200 IID == Intrinsic::amdgcn_permlanex16;
6201 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6202 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6203 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6204 IID == Intrinsic::amdgcn_permlane_up ||
6205 IID == Intrinsic::amdgcn_permlane_down ||
6206 IID == Intrinsic::amdgcn_permlane_xor;
6210 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6212 case Intrinsic::amdgcn_readfirstlane:
6213 case Intrinsic::amdgcn_permlane64:
6214 return LaneOp.getReg(0);
6215 case Intrinsic::amdgcn_readlane:
6216 case Intrinsic::amdgcn_set_inactive:
6217 case Intrinsic::amdgcn_set_inactive_chain_arg:
6218 return LaneOp.addUse(Src1).getReg(0);
6219 case Intrinsic::amdgcn_writelane:
6220 case Intrinsic::amdgcn_permlane_bcast:
6221 case Intrinsic::amdgcn_permlane_up:
6222 case Intrinsic::amdgcn_permlane_down:
6223 case Intrinsic::amdgcn_permlane_xor:
6224 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6225 case Intrinsic::amdgcn_permlane16:
6226 case Intrinsic::amdgcn_permlanex16: {
6228 int64_t Src4 =
MI.getOperand(6).getImm();
6229 int64_t Src5 =
MI.getOperand(7).getImm();
6230 return LaneOp.addUse(Src1)
6237 case Intrinsic::amdgcn_mov_dpp8:
6238 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6239 case Intrinsic::amdgcn_update_dpp:
6240 return LaneOp.addUse(Src1)
6241 .addImm(
MI.getOperand(4).getImm())
6242 .addImm(
MI.getOperand(5).getImm())
6243 .addImm(
MI.getOperand(6).getImm())
6244 .addImm(
MI.getOperand(7).getImm())
6254 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6255 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6256 IsPermlaneShuffle) {
6257 Src1 =
MI.getOperand(3).getReg();
6258 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6259 IsPermlaneShuffle) {
6260 Src2 =
MI.getOperand(4).getReg();
6265 unsigned Size = Ty.getSizeInBits();
6267 unsigned SplitSize = 32;
6268 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6269 ST.hasDPALU_DPP() &&
6273 if (
Size == SplitSize) {
6280 bool IsFloat = Ty.getScalarType().isFloat();
6284 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6286 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6288 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6292 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6294 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6295 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6297 if (IID == Intrinsic::amdgcn_writelane)
6298 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6300 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6302 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6304 B.buildTrunc(DstReg, LaneOpDst);
6305 MI.eraseFromParent();
6309 if (
Size % SplitSize != 0)
6313 bool NeedsBitcast =
false;
6314 if (IntTy.isVector()) {
6317 if (EltSize == SplitSize) {
6318 PartialResTy = EltTy;
6319 }
else if (EltSize == 16 || EltSize == 32) {
6320 unsigned NElem = SplitSize / EltSize;
6323 NeedsBitcast =
true;
6328 unsigned NumParts =
Size / SplitSize;
6332 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6333 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6335 if (IID == Intrinsic::amdgcn_writelane)
6336 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6338 for (
unsigned i = 0; i < NumParts; ++i) {
6339 Src0 = Src0Parts.
getReg(i);
6341 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6342 Src1 = Src1Parts.
getReg(i);
6344 if (IID == Intrinsic::amdgcn_writelane)
6345 Src2 = Src2Parts.
getReg(i);
6347 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6350 if (NeedsBitcast || IsFloat)
6353 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6355 B.buildMergeLikeInstr(DstReg, PartialRes);
6357 MI.eraseFromParent();
6365 ST.getTargetLowering()->getImplicitParameterOffset(
6375 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6376 B.buildConstant(IdxTy,
Offset).getReg(0));
6387 Register Pointer =
MI.getOperand(2).getReg();
6389 Register NumRecords =
MI.getOperand(4).getReg();
6395 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6397 auto ExtStride =
B.buildAnyExt(I32, Stride);
6399 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6400 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6402 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6404 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6408 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6409 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6410 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6411 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6415 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6416 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6417 auto ExtShiftedStride =
6418 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6419 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6420 auto ExtShiftedFlags =
6421 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6422 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6424 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6425 B.buildMergeValues(Result, {LowHalf, HighHalf});
6427 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6428 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6429 auto LowHalf = Unmerge.getReg(0);
6430 auto HighHalf = Unmerge.getReg(1);
6432 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6433 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6434 auto ShiftConst =
B.buildConstant(I32, 16);
6435 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6436 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6437 Register NewHighHalfReg = NewHighHalf.getReg(0);
6438 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6441 MI.eraseFromParent();
6458 MI.eraseFromParent();
6466 std::optional<uint32_t> KnownSize =
6468 if (KnownSize.has_value())
6469 B.buildConstant(DstReg, *KnownSize);
6487 MI.eraseFromParent();
6494 unsigned AddrSpace)
const {
6496 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6500 ST.hasGloballyAddressableScratch()) {
6502 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6503 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6505 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6507 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6509 B.buildConstant(I32, 1u << 26));
6514 MI.eraseFromParent();
6524std::pair<Register, unsigned>
6536 bool CheckNUW = ST.hasGFX1250Insts();
6538 MRI, OrigOffset,
nullptr, CheckNUW);
6542 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6552 unsigned Overflow = ImmOffset & ~MaxImm;
6553 ImmOffset -= Overflow;
6554 if ((int32_t)Overflow < 0) {
6555 Overflow += ImmOffset;
6559 if (Overflow != 0) {
6561 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6563 auto OverflowVal =
B.buildConstant(I32, Overflow);
6564 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6569 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6571 return std::pair(BaseReg, ImmOffset);
6578 bool ImageStore)
const {
6586 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6588 if (ST.hasUnpackedD16VMem()) {
6589 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6592 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6593 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6601 if (ImageStore && ST.hasImageStoreD16Bug()) {
6604 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6606 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6613 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6614 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6616 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6624 auto Unmerge =
B.buildUnmerge(I32, Reg);
6625 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6627 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6637 Reg =
B.buildPadVectorWithUndefElements(
6646 bool IsFormat)
const {
6656 VData =
B.buildBitcast(Ty, VData).getReg(0);
6664 if (Ty.isVector()) {
6665 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6677 bool IsFormat)
const {
6684 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6691 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6692 const Function &Fn =
B.getMF().getFunction();
6694 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6695 MI.eraseFromParent();
6707 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6710 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6714 VIndex =
MI.getOperand(3).getReg();
6717 VIndex =
B.buildConstant(I32, 0).getReg(0);
6720 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6721 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6725 Format =
MI.getOperand(5 + OpOffset).getImm();
6729 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6735 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6736 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6737 }
else if (IsFormat) {
6738 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6739 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6743 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6746 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6749 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6754 auto MIB =
B.buildInstr(
Opc)
6765 MIB.addImm(AuxiliaryData)
6766 .addImm(HasVIndex ? -1 : 0)
6767 .addMemOperand(MMO);
6769 MI.eraseFromParent();
6775 unsigned ImmOffset,
unsigned Format,
6778 auto MIB =
B.buildInstr(
Opc)
6789 MIB.addImm(AuxiliaryData)
6790 .addImm(HasVIndex ? -1 : 0)
6791 .addMemOperand(MMO);
6797 bool IsTyped)
const {
6811 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6812 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6814 StatusDst =
MI.getOperand(1).getReg();
6819 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6822 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6825 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6828 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6831 VIndex =
B.buildConstant(I32, 0).getReg(0);
6834 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6835 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6839 Format =
MI.getOperand(5 + OpOffset).getImm();
6843 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6853 Dst =
MI.getOperand(0).getReg();
6854 B.setInsertPt(
B.getMBB(),
MI);
6861 Dst =
MI.getOperand(0).getReg();
6862 B.setInsertPt(
B.getMBB(),
MI);
6866 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6867 const bool Unpacked = ST.hasUnpackedD16VMem();
6869 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6870 const Function &Fn =
B.getMF().getFunction();
6872 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6875 B.buildUndef(StatusDst);
6876 MI.eraseFromParent();
6888 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6889 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6890 }
else if (IsFormat) {
6894 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6896 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6897 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6902 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6903 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6906 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6907 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6910 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6911 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6917 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6918 unsigned NumLoadDWords = NumValueDWords + 1;
6920 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6922 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6923 bool IsFloat = Ty.getScalarType().isFloat();
6928 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6930 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6931 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6932 B.buildTrunc(DstInt, ExtDst);
6933 }
else if (NumValueDWords == 1) {
6934 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6937 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6938 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6940 B.buildUnmerge(LoadElts, LoadDstReg);
6942 B.buildMergeLikeInstr(DstInt, LoadElts);
6945 B.buildBitcast(Dst, DstInt);
6947 (IsD16 && !Ty.isVector())) {
6948 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6950 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6951 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6952 B.buildTrunc(Dst, LoadDstReg);
6953 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6955 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6957 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6958 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6960 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6962 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6963 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6964 B.buildMergeLikeInstr(Dst, Repack);
6967 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6970 MI.eraseFromParent();
6976 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6977 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6978 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6979 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6980 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6981 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6982 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6983 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6984 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6985 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6986 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6987 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6988 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6989 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6990 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6991 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6992 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6993 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6994 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6995 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6996 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6997 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6998 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6999 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7000 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7001 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7002 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7003 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7004 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7005 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7006 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7007 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7008 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7009 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7010 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7011 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7012 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7013 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7014 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7015 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7016 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7017 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7018 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7019 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7020 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7021 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7022 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7023 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7024 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7025 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7026 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7027 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7028 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7029 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7030 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7031 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7032 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7033 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7034 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7035 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7036 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7037 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7038 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7039 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7040 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7041 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7042 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7043 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7044 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7045 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7046 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7047 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7048 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7049 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7050 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7051 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7052 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7053 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7054 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7055 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7056 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7057 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7058 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7059 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7060 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7061 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7062 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7063 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7064 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7065 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7074 const bool IsCmpSwap =
7075 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7076 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7077 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7078 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7089 CmpVal =
MI.getOperand(3).getReg();
7094 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7095 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7098 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7101 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7107 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7108 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7109 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7128 .addImm(AuxiliaryData)
7129 .addImm(HasVIndex ? -1 : 0)
7130 .addMemOperand(MMO);
7132 MI.eraseFromParent();
7142 bool IsA16,
bool IsG16) {
7156 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7161 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7165 "Bias needs to be converted to 16 bit in A16 mode");
7167 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7171 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7175 if (((
I + 1) >= EndIdx) ||
7182 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7184 B.buildBuildVector(V2EltTy,
7185 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7190 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7201 int DimIdx,
int NumVAddrs) {
7203 for (
int I = 0;
I != NumVAddrs; ++
I) {
7205 if (
SrcOp.isReg()) {
7208 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7209 if (
B.getMRI()->getType(
Reg) != I32)
7210 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7215 int NumAddrRegs = AddrRegs.
size();
7216 if (NumAddrRegs != 1) {
7217 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7220 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7223 for (
int I = 1;
I != NumVAddrs; ++
I) {
7226 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7248 const unsigned NumDefs =
MI.getNumExplicitDefs();
7249 const unsigned ArgOffset = NumDefs + 1;
7250 bool IsTFE = NumDefs == 2;
7268 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7272 const bool IsAtomicPacked16Bit =
7273 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7274 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7281 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7282 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7283 const bool DataTyIs16 =
7284 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7286 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7287 const bool IsA16 = AddrTyIs16;
7288 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7291 if (!BaseOpcode->
Atomic) {
7292 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7295 }
else if (DMask != 0) {
7297 }
else if (!IsTFE && !BaseOpcode->
Store) {
7299 B.buildUndef(
MI.getOperand(0));
7300 MI.eraseFromParent();
7308 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7309 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7310 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7311 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7312 unsigned NewOpcode = LoadOpcode;
7313 if (BaseOpcode->
Store)
7314 NewOpcode = StoreOpcode;
7316 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7319 MI.setDesc(
B.getTII().get(NewOpcode));
7323 if (IsTFE && DMask == 0) {
7326 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7329 if (BaseOpcode->
Atomic) {
7334 if (Ty.isVector() && !IsAtomicPacked16Bit)
7341 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7342 MI.getOperand(2).setReg(
Concat.getReg(0));
7343 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7347 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7350 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7356 if (IsA16 && !ST.hasA16()) {
7361 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7362 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7364 if (IsA16 || IsG16) {
7372 const bool UseNSA = ST.hasNSAEncoding() &&
7373 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7374 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7375 const bool UsePartialNSA =
7376 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7378 if (UsePartialNSA) {
7382 auto Concat =
B.buildConcatVectors(
7383 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7384 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7385 PackedRegs.
resize(NSAMaxSize);
7386 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7388 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7389 PackedRegs[0] =
Concat.getReg(0);
7393 const unsigned NumPacked = PackedRegs.
size();
7396 if (!
SrcOp.isReg()) {
7406 SrcOp.setReg(AMDGPU::NoRegister);
7423 const bool UseNSA = ST.hasNSAEncoding() &&
7424 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7425 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7426 const bool UsePartialNSA =
7427 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7429 if (UsePartialNSA) {
7431 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7433 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7448 if (!Ty.isVector() || !IsD16)
7452 if (RepackedReg != VData) {
7453 MI.getOperand(1).setReg(RepackedReg);
7461 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7464 if (NumElts < DMaskLanes)
7467 if (NumElts > 4 || DMaskLanes > 4)
7478 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7479 const LLT AdjustedTy =
7495 if (IsD16 && ST.hasUnpackedD16VMem()) {
7502 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7503 unsigned RoundedSize = 32 * RoundedElts;
7507 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7512 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7518 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7522 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7523 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7527 MI.getOperand(0).setReg(NewResultReg);
7535 Dst1Reg =
MI.getOperand(1).getReg();
7536 if (MRI->
getType(Dst1Reg) != I32)
7540 MI.removeOperand(1);
7543 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7544 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7545 B.buildBitcast(DstReg, Unmerge.getReg(0));
7546 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7555 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7557 if (ResultNumRegs == 1) {
7559 ResultRegs[0] = NewResultReg;
7562 for (
int I = 0;
I != NumDataRegs; ++
I)
7564 B.buildUnmerge(ResultRegs, NewResultReg);
7569 ResultRegs.
resize(NumDataRegs);
7574 if (IsD16 && !Ty.isVector()) {
7575 B.buildTrunc(DstReg, ResultRegs[0]);
7580 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7581 !ST.hasUnpackedD16VMem()) {
7582 B.buildBitcast(DstReg, ResultRegs[0]);
7594 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7596 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7597 }
else if (ST.hasUnpackedD16VMem()) {
7599 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7603 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7607 for (
int I = 0;
I != NumElts; ++
I)
7614 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7615 B.buildBuildVector(DstReg, ResultRegs);
7619 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7620 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7625 if (Ty == V3I16 || Ty == V3F16) {
7627 if (ResultRegs.
size() == 1) {
7628 NewResultReg = ResultRegs[0];
7629 }
else if (ResultRegs.
size() == 2) {
7631 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7646 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7648 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7650 if (ResizeDst != DstReg)
7651 B.buildBitcast(DstReg, ResizeDst);
7655 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7656 B.buildConcatVectors(DstReg, ResultRegs);
7665 Register OrigDst =
MI.getOperand(0).getReg();
7667 LLT Ty =
B.getMRI()->getType(OrigDst);
7668 unsigned Size = Ty.getSizeInBits();
7670 bool HasMMO = !
MI.memoperands_empty();
7672 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7674 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7675 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7678 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7680 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7689 B.setInsertPt(
B.getMBB(),
MI);
7694 B.setInsertPt(
B.getMBB(),
MI);
7697 MI.setDesc(
B.getTII().get(
Opc));
7698 MI.removeOperand(1);
7704 const unsigned MemSize = (
Size + 7) / 8;
7705 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7712 MI.addMemOperand(MF, MMO);
7714 if (Dst != OrigDst) {
7715 MI.getOperand(0).setReg(Dst);
7716 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7717 B.buildTrunc(OrigDst, Dst);
7739 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7740 MI.removeOperand(0);
7750 if (!ST.hasTrapHandler() ||
7754 return ST.supportsGetDoorbellID() ?
7767 MI.eraseFromParent();
7777 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7779 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7783 MI.eraseFromParent();
7792 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7799 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7819 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7822 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7823 B.buildCopy(SGPR01, Temp);
7824 B.buildInstr(AMDGPU::S_TRAP)
7827 MI.eraseFromParent();
7838 B.buildCopy(SGPR01, LiveIn);
7839 B.buildInstr(AMDGPU::S_TRAP)
7843 MI.eraseFromParent();
7852 if (ST.hasPrivEnabledTrap2NopBug()) {
7853 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7855 MI.eraseFromParent();
7859 B.buildInstr(AMDGPU::S_TRAP)
7861 MI.eraseFromParent();
7870 if (!ST.hasTrapHandler() ||
7874 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7877 B.buildInstr(AMDGPU::S_TRAP)
7881 MI.eraseFromParent();
7895 Register NodePtr =
MI.getOperand(2).getReg();
7896 Register RayExtent =
MI.getOperand(3).getReg();
7897 Register RayOrigin =
MI.getOperand(4).getReg();
7899 Register RayInvDir =
MI.getOperand(6).getReg();
7902 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7909 const unsigned NumVDataDwords = 4;
7910 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7911 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7913 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7915 const unsigned BaseOpcodes[2][2] = {
7916 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7917 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7918 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7922 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7923 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7924 : AMDGPU::MIMGEncGfx10NSA,
7925 NumVDataDwords, NumVAddrDwords);
7929 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7930 : AMDGPU::MIMGEncGfx10Default,
7931 NumVDataDwords, NumVAddrDwords);
7936 if (UseNSA && IsGFX11Plus) {
7937 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7938 auto SrcInt =
B.buildBitcast(V3I32, Src);
7939 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7940 auto Merged =
B.buildMergeLikeInstr(
7941 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7942 Ops.push_back(Merged.getReg(0));
7945 Ops.push_back(NodePtr);
7946 Ops.push_back(RayExtent);
7947 packLanes(RayOrigin);
7950 auto UnmergeRayDir =
7951 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7952 auto UnmergeRayInvDir =
7953 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7954 auto MergedDir =
B.buildMergeLikeInstr(
7957 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7958 UnmergeRayDir.getReg(0)}))
7961 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7962 UnmergeRayDir.getReg(1)}))
7965 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7966 UnmergeRayDir.getReg(2)}))
7968 Ops.push_back(MergedDir.getReg(0));
7971 packLanes(RayInvDir);
7975 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7976 Ops.push_back(Unmerge.getReg(0));
7977 Ops.push_back(Unmerge.getReg(1));
7979 Ops.push_back(NodePtr);
7981 Ops.push_back(RayExtent);
7983 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7984 auto SrcInt =
B.buildBitcast(V3I32, Src);
7985 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7986 Ops.push_back(Unmerge.getReg(0));
7987 Ops.push_back(Unmerge.getReg(1));
7988 Ops.push_back(Unmerge.getReg(2));
7991 packLanes(RayOrigin);
7993 auto UnmergeRayDir =
7994 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7995 auto UnmergeRayInvDir =
7996 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8000 B.buildMergeLikeInstr(R1,
8001 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8002 B.buildMergeLikeInstr(
8003 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8004 B.buildMergeLikeInstr(
8005 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8011 packLanes(RayInvDir);
8020 Ops.push_back(MergedOps);
8023 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8032 .addImm(IsA16 ? 1 : 0)
8035 MI.eraseFromParent();
8045 Register DstOrigin =
MI.getOperand(1).getReg();
8047 Register NodePtr =
MI.getOperand(4).getReg();
8048 Register RayExtent =
MI.getOperand(5).getReg();
8049 Register InstanceMask =
MI.getOperand(6).getReg();
8050 Register RayOrigin =
MI.getOperand(7).getReg();
8052 Register Offsets =
MI.getOperand(9).getReg();
8053 Register TDescr =
MI.getOperand(10).getReg();
8056 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8057 const unsigned NumVDataDwords = 10;
8058 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8060 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8061 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8062 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8065 auto RayExtentInstanceMaskVec =
8066 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8067 B.buildAnyExt(I32, InstanceMask)});
8069 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8070 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8076 .addUse(RayExtentInstanceMaskVec.getReg(0))
8083 MI.eraseFromParent();
8092 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8093 MI.eraseFromParent();
8100 if (!ST.hasArchitectedSGPRs())
8104 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8105 auto LSB =
B.buildConstant(I32, 25);
8106 auto Width =
B.buildConstant(I32, 5);
8107 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8108 MI.eraseFromParent();
8116 unsigned Width)
const {
8120 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8121 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8124 MI.eraseFromParent();
8144 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8148 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8151 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8152 MI.eraseFromParent();
8165 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8169 .addReg(Unmerge.getReg(0));
8173 .addReg(Unmerge.getReg(1));
8174 MI.eraseFromParent();
8186 case Intrinsic::sponentry:
8192 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8195 B.buildIntToPtr(DstReg, TmpReg);
8196 MI.eraseFromParent();
8198 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8200 B.buildFrameIndex(
MI.getOperand(0), FI);
8201 MI.eraseFromParent();
8204 case Intrinsic::amdgcn_if:
8205 case Intrinsic::amdgcn_else: {
8208 bool Negated =
false;
8220 std::swap(CondBrTarget, UncondBrTarget);
8222 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8223 if (IntrID == Intrinsic::amdgcn_if) {
8224 B.buildInstr(AMDGPU::SI_IF)
8227 .addMBB(UncondBrTarget);
8229 B.buildInstr(AMDGPU::SI_ELSE)
8232 .addMBB(UncondBrTarget);
8241 B.buildBr(*CondBrTarget);
8246 MI.eraseFromParent();
8247 BrCond->eraseFromParent();
8253 case Intrinsic::amdgcn_loop: {
8256 bool Negated =
false;
8266 std::swap(CondBrTarget, UncondBrTarget);
8268 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8269 B.buildInstr(AMDGPU::SI_LOOP)
8271 .addMBB(UncondBrTarget);
8276 B.buildBr(*CondBrTarget);
8278 MI.eraseFromParent();
8279 BrCond->eraseFromParent();
8286 case Intrinsic::amdgcn_wave_reduce_min:
8287 case Intrinsic::amdgcn_wave_reduce_umin:
8288 case Intrinsic::amdgcn_wave_reduce_fmin:
8289 case Intrinsic::amdgcn_wave_reduce_max:
8290 case Intrinsic::amdgcn_wave_reduce_umax:
8291 case Intrinsic::amdgcn_wave_reduce_fmax:
8292 case Intrinsic::amdgcn_wave_reduce_add:
8293 case Intrinsic::amdgcn_wave_reduce_fadd:
8294 case Intrinsic::amdgcn_wave_reduce_sub:
8295 case Intrinsic::amdgcn_wave_reduce_fsub:
8296 case Intrinsic::amdgcn_wave_reduce_and:
8297 case Intrinsic::amdgcn_wave_reduce_or:
8298 case Intrinsic::amdgcn_wave_reduce_xor: {
8303 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8304 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8305 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8306 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8307 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8308 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8309 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8310 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8311 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8318 .addUse(Ext.getReg(0))
8319 .addImm(
MI.getOperand(3).getImm());
8321 B.buildFPTrunc(DstReg, NewDst);
8323 B.buildTrunc(DstReg, NewDst);
8324 MI.eraseFromParent();
8327 case Intrinsic::amdgcn_make_buffer_rsrc:
8329 case Intrinsic::amdgcn_kernarg_segment_ptr:
8332 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8333 MI.eraseFromParent();
8339 case Intrinsic::amdgcn_implicitarg_ptr:
8341 case Intrinsic::amdgcn_workitem_id_x:
8344 case Intrinsic::amdgcn_workitem_id_y:
8347 case Intrinsic::amdgcn_workitem_id_z:
8350 case Intrinsic::amdgcn_workgroup_id_x:
8355 case Intrinsic::amdgcn_workgroup_id_y:
8360 case Intrinsic::amdgcn_workgroup_id_z:
8365 case Intrinsic::amdgcn_cluster_id_x:
8366 return ST.hasClusters() &&
8369 case Intrinsic::amdgcn_cluster_id_y:
8370 return ST.hasClusters() &&
8373 case Intrinsic::amdgcn_cluster_id_z:
8374 return ST.hasClusters() &&
8377 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8378 return ST.hasClusters() &&
8381 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8382 return ST.hasClusters() &&
8385 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8386 return ST.hasClusters() &&
8389 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8390 return ST.hasClusters() &&
8392 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8393 return ST.hasClusters() &&
8396 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8397 return ST.hasClusters() &&
8400 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8401 return ST.hasClusters() &&
8404 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8405 return ST.hasClusters() &&
8409 case Intrinsic::amdgcn_wave_id:
8411 case Intrinsic::amdgcn_lds_kernel_id:
8414 case Intrinsic::amdgcn_dispatch_ptr:
8417 case Intrinsic::amdgcn_queue_ptr:
8420 case Intrinsic::amdgcn_implicit_buffer_ptr:
8423 case Intrinsic::amdgcn_dispatch_id:
8426 case Intrinsic::r600_read_ngroups_x:
8430 case Intrinsic::r600_read_ngroups_y:
8433 case Intrinsic::r600_read_ngroups_z:
8436 case Intrinsic::r600_read_local_size_x:
8439 case Intrinsic::r600_read_local_size_y:
8443 case Intrinsic::r600_read_local_size_z:
8446 case Intrinsic::amdgcn_fdiv_fast:
8448 case Intrinsic::amdgcn_is_shared:
8450 case Intrinsic::amdgcn_is_private:
8452 case Intrinsic::amdgcn_wavefrontsize: {
8453 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8454 MI.eraseFromParent();
8457 case Intrinsic::amdgcn_s_buffer_load:
8458 case Intrinsic::amdgcn_ptr_s_buffer_load:
8460 case Intrinsic::amdgcn_raw_buffer_store:
8461 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8462 case Intrinsic::amdgcn_struct_buffer_store:
8463 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8465 case Intrinsic::amdgcn_raw_buffer_store_format:
8466 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8467 case Intrinsic::amdgcn_struct_buffer_store_format:
8468 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8470 case Intrinsic::amdgcn_raw_tbuffer_store:
8471 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8472 case Intrinsic::amdgcn_struct_tbuffer_store:
8473 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8475 case Intrinsic::amdgcn_raw_buffer_load:
8476 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8477 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8478 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8479 case Intrinsic::amdgcn_struct_buffer_load:
8480 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8481 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8482 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8484 case Intrinsic::amdgcn_raw_buffer_load_format:
8485 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8486 case Intrinsic::amdgcn_struct_buffer_load_format:
8487 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8489 case Intrinsic::amdgcn_raw_tbuffer_load:
8490 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8491 case Intrinsic::amdgcn_struct_tbuffer_load:
8492 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8494 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8495 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8496 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8497 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8498 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8499 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8500 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8501 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8502 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8503 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8504 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8505 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8506 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8507 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8508 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8509 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8510 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8511 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8512 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8513 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8514 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8515 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8516 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8517 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8518 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8519 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8520 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8521 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8522 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8523 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8524 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8525 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8526 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8527 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8528 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8529 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8530 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8531 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8532 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8533 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8534 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8535 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8536 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8537 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8538 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8539 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8540 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8541 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8542 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8543 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8544 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8545 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8546 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8547 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8548 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8549 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8550 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8551 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8552 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8553 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8554 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8555 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8556 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8557 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8558 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8559 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8560 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8561 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8562 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8563 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8564 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8565 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8567 case Intrinsic::amdgcn_rsq_clamp:
8569 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8571 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8572 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8574 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8575 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8576 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8577 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8578 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8579 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8580 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8581 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8585 if (IndexArgTy != I64) {
8586 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8587 :
B.buildAnyExt(I64, Index);
8588 MI.getOperand(5).setReg(NewIndex.getReg(0));
8592 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8593 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8594 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8595 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8596 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8597 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8598 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8599 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8602 if (MRI.
getType(Index) != I32)
8603 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8606 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8607 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8608 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8609 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8610 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8611 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8612 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8613 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8614 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8616 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8620 if (IndexArgTy != IdxTy) {
8621 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8622 :
B.buildAnyExt(IdxTy, Index);
8623 MI.getOperand(7).setReg(NewIndex.getReg(0));
8628 case Intrinsic::amdgcn_fmed3: {
8634 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8635 MI.removeOperand(1);
8639 case Intrinsic::amdgcn_readlane:
8640 case Intrinsic::amdgcn_writelane:
8641 case Intrinsic::amdgcn_readfirstlane:
8642 case Intrinsic::amdgcn_permlane16:
8643 case Intrinsic::amdgcn_permlanex16:
8644 case Intrinsic::amdgcn_permlane64:
8645 case Intrinsic::amdgcn_set_inactive:
8646 case Intrinsic::amdgcn_set_inactive_chain_arg:
8647 case Intrinsic::amdgcn_mov_dpp8:
8648 case Intrinsic::amdgcn_update_dpp:
8649 case Intrinsic::amdgcn_permlane_bcast:
8650 case Intrinsic::amdgcn_permlane_up:
8651 case Intrinsic::amdgcn_permlane_down:
8652 case Intrinsic::amdgcn_permlane_xor:
8654 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8656 case Intrinsic::amdgcn_dead: {
8660 MI.eraseFromParent();
8663 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8664 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8665 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8666 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8667 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8668 MI.eraseFromParent();
8670 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8671 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8672 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8673 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8674 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8675 MI.eraseFromParent();
8677 case Intrinsic::amdgcn_av_load_b128:
8678 case Intrinsic::amdgcn_av_store_b128: {
8679 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8680 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8681 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8683 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8684 **
MI.memoperands_begin());
8685 MI.eraseFromParent();
8688 case Intrinsic::amdgcn_flat_load_monitor_b32:
8689 case Intrinsic::amdgcn_flat_load_monitor_b64:
8690 case Intrinsic::amdgcn_flat_load_monitor_b128:
8691 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8692 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8693 .add(
MI.getOperand(0))
8694 .add(
MI.getOperand(2))
8695 .addMemOperand(*
MI.memoperands_begin());
8696 MI.eraseFromParent();
8698 case Intrinsic::amdgcn_global_load_monitor_b32:
8699 case Intrinsic::amdgcn_global_load_monitor_b64:
8700 case Intrinsic::amdgcn_global_load_monitor_b128:
8701 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8702 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8703 .add(
MI.getOperand(0))
8704 .add(
MI.getOperand(2))
8705 .addMemOperand(*
MI.memoperands_begin());
8706 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.
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.