36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
59 unsigned Bits = Ty.getSizeInBits();
69 const LLT Ty = Query.Types[TypeIdx];
75 return Ty.getNumElements() % 2 != 0 &&
76 EltSize > 1 && EltSize < 32 &&
77 Ty.getSizeInBits() % 32 != 0;
83 const LLT Ty = Query.Types[TypeIdx];
90 const LLT Ty = Query.Types[TypeIdx];
92 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
98 const LLT Ty = Query.Types[TypeIdx];
100 return std::pair(TypeIdx,
107 const LLT Ty = Query.Types[TypeIdx];
109 unsigned Size = Ty.getSizeInBits();
110 unsigned Pieces = (
Size + 63) / 64;
111 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
121 const LLT Ty = Query.Types[TypeIdx];
124 const int Size = Ty.getSizeInBits();
126 const int NextMul32 = (
Size + 31) / 32;
130 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
138 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
146 const LLT Ty = Query.Types[TypeIdx];
148 const unsigned EltSize = Ty.getElementType().getSizeInBits();
151 assert(EltSize == 32 || EltSize == 64);
156 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
160 return std::pair(TypeIdx,
175 const unsigned NumElems = Ty.getElementCount().getFixedValue();
180 const unsigned Size = Ty.getSizeInBits();
193 const LLT Ty = Query.Types[TypeIdx];
200 const LLT Ty = Query.Types[TypeIdx];
201 unsigned Size = Ty.getSizeInBits();
203 return std::pair(TypeIdx,
211 const LLT QueryTy = Query.Types[TypeIdx];
218 const LLT QueryTy = Query.Types[TypeIdx];
225 const LLT QueryTy = Query.Types[TypeIdx];
231 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
237 return EltSize == 16 || EltSize % 32 == 0;
241 const int EltSize = Ty.getElementType().getSizeInBits();
242 return EltSize == 32 || EltSize == 64 ||
243 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
244 EltSize == 128 || EltSize == 256;
273 LLT Ty = Query.Types[TypeIdx];
281 const LLT QueryTy = Query.Types[TypeIdx];
369 if (Ty.isPointerOrPointerVector())
370 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
374 (ST.useRealTrue16Insts() && Ty ==
S16) ||
389 const LLT Ty = Query.Types[TypeIdx];
390 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
391 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
399 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
409 bool IsLoad,
bool IsAtomic) {
413 return ST.hasFlatScratchEnabled() ? 128 : 32;
415 return ST.useDS128() ? 128 : 64;
426 return IsLoad ? 512 : 128;
431 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
440 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
442 unsigned RegSize = Ty.getSizeInBits();
445 unsigned AS = Query.
Types[1].getAddressSpace();
452 if (Ty.isVector() && MemSize !=
RegSize)
459 if (IsLoad && MemSize <
Size)
460 MemSize = std::max(MemSize,
Align);
467 if (IsLoad &&
RegSize == 16 && !ST.d16PreservesUnusedBits())
483 if (!ST.hasDwordx3LoadStores())
496 if (AlignBits < MemSize) {
498 if (!
TLI->allowsMisalignedMemoryAccessesImpl(MemSize, AS,
499 Align(AlignBits / 8)))
526 if (ST.getCLOpts().global_isel_new_legality)
529 const unsigned Size = Ty.getSizeInBits();
530 if (Ty.isPointerVector())
540 unsigned EltSize = Ty.getScalarSizeInBits();
541 return EltSize != 32 && EltSize != 64;
555 const unsigned Size = Ty.getSizeInBits();
556 if (
Size != MemSizeInBits)
557 return Size <= 32 && Ty.isVector();
563 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
572 uint64_t AlignInBits,
unsigned AddrSpace,
582 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
593 if (AlignInBits < RoundedSize)
599 return TLI->allowsMisalignedMemoryAccessesImpl(
600 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
612 Query.
Types[1].getAddressSpace(), Opcode);
635 Register VectorReg =
MRI.createGenericVirtualRegister(VectorTy);
636 std::array<Register, 4> VectorElems;
637 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
640 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
641 B.buildMergeValues(MO, VectorElems);
645 Register BitcastReg =
MRI.createGenericVirtualRegister(VectorTy);
646 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
647 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
672 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
675 return B.buildBitcast(VectorTy,
Scalar).getReg(0);
703 const LLT BufferStridedPtr =
706 const LLT CodePtr = FlatPtr;
708 const std::initializer_list<LLT> AddrSpaces64 = {
709 GlobalPtr, ConstantPtr, FlatPtr
712 const std::initializer_list<LLT> AddrSpaces32 = {
713 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
716 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
718 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
719 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
720 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
749 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
751 if (ST.hasAnyPackedU64Ops()) {
754 .clampMaxNumElementsStrict(0,
S16, 2)
760 }
else if (ST.hasScalarAddSub64()) {
763 .clampMaxNumElementsStrict(0,
S16, 2)
771 .clampMaxNumElementsStrict(0,
S16, 2)
778 if (ST.hasScalarSMulU64()) {
781 .clampMaxNumElementsStrict(0,
S16, 2)
789 .clampMaxNumElementsStrict(0,
S16, 2)
799 .minScalarOrElt(0,
S16)
804 }
else if (ST.has16BitInsts()) {
838 .widenScalarToNextMultipleOf(0, 32)
848 if (ST.hasMad64_32())
853 if (ST.hasIntClamp()) {
876 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
886 if (ST.hasVOP3PInsts()) {
888 .clampMaxNumElements(0,
S8, 2)
909 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
925 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
968 auto &FCanonicalizeActions =
970 auto &StrictFPOpActions =
977 if (ST.has16BitInsts()) {
978 if (ST.hasVOP3PInsts()) {
980 FCanonicalizeActions.legalFor({
F16,
V2F16});
981 StrictFPOpActions.legalFor({
F16,
V2F16});
983 FPOpActions.legalFor({
F16});
984 FCanonicalizeActions.legalFor({
F16});
985 StrictFPOpActions.legalFor({
F16});
988 TrigActions.customFor({
F16});
989 FDIVActions.customFor({
F16});
992 if (ST.hasBF16PackedInsts()) {
996 .clampMaxNumElementsStrict(0,
BF16, 2);
999 .clampMaxNumElementsStrict(0,
BF16, 2);
1002 .clampMaxNumElementsStrict(0,
BF16, 2);
1008 if (ST.hasAnyPackedFP32Ops()) {
1009 FPOpActions.legalFor({
V2F32});
1010 FCanonicalizeActions.legalFor({
V2F32});
1011 StrictFPOpActions.legalFor({
V2F32});
1012 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1013 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1014 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1017 if (ST.hasAnyPackedFP64Ops()) {
1018 FPOpActions.legalFor({
V2F64});
1019 FCanonicalizeActions.legalFor({
V2F64});
1020 StrictFPOpActions.legalFor({
V2F64});
1021 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1022 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1023 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1026 auto &MinNumMaxNumIeee =
1029 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1031 MinNumMaxNumIeee.
legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F32, F64});
1032 MinNumMaxNum.
legalFor(ST.hasIEEEMinimumMaximumInsts(), {F32, F64})
1035 if (ST.has16BitInsts()) {
1036 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F16});
1037 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {F16})
1042 if (ST.hasVOP3PInsts()) {
1043 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1046 .clampMaxNumElements(0,
F16, 2);
1047 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1051 .clampMaxNumElements(0,
F16, 2);
1055 if (ST.hasAnyPackedFP64Ops()) {
1056 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F64})
1060 .clampMaxNumElements(0,
F64, 2);
1064 if (ST.hasBF16PackedInsts()) {
1065 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1066 .clampMaxNumElementsStrict(0,
BF16, 2);
1068 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1071 .clampMaxNumElementsStrict(0,
BF16, 2);
1079 if (!ST.has16BitInsts()) {
1080 MinNumMaxNumIeee.minScalar(0,
F32);
1081 MinNumMaxNum.minScalar(0,
F32);
1084 if (ST.hasVOP3PInsts()) {
1085 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1086 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1087 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1095 if (!ST.has16BitInsts()) {
1106 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1109 if (ST.hasAnyPackedFP32Ops())
1113 if (ST.has16BitInsts()) {
1116 .legalFor(ST.hasBF16TransInsts(), {BF16})
1126 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1148 if (ST.hasFractBug()) {
1162 .legalFor({{
F32, I32}, {
F64, I32}})
1182 if (ST.hasCvtPkF16F32Inst()) {
1184 .clampMaxNumElements(0,
F16, 2);
1197 if (ST.has16BitInsts()) {
1211 if (ST.hasBF16PackedInsts()) {
1214 .clampMaxNumElementsStrict(0,
BF16, 2);
1219 if (ST.hasAnyPackedFP32Ops())
1227 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1228 FMad.customFor({
F32,
F16});
1229 else if (ST.hasMadMacF32Insts())
1230 FMad.customFor({
F32});
1231 else if (ST.hasMadF16())
1232 FMad.customFor({
F16});
1237 if (ST.has16BitInsts()) {
1240 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1248 .clampMaxNumElements(0,
S16, 2)
1264 .legalFor({{
F32, I32}, {
F64, I32}})
1268 if (ST.has16BitInsts())
1276 .legalFor({{I32,
F32}, {I32,
F64}})
1277 .customFor({{I64,
F32}, {I64,
F64}})
1280 .widenScalarFor({{I16,
BF16}, {I32,
BF16}, {I64,
BF16}},
1282 if (ST.has16BitInsts())
1291 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1292 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1293 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1297 if (
ST.has16BitInsts())
1300 if (
ST.hasVCvtPkIU16F32())
1310 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1311 .clampScalar(0, I16, I64)
1315 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1321 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1325 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1326 .clampScalar(0, I16, I64)
1330 auto &RoundingActions = getActionDefinitionsBuilder(
1331 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1332 if (
ST.has16BitInsts())
1340 if (!
ST.has16BitInsts())
1343 getActionDefinitionsBuilder(G_PTR_ADD)
1349 getActionDefinitionsBuilder(G_PTRMASK)
1351 .scalarSameSizeAs(1, 0)
1355 getActionDefinitionsBuilder(G_ICMP)
1367 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1368 .legalForCartesianProduct(
1369 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1370 if (
ST.has16BitInsts()) {
1371 CmpBuilder.legalFor({{
S1,
S16}});
1380 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).
lower();
1383 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1384 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1386 if (
ST.hasSALUFloatInsts())
1387 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1390 .widenScalarToNextPow2(1)
1394 getActionDefinitionsBuilder(G_FPOW)
1396 .clampScalar(0,
F32,
F32)
1399 getActionDefinitionsBuilder(G_FPOWI)
1400 .clampScalar(0,
F32,
F32)
1404 getActionDefinitionsBuilder(G_FLOG2)
1405 .legalFor(
ST.has16BitInsts(), {F16})
1406 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1412 getActionDefinitionsBuilder(G_FEXP2)
1413 .legalFor(
ST.has16BitInsts(), {F16})
1414 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1420 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1424 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1429 getActionDefinitionsBuilder(G_CTPOP)
1431 .clampScalar(0,
S32,
S32)
1432 .widenScalarToNextPow2(1, 32)
1433 .clampScalar(1,
S32,
S64)
1435 .widenScalarToNextPow2(0, 32);
1438 if (
ST.has16BitInsts())
1439 getActionDefinitionsBuilder(G_IS_FPCLASS)
1440 .legalForCartesianProduct({
I1}, FPTypes16)
1441 .widenScalarToNextPow2(1)
1445 getActionDefinitionsBuilder(G_IS_FPCLASS)
1446 .legalForCartesianProduct({
I1}, FPTypesBase)
1447 .lowerFor({
I1,
F16})
1448 .widenScalarToNextPow2(1)
1455 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1457 .clampScalar(0,
S32,
S32)
1458 .clampScalar(1,
S32,
S64)
1459 .widenScalarToNextPow2(0, 32)
1460 .widenScalarToNextPow2(1, 32)
1464 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1467 .clampScalar(0,
S32,
S32)
1468 .clampScalar(1,
S32,
S64)
1470 .widenScalarToNextPow2(0, 32)
1471 .widenScalarToNextPow2(1, 32);
1473 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1475 .clampScalar(0,
S32,
S32)
1476 .clampScalar(1,
S32,
S64)
1478 .widenScalarToNextPow2(0, 32)
1479 .widenScalarToNextPow2(1, 32);
1481 getActionDefinitionsBuilder(G_CTLS)
1484 .clampScalar(0,
S32,
S32)
1485 .clampScalar(1,
S32,
S32);
1489 getActionDefinitionsBuilder(G_BITREVERSE)
1491 .clampScalar(0,
S32,
S64)
1493 .widenScalarToNextPow2(0);
1495 if (
ST.has16BitInsts()) {
1496 getActionDefinitionsBuilder(G_BSWAP)
1498 .clampMaxNumElementsStrict(0,
S16, 2)
1501 .widenScalarToNextPow2(0)
1502 .clampScalar(0,
S16,
S32)
1505 if (
ST.hasVOP3PInsts()) {
1506 getActionDefinitionsBuilder(G_ABS)
1508 .clampMaxNumElements(0,
S16, 2)
1510 .widenScalarToNextPow2(0)
1513 if (
ST.useMinMaxI64Insts()) {
1514 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1516 .clampMaxNumElements(0,
S16, 2)
1518 .widenScalarToNextPow2(0)
1522 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1524 .clampMaxNumElements(0,
S16, 2)
1526 .widenScalarToNextPow2(0)
1531 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1533 .widenScalarToNextPow2(0)
1540 getActionDefinitionsBuilder(G_BSWAP)
1545 .widenScalarToNextPow2(0)
1550 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1553 .widenScalarToNextPow2(0)
1558 getActionDefinitionsBuilder(G_INTTOPTR)
1560 .legalForCartesianProduct(AddrSpaces64, {
S64})
1561 .legalForCartesianProduct(AddrSpaces32, {
S32})
1574 getActionDefinitionsBuilder(G_PTRTOINT)
1576 .legalForCartesianProduct(AddrSpaces64, {
S64})
1577 .legalForCartesianProduct(AddrSpaces32, {
S32})
1590 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1594 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1595 bool IsLoad) ->
bool {
1599 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1612 !
ST.hasUsableDSOffset() && Query.
MMODescrs[0].AlignInBits == 32)
1617 unsigned NumRegs = (MemSize + 31) / 32;
1619 if (!
ST.hasDwordx3LoadStores())
1630 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1631 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1632 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1633 unsigned LocalAlign64 =
ST.hasUsableDSOffset() ? 32 : 64;
1639 for (
unsigned Op : {G_LOAD, G_STORE}) {
1640 const bool IsStore =
Op == G_STORE;
1642 auto &Actions = getActionDefinitionsBuilder(
Op);
1645 Actions.legalForTypesWithMemDesc(
1646 {{
S32, GlobalPtr,
S32, GlobalAlign32},
1649 {
S64, GlobalPtr,
S64, GlobalAlign32},
1652 {
S32, GlobalPtr,
S8, GlobalAlign8},
1653 {
S32, GlobalPtr,
S16, GlobalAlign16},
1655 {
S32, LocalPtr,
S32, 32},
1656 {
S64, LocalPtr,
S64, LocalAlign64},
1658 {
S32, LocalPtr,
S8, 8},
1659 {
S32, LocalPtr,
S16, 16},
1662 {
S32, PrivatePtr,
S32, 32},
1663 {
S32, PrivatePtr,
S8, 8},
1664 {
S32, PrivatePtr,
S16, 16},
1667 {
S32, ConstantPtr,
S32, GlobalAlign32},
1670 {
S64, ConstantPtr,
S64, GlobalAlign32}});
1672 if (IsStore ||
ST.d16PreservesUnusedBits()) {
1673 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1674 {{S16, GlobalPtr, S8, GlobalAlign8},
1675 {S16, GlobalPtr, S16, GlobalAlign16},
1676 {S16, LocalPtr, S8, 8},
1677 {S16, LocalPtr, S16, 16},
1678 {S16, PrivatePtr, S8, 8},
1679 {S16, PrivatePtr, S16, 16}});
1690 Actions.unsupportedIf(
1691 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1705 Actions.customIf(
typeIs(1, Constant32Ptr));
1731 return !Query.
Types[0].isVector() &&
1732 needToSplitMemOp(Query,
Op == G_LOAD);
1734 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1739 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1742 if (DstSize > MemSize)
1748 if (MemSize > MaxSize)
1756 return Query.
Types[0].isVector() &&
1757 needToSplitMemOp(Query,
Op == G_LOAD);
1759 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1773 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1774 if (MemSize > MaxSize) {
1778 if (MaxSize % EltSize == 0) {
1784 unsigned NumPieces = MemSize / MaxSize;
1788 if (NumPieces == 1 || NumPieces >= NumElts ||
1789 NumElts % NumPieces != 0)
1790 return std::pair(0, EltTy);
1798 return std::pair(0, EltTy);
1813 return std::pair(0, EltTy);
1818 .widenScalarToNextPow2(0)
1825 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1826 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1827 {
S32, GlobalPtr,
S16, 2 * 8},
1828 {
S32, LocalPtr,
S8, 8},
1829 {
S32, LocalPtr,
S16, 16},
1830 {
S32, PrivatePtr,
S8, 8},
1831 {
S32, PrivatePtr,
S16, 16},
1832 {
S32, ConstantPtr,
S8, 8},
1833 {
S32, ConstantPtr,
S16, 2 * 8}})
1834 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1835 {{S16, GlobalPtr, S8, GlobalAlign8},
1836 {S16, LocalPtr, S8, GlobalAlign8},
1837 {S16, PrivatePtr, S8, GlobalAlign8},
1838 {S16, ConstantPtr, S8, GlobalAlign8}})
1843 if (
ST.hasFlatAddressSpace()) {
1844 ExtLoads.legalForTypesWithMemDesc(
1845 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1847 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1848 {{S16, FlatPtr, S8, GlobalAlign8}});
1856 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1858 ExtLoads.narrowScalarIf(
1865 ExtLoads.clampScalar(0,
S32,
S32)
1866 .widenScalarToNextPow2(0)
1869 auto &Atomics = getActionDefinitionsBuilder(
1870 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1871 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1872 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1873 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1874 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1875 {
S64, GlobalPtr}, {
S64, LocalPtr},
1876 {
S32, RegionPtr}, {
S64, RegionPtr}});
1877 if (
ST.hasFlatAddressSpace()) {
1878 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1882 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1883 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1884 if (
ST.hasFlatAddressSpace()) {
1885 Atomics32.legalFor({{
S32, FlatPtr}});
1889 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1890 if (
ST.hasLDSFPAtomicAddF32()) {
1892 if (
ST.hasLdsAtomicAddF64())
1894 if (
ST.hasAtomicDsPkAdd16Insts())
1897 if (
ST.hasAtomicFaddInsts())
1899 if (
ST.hasFlatAtomicFaddF32Inst())
1902 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1906 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1909 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1910 ST.hasAtomicBufferGlobalPkAddF16Insts())
1912 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1914 if (
ST.hasAtomicFlatPkAdd16Insts())
1920 auto &AtomicFMinFMax =
1921 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1922 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1924 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1925 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1926 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1927 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1928 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1929 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1930 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1931 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1935 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1936 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1937 {
S32, FlatPtr}, {
S64, FlatPtr}})
1938 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1939 {
S32, RegionPtr}, {
S64, RegionPtr}});
1943 getActionDefinitionsBuilder(G_SELECT)
1945 LocalPtr, FlatPtr, PrivatePtr,
1949 .clampScalar(0,
S16,
S64)
1953 .clampMaxNumElements(0,
S32, 2)
1954 .clampMaxNumElements(0, LocalPtr, 2)
1955 .clampMaxNumElements(0, PrivatePtr, 2)
1957 .widenScalarToNextPow2(0)
1962 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1964 if (
ST.has16BitInsts()) {
1965 if (
ST.hasVOP3PInsts()) {
1967 .clampMaxNumElements(0,
S16, 2);
1969 Shifts.legalFor({{
S16,
S16}});
1972 Shifts.widenScalarIf(
1977 const LLT AmountTy = Query.
Types[1];
1983 Shifts.clampScalar(1,
S32,
S32);
1984 Shifts.widenScalarToNextPow2(0, 16);
1985 Shifts.clampScalar(0,
S16,
S64);
1987 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1995 Shifts.clampScalar(1,
S32,
S32);
1996 Shifts.widenScalarToNextPow2(0, 32);
1997 Shifts.clampScalar(0,
S32,
S64);
1999 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2004 Shifts.scalarize(0);
2006 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
2007 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
2008 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
2009 unsigned IdxTypeIdx = 2;
2011 getActionDefinitionsBuilder(
Op)
2013 const LLT EltTy = Query.
Types[EltTypeIdx];
2014 const LLT VecTy = Query.
Types[VecTypeIdx];
2015 const LLT IdxTy = Query.
Types[IdxTypeIdx];
2017 const bool isLegalVecType =
2027 return (EltSize == 32 || EltSize == 64) &&
2043 const LLT EltTy = Query.
Types[EltTypeIdx];
2044 const LLT VecTy = Query.
Types[VecTypeIdx];
2048 const unsigned TargetEltSize =
2049 DstEltSize % 64 == 0 ? 64 : 32;
2050 return std::pair(VecTypeIdx,
2054 .clampScalar(EltTypeIdx,
S32,
S64)
2055 .clampScalar(VecTypeIdx,
S32,
S64)
2056 .clampScalar(IdxTypeIdx,
S32,
S32)
2057 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2066 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2068 const LLT &EltTy = Query.
Types[1].getElementType();
2069 return Query.
Types[0] != EltTy;
2072 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2073 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2074 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2075 getActionDefinitionsBuilder(
Op)
2078 const LLT BigTy = Query.
Types[BigTyIdx];
2084 const LLT LitTy = Query.
Types[LitTyIdx];
2089 .widenScalarToNextPow2(BigTyIdx, 32)
2097 const LLT BigTy = Query.
Types[BigTyIdx];
2098 const LLT LitTy = Query.
Types[LitTyIdx];
2106 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2116 if (
ST.hasScalarPackInsts()) {
2119 .minScalarOrElt(0,
S16)
2122 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2126 BuildVector.customFor({
V2S16,
S16});
2127 BuildVector.minScalarOrElt(0,
S32);
2129 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2137 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2139 .clampMaxNumElements(0,
S32, 32)
2140 .clampMaxNumElements(1,
S16, 2)
2141 .clampMaxNumElements(0,
S16, 64);
2143 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2146 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2147 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2148 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2150 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2151 const LLT Ty = Query.
Types[TypeIdx];
2163 getActionDefinitionsBuilder(
Op)
2167 const LLT BigTy = Query.
Types[BigTyIdx];
2173 .widenScalarToNextPow2(LitTyIdx, 16)
2182 .clampScalar(LitTyIdx,
S32,
S512)
2183 .widenScalarToNextPow2(LitTyIdx, 32)
2187 return notValidElt(Query, LitTyIdx);
2192 return notValidElt(Query, BigTyIdx);
2197 if (
Op == G_MERGE_VALUES) {
2198 Builder.widenScalarIf(
2201 const LLT Ty = Query.
Types[LitTyIdx];
2207 Builder.widenScalarIf(
2209 const LLT Ty = Query.
Types[BigTyIdx];
2215 const LLT &Ty = Query.
Types[BigTyIdx];
2217 if (NewSizeInBits >= 256) {
2219 if (RoundedTo < NewSizeInBits)
2220 NewSizeInBits = RoundedTo;
2222 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2231 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2232 .legalFor({{
S32}, {
S64}})
2233 .clampScalar(0,
S32,
S64);
2235 if (
ST.hasVOP3PInsts()) {
2236 SextInReg.lowerFor({{
V2S16}})
2240 .clampMaxNumElementsStrict(0,
S16, 2);
2241 }
else if (
ST.has16BitInsts()) {
2242 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2246 SextInReg.lowerFor({{
S32}, {
S64}});
2251 .clampScalar(0,
S32,
S64)
2254 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2258 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2259 FSHRActionDefs.legalFor({{
S32,
S32}})
2260 .clampMaxNumElementsStrict(0,
S16, 2);
2261 if (
ST.hasVOP3PInsts())
2263 FSHRActionDefs.scalarize(0).lower();
2265 if (
ST.hasVOP3PInsts()) {
2266 getActionDefinitionsBuilder(G_FSHL)
2268 .clampMaxNumElementsStrict(0,
S16, 2)
2272 getActionDefinitionsBuilder(G_FSHL)
2277 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2280 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2282 getActionDefinitionsBuilder(G_FENCE)
2285 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2290 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2292 .clampScalar(1,
S32,
S32)
2293 .clampScalar(0,
S32,
S64)
2294 .widenScalarToNextPow2(0)
2297 getActionDefinitionsBuilder(
2301 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2307 if (
ST.hasIEEEMinimumMaximumInsts()) {
2308 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2309 .legalFor(FPTypesPK16)
2310 .clampMaxNumElements(0,
F16, 2)
2312 }
else if (
ST.hasVOP3PInsts()) {
2313 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2315 .clampMaxNumElementsStrict(0,
F16, 2)
2319 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2321 .clampScalar(0,
F32,
F64)
2325 getActionDefinitionsBuilder(
2326 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2329 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2331 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2332 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2333 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2336 getActionDefinitionsBuilder(G_PREFETCH)
2337 .customFor({Constant32Ptr})
2340 getActionDefinitionsBuilder(
2341 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2342 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2343 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2344 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2349 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2350 G_INTRINSIC_CONVERGENT,
2351 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2363 switch (
MI.getOpcode()) {
2364 case TargetOpcode::G_ADDRSPACE_CAST:
2366 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2368 case TargetOpcode::G_FCEIL:
2370 case TargetOpcode::G_FREM:
2372 case TargetOpcode::G_INTRINSIC_TRUNC:
2374 case TargetOpcode::G_SITOFP:
2376 case TargetOpcode::G_UITOFP:
2378 case TargetOpcode::G_FPTOSI:
2380 case TargetOpcode::G_FPTOUI:
2382 case TargetOpcode::G_FMINNUM:
2383 case TargetOpcode::G_FMAXNUM:
2384 case TargetOpcode::G_FMINIMUMNUM:
2385 case TargetOpcode::G_FMAXIMUMNUM:
2387 case TargetOpcode::G_EXTRACT:
2389 case TargetOpcode::G_INSERT:
2391 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2393 case TargetOpcode::G_INSERT_VECTOR_ELT:
2395 case TargetOpcode::G_FSIN:
2396 case TargetOpcode::G_FCOS:
2398 case TargetOpcode::G_GLOBAL_VALUE:
2400 case TargetOpcode::G_LOAD:
2401 case TargetOpcode::G_SEXTLOAD:
2402 case TargetOpcode::G_ZEXTLOAD:
2403 case TargetOpcode::G_PREFETCH:
2405 case TargetOpcode::G_STORE:
2407 case TargetOpcode::G_FMAD:
2409 case TargetOpcode::G_FDIV:
2411 case TargetOpcode::G_FFREXP:
2413 case TargetOpcode::G_FSQRT:
2415 case TargetOpcode::G_UDIV:
2416 case TargetOpcode::G_UREM:
2417 case TargetOpcode::G_UDIVREM:
2419 case TargetOpcode::G_SDIV:
2420 case TargetOpcode::G_SREM:
2421 case TargetOpcode::G_SDIVREM:
2423 case TargetOpcode::G_ATOMIC_CMPXCHG:
2425 case TargetOpcode::G_FLOG2:
2427 case TargetOpcode::G_FLOG:
2428 case TargetOpcode::G_FLOG10:
2430 case TargetOpcode::G_FEXP2:
2432 case TargetOpcode::G_FEXP:
2433 case TargetOpcode::G_FEXP10:
2435 case TargetOpcode::G_FPOW:
2437 case TargetOpcode::G_FFLOOR:
2439 case TargetOpcode::G_BUILD_VECTOR:
2440 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2442 case TargetOpcode::G_MUL:
2444 case TargetOpcode::G_CTLZ:
2445 case TargetOpcode::G_CTTZ:
2447 case TargetOpcode::G_CTLS:
2449 case TargetOpcode::G_CTLZ_ZERO_POISON:
2451 case TargetOpcode::G_STACKSAVE:
2453 case TargetOpcode::G_GET_FPENV:
2455 case TargetOpcode::G_SET_FPENV:
2457 case TargetOpcode::G_TRAP:
2459 case TargetOpcode::G_DEBUGTRAP:
2471 unsigned BaseAS = AS;
2476 Register Aperture = getBaseSegmentAperture(BaseAS,
MRI,
B);
2480 auto Tag =
B.buildConstant(
S32, SANum);
2481 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2487Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2497 if (ST.hasApertureRegs()) {
2501 const unsigned ApertureRegNo =
2502 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2503 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2504 !ST.hasGloballyAddressableScratch()) &&
2505 "Cannot use src_private_base with globally addressable scratch!");
2506 Register Dst =
MRI.createGenericVirtualRegister(I64);
2507 MRI.setRegClass(Dst, &AMDGPU::SReg_64RegClass);
2508 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2509 return B.buildUnmerge(I32, Dst).getReg(1);
2524 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2540 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2543 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2557 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2565 B.buildObjectPtrOffset(
2568 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2576 switch (Def->getOpcode()) {
2577 case AMDGPU::G_FRAME_INDEX:
2578 case AMDGPU::G_GLOBAL_VALUE:
2579 case AMDGPU::G_BLOCK_ADDR:
2581 case AMDGPU::G_CONSTANT: {
2582 const ConstantInt *CI = Def->getOperand(1).getCImm();
2597 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2603 LLT DstTy =
MRI.getType(Dst);
2604 LLT SrcTy =
MRI.getType(Src);
2606 unsigned SrcAS = SrcTy.getAddressSpace();
2620 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2627 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2629 ST.hasGloballyAddressableScratch()) {
2632 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2634 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2635 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2637 MRI.setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2638 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2639 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2642 return B.buildExtract(Dst, Src, 0).getReg(0);
2646 castFlatToLocalOrPrivate(Dst);
2647 MI.eraseFromParent();
2653 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2654 auto FlatNull =
B.buildConstant(SrcTy, 0);
2657 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2661 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2663 MI.eraseFromParent();
2670 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2673 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2676 ST.hasGloballyAddressableScratch()) {
2680 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2681 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2685 if (ST.isWave64()) {
2686 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2692 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2693 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2695 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2699 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2700 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2702 MRI.setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2703 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2712 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2716 castLocalOrPrivateToFlat(Dst);
2717 MI.eraseFromParent();
2721 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2728 SegmentNull.getReg(0));
2730 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2732 MI.eraseFromParent();
2737 SrcTy.getSizeInBits() == 64) {
2739 B.buildExtract(Dst, Src, 0);
2740 MI.eraseFromParent();
2747 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2748 auto PtrLo =
B.buildPtrToInt(I32, Src);
2749 if (AddrHiVal == 0) {
2750 auto Zext =
B.buildZExt(I64, PtrLo);
2751 B.buildIntToPtr(Dst, Zext);
2753 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2754 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2757 MI.eraseFromParent();
2764 MI.eraseFromParent();
2772 LLT Ty =
MRI.getType(Src);
2773 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2778 auto C1 =
B.buildFConstant(Ty, C1Val);
2779 auto CopySign =
B.buildFCopysign(Ty,
C1, Src);
2782 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2783 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2785 auto C2 =
B.buildFConstant(Ty, C2Val);
2786 auto Fabs =
B.buildFAbs(Ty, Src);
2789 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2790 MI.eraseFromParent();
2807 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2809 const auto Zero =
B.buildFConstant(
F64, 0.0);
2810 const auto One =
B.buildFConstant(
F64, 1.0);
2813 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2817 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2818 MI.eraseFromParent();
2826 Register Src0Reg =
MI.getOperand(1).getReg();
2827 Register Src1Reg =
MI.getOperand(2).getReg();
2828 auto Flags =
MI.getFlags();
2829 LLT Ty =
MRI.getType(DstReg);
2831 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2832 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2833 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2834 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2835 MI.eraseFromParent();
2841 const unsigned FractBits = 52;
2842 const unsigned ExpBits = 11;
2845 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2846 auto Const1 =
B.buildConstant(I32, ExpBits);
2848 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2850 .addUse(Const0.getReg(0))
2851 .addUse(Const1.getReg(0));
2853 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2866 auto SrcInt =
B.buildBitcast(I64, Src);
2869 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2876 const unsigned FractBits = 52;
2879 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2880 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2882 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2884 const auto Zero32 =
B.buildConstant(I32, 0);
2887 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2889 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2890 auto Not =
B.buildNot(I64, Shr);
2891 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2892 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2897 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2898 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2899 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2900 MI.eraseFromParent();
2916 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2917 auto ThirtyTwo =
B.buildConstant(I32, 32);
2919 if (
MRI.getType(Dst) ==
F64) {
2920 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2921 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2923 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2924 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2927 B.buildFAdd(Dst, LdExp, CvtLo);
2928 MI.eraseFromParent();
2934 auto One =
B.buildConstant(I32, 1);
2938 auto ThirtyOne =
B.buildConstant(I32, 31);
2939 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2940 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2941 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2942 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2943 .addUse(Unmerge.getReg(1));
2944 auto LS2 =
B.buildSub(I32, LS, One);
2945 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2947 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2948 auto Norm =
B.buildShl(I64, Src, ShAmt);
2949 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2950 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2951 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2952 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2953 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2954 B.buildFLdexp(Dst, FVal, Scale);
2955 MI.eraseFromParent();
2972 const LLT SrcLT =
MRI.getType(Src);
2975 unsigned Flags =
MI.getFlags();
2986 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2994 auto SrcInt =
B.buildBitcast(I32, Src);
2995 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2996 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
3000 K0 =
B.buildFConstant(
3002 K1 =
B.buildFConstant(
3005 K0 =
B.buildFConstant(
3007 K1 =
B.buildFConstant(
3011 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
3012 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
3013 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
3015 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
3016 :
B.buildFPTOUI(I32, FloorMul);
3017 auto Lo =
B.buildFPTOUI(I32, Fma);
3023 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}),
Sign),
3026 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3027 MI.eraseFromParent();
3050 uint64_t
Offset =
MI.getOperand(2).getImm();
3058 const LLT DstTy =
MRI.getType(DstReg);
3059 unsigned StartIdx =
Offset / 32;
3063 if (DstCount == 1) {
3065 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3068 MRI.replaceRegWith(DstReg, Unmerge.getReg(StartIdx));
3073 for (
unsigned I = 0;
I < DstCount; ++
I)
3074 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3075 B.buildMergeLikeInstr(DstReg, MergeVec);
3078 MI.eraseFromParent();
3088 Register InsertSrc =
MI.getOperand(2).getReg();
3089 uint64_t
Offset =
MI.getOperand(3).getImm();
3091 unsigned DstSize =
MRI.getType(DstReg).getSizeInBits();
3092 const LLT InsertTy =
MRI.getType(InsertSrc);
3097 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3101 unsigned DstCount = DstSize / 32;
3102 unsigned InsertCount = InsertSize / 32;
3103 unsigned StartIdx =
Offset / 32;
3105 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3108 for (
unsigned I = 0;
I < StartIdx; ++
I)
3111 if (InsertCount == 1) {
3115 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3118 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3119 for (
unsigned I = 0;
I < InsertCount; ++
I)
3123 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3126 B.buildMergeLikeInstr(DstReg, MergeVec);
3128 MI.eraseFromParent();
3142 LLT VecTy =
MRI.getType(Vec);
3155 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3156 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3157 B.buildIntToPtr(Dst, IntElt);
3159 MI.eraseFromParent();
3166 std::optional<ValueAndVReg> MaybeIdxVal =
3170 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3173 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3174 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3179 MI.eraseFromParent();
3194 LLT VecTy =
MRI.getType(Vec);
3208 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3209 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3210 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3212 B.buildIntToPtr(Dst, IntVecDest);
3213 MI.eraseFromParent();
3220 std::optional<ValueAndVReg> MaybeIdxVal =
3225 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3228 if (IdxVal < NumElts) {
3230 for (
unsigned i = 0; i < NumElts; ++i)
3231 SrcRegs.
push_back(
MRI.createGenericVirtualRegister(EltTy));
3232 B.buildUnmerge(SrcRegs, Vec);
3234 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3235 B.buildMergeLikeInstr(Dst, SrcRegs);
3240 MI.eraseFromParent();
3250 LLT Ty =
MRI.getType(DstReg);
3251 unsigned Flags =
MI.getFlags();
3255 if (ST.hasTrigReducedRange()) {
3256 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3257 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3258 .addUse(MulVal.getReg(0))
3262 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3265 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3269 MI.eraseFromParent();
3277 unsigned GAFlags)
const {
3308 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass, PCRegTy});
3310 if (ST.has64BitLiterals()) {
3314 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3318 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3329 B.buildExtract(DstReg, PCReg, 0);
3331 B.buildCopy(DstReg, PCReg);
3341 if (RequiresHighHalf && ST.has64BitLiterals()) {
3343 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass, PtrTy});
3344 B.buildInstr(AMDGPU::S_MOV_B64)
3347 B.buildCopy(DstReg, Addr);
3352 Register AddrLo =
MRI.createVirtualRegister({&AMDGPU::SReg_32RegClass, I32});
3355 B.buildInstr(AMDGPU::S_MOV_B32)
3360 if (RequiresHighHalf) {
3362 "Must provide a 64-bit pointer type!");
3365 MRI.createVirtualRegister({&AMDGPU::SReg_32RegClass, I32});
3367 B.buildInstr(AMDGPU::S_MOV_B32)
3372 MRI.createVirtualRegister({&AMDGPU::SReg_64RegClass,
LLT::integer(64)});
3374 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3375 B.buildCast(DstReg, AddrDst);
3377 B.buildCast(DstReg, AddrLo);
3385 LLT Ty =
MRI.getType(DstReg);
3386 unsigned AS = Ty.getAddressSpace();
3397 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3399 B.buildUndef(DstReg);
3400 MI.eraseFromParent();
3404 B.buildConstant(DstReg,
3406 MI.eraseFromParent();
3412 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3415 Fn,
"local memory global used by non-kernel function",
3424 B.buildUndef(DstReg);
3425 MI.eraseFromParent();
3433 if (!
TLI->shouldUseLDSConstAddress(GV)) {
3449 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3450 B.buildIntToPtr(DstReg, Sz);
3451 MI.eraseFromParent();
3457 MI.eraseFromParent();
3461 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3463 MI.eraseFromParent();
3469 if (
TLI->shouldEmitFixup(GV)) {
3471 MI.eraseFromParent();
3475 if (
TLI->shouldEmitPCReloc(GV)) {
3477 MI.eraseFromParent();
3482 Register GOTAddr =
MRI.createGenericVirtualRegister(PtrTy);
3493 if (Ty.getSizeInBits() == 32) {
3495 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3496 B.buildExtract(DstReg,
Load, 0);
3498 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3500 MI.eraseFromParent();
3517 unsigned PtrIdx =
MI.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3518 Register PtrReg =
MI.getOperand(PtrIdx).getReg();
3519 LLT PtrTy =
MRI.getType(PtrReg);
3524 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3526 MI.getOperand(PtrIdx).setReg(Cast.getReg(0));
3531 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3535 LLT ValTy =
MRI.getType(ValReg);
3549 const uint64_t AlignInBits = 8 * MemAlign.
value();
3557 if (WideMemSize == ValSize) {
3563 MI.setMemRefs(MF, {WideMMO});
3569 if (ValSize > WideMemSize)
3576 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3577 B.buildTrunc(ValReg, WideLoad).getReg(0);
3584 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3585 B.buildExtract(ValReg, WideLoad, 0);
3589 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3590 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3594 MI.eraseFromParent();
3607 Register DataReg =
MI.getOperand(0).getReg();
3608 LLT DataTy =
MRI.getType(DataReg);
3622 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
3652 "this should not have been custom lowered");
3654 LLT ValTy =
MRI.getType(CmpVal);
3657 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3659 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3663 .setMemRefs(
MI.memoperands());
3665 MI.eraseFromParent();
3673 switch (
DefMI->getOpcode()) {
3674 case TargetOpcode::G_INTRINSIC: {
3676 case Intrinsic::amdgcn_frexp_mant:
3677 case Intrinsic::amdgcn_log:
3678 case Intrinsic::amdgcn_log_clamp:
3679 case Intrinsic::amdgcn_exp2:
3680 case Intrinsic::amdgcn_sqrt:
3688 case TargetOpcode::G_FSQRT:
3690 case TargetOpcode::G_FFREXP: {
3691 if (
DefMI->getOperand(0).getReg() == Src)
3695 case TargetOpcode::G_FPEXT: {
3696 return MRI.getType(
DefMI->getOperand(1).getReg()) ==
F16;
3716std::pair<Register, Register>
3718 unsigned Flags)
const {
3722 auto SmallestNormal =
B.buildFConstant(
3724 auto IsLtSmallestNormal =
3727 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3728 auto One =
B.buildFConstant(
F32, 1.0);
3730 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3731 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3733 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3746 LLT Ty =
B.getMRI()->getType(Dst);
3747 unsigned Flags =
MI.getFlags();
3751 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3752 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3753 .addUse(Ext.getReg(0))
3755 B.buildFPTrunc(Dst,
Log2, Flags);
3756 MI.eraseFromParent();
3764 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3767 MI.eraseFromParent();
3771 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3772 .addUse(ScaledInput)
3775 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3776 auto Zero =
B.buildFConstant(Ty, 0.0);
3778 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo,
Zero, Flags);
3779 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3781 MI.eraseFromParent();
3787 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3788 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3793 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3794 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3799 unsigned Flags =
MI.getFlags();
3800 const LLT Ty =
MRI.getType(
X);
3809 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3811 B.buildFPTrunc(Dst, LogVal, Flags);
3816 MI.eraseFromParent();
3825 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3828 if (ST.hasFastFMAF32()) {
3830 const float c_log10 = 0x1.344134p-2f;
3831 const float cc_log10 = 0x1.09f79ep-26f;
3834 const float c_log = 0x1.62e42ep-1f;
3835 const float cc_log = 0x1.efa39ep-25f;
3837 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3838 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3842 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3843 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3844 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3845 auto FMA1 =
B.buildFMA(Ty,
Y,
CC, FMA0, NewFlags);
3846 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3849 const float ch_log10 = 0x1.344000p-2f;
3850 const float ct_log10 = 0x1.3509f6p-18f;
3853 const float ch_log = 0x1.62e000p-1f;
3854 const float ct_log = 0x1.0bfbe8p-15f;
3856 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3857 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3860 auto YInt =
B.buildBitcast(I32,
Y);
3861 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3862 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3863 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3867 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3870 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3872 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3875 const bool IsFiniteOnly =
3878 if (!IsFiniteOnly) {
3881 auto Fabs =
B.buildFAbs(Ty,
Y);
3884 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3888 auto Zero =
B.buildFConstant(Ty, 0.0);
3890 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3891 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK,
Zero, Flags);
3892 B.buildFSub(Dst, R, Shift, Flags);
3894 B.buildCopy(Dst, R);
3897 MI.eraseFromParent();
3903 unsigned Flags)
const {
3904 const double Log2BaseInverted =
3907 LLT Ty =
B.getMRI()->getType(Dst);
3912 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3913 .addUse(ScaledInput)
3915 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3916 auto Zero =
B.buildFConstant(Ty, 0.0);
3918 B.buildSelect(Ty, IsScaled, ScaledResultOffset,
Zero, Flags);
3919 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3921 if (ST.hasFastFMAF32())
3922 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3924 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3925 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3932 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3933 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3936 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3937 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3948 unsigned Flags =
MI.getFlags();
3949 LLT Ty =
B.getMRI()->getType(Dst);
3956 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3957 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3958 .addUse(Ext.getReg(0))
3960 B.buildFPTrunc(Dst,
Log2, Flags);
3961 MI.eraseFromParent();
3971 MI.eraseFromParent();
3979 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3981 RangeCheckConst, Flags);
3983 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3984 auto Zero =
B.buildFConstant(Ty, 0.0);
3985 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour,
Zero, Flags);
3986 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3988 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3989 .addUse(AddInput.getReg(0))
3992 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3993 auto One =
B.buildFConstant(Ty, 1.0);
3994 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3995 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3996 MI.eraseFromParent();
4001 const SrcOp &Src,
unsigned Flags) {
4002 LLT Ty = Dst.getLLTTy(*
B.getMRI());
4005 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
4006 .addUse(Src.getReg())
4009 return B.buildFExp2(Dst, Src, Flags);
4015 bool IsExp10)
const {
4016 LLT Ty =
B.getMRI()->getType(
X);
4020 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
4021 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4028 LLT Ty =
B.getMRI()->getType(Dst);
4034 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4037 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4038 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4039 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4042 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4044 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4045 .addUse(ExpInput.getReg(0))
4048 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4049 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4050 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4056 unsigned Flags)
const {
4057 LLT Ty =
B.getMRI()->getType(Dst);
4061 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4062 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4064 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4065 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4066 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4067 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4068 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4078 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4082 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4083 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4084 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4086 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4087 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4089 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4090 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4091 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4092 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4094 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4095 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4096 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4098 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4116 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4118 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4120 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4122 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4123 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4124 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4125 T =
B.buildFMA(
F64,
F,
C1, Mul2, Flags).getReg(0);
4127 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4128 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4129 auto Mul =
B.buildFMul(
F64,
X,
C1, Flags).getReg(0);
4130 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4132 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4133 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4134 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4135 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4136 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4138 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4139 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4140 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4141 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4144 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4145 auto Mul =
B.buildFMul(
F64,
X,
C1, Flags).getReg(0);
4146 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4148 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4149 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4150 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4151 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4152 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4156 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4157 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4159 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4161 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4163 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4165 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4167 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4168 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4169 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4170 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4172 auto One =
B.buildFConstant(
F64, 1.0);
4173 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4174 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4177 auto DnInt =
B.buildFPTOSI(I32, Dn);
4178 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4185 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4192 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z,
Zero, Flags);
4194 MI.eraseFromParent();
4202 const unsigned Flags =
MI.getFlags();
4205 LLT Ty =
MRI.getType(Dst);
4210 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4218 MI.eraseFromParent();
4229 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4232 B.buildFPTrunc(Dst, Lowered, Flags);
4233 MI.eraseFromParent();
4244 MI.eraseFromParent();
4272 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4275 if (ST.hasFastFMAF32()) {
4277 const float cc_exp = 0x1.4ae0bep-26f;
4278 const float c_exp10 = 0x1.a934f0p+1f;
4279 const float cc_exp10 = 0x1.2f346ep-24f;
4281 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4282 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4283 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4284 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4286 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4287 PL =
B.buildFMA(Ty,
X,
CC, FMA0, Flags).getReg(0);
4289 const float ch_exp = 0x1.714000p+0f;
4290 const float cl_exp = 0x1.47652ap-12f;
4292 const float ch_exp10 = 0x1.a92000p+1f;
4293 const float cl_exp10 = 0x1.4f0978p-11f;
4296 auto XInt =
B.buildBitcast(I32,
X);
4297 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4298 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4299 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4301 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4302 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4304 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4305 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4308 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4309 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4312 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4315 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4316 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4318 auto IntE =
B.buildFPTOSI(I32, E);
4320 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4321 .addUse(
A.getReg(0))
4323 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4325 auto UnderflowCheckConst =
4326 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4327 auto Zero =
B.buildFConstant(Ty, 0.0);
4331 R =
B.buildSelect(Ty, Underflow,
Zero, R);
4334 auto OverflowCheckConst =
4335 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4340 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4343 B.buildCopy(Dst, R);
4344 MI.eraseFromParent();
4355 unsigned Flags =
MI.getFlags();
4364 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4366 .setMIFlags(CoreFlags);
4367 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4369 .addUse(Log.getReg(0))
4370 .setMIFlags(CoreFlags);
4372 MI.eraseFromParent();
4376 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4377 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4378 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4380 .addUse(Log.getReg(0))
4381 .setMIFlags(CoreFlags);
4386 .signBitIsZeroOrNaN()) {
4387 B.buildFExp2(Dst,
Mul, CoreFlags);
4388 MI.eraseFromParent();
4394 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4396 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4397 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4398 auto YIsOdd =
B.buildAnd(
4402 auto Neg =
B.buildFCopysign(
F32, R,
X);
4404 B.buildSelect(Dst, YIsOdd, Neg, R);
4405 MI.eraseFromParent();
4408 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4415 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4417 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4419 B.buildSelect(Dst, NegNonInt, NaN, R);
4421 MI.eraseFromParent();
4429 ModSrc = SrcFNeg->getOperand(1).getReg();
4431 ModSrc = SrcFAbs->getOperand(1).getReg();
4433 ModSrc = SrcFAbs->getOperand(1).getReg();
4443 Register OrigSrc =
MI.getOperand(1).getReg();
4444 unsigned Flags =
MI.getFlags();
4446 "this should not have been custom lowered");
4456 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4475 if (MFI->
getMode().
IEEE && !ST.hasIEEEMinimumMaximumInsts())
4476 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4478 B.buildFMinNum(Min, Fract, Const, Flags);
4483 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4486 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4487 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4489 MI.eraseFromParent();
4501 MRI.getType(Dst).getNumElements() == 2 &&
4502 MRI.getType(Dst).getScalarSizeInBits() == 16);
4507 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4509 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4510 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4513 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4514 B.buildBitcast(Dst,
Merge);
4516 MI.eraseFromParent();
4533 bool UsePartialMad64_32,
4534 bool SeparateOddAlignedProducts)
const {
4549 auto getZero32 = [&]() ->
Register {
4551 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4554 auto getZero64 = [&]() ->
Register {
4556 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4561 for (
unsigned i = 0; i < Src0.size(); ++i) {
4572 if (CarryIn.empty())
4575 bool HaveCarryOut =
true;
4577 if (CarryIn.size() == 1) {
4579 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4583 CarryAccum = getZero32();
4585 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4586 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4588 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4593 LocalAccum = getZero32();
4594 HaveCarryOut =
false;
4599 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4600 LocalAccum =
Add.getReg(0);
4614 auto buildMadChain =
4617 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4618 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4625 if (LocalAccum.size() == 1 &&
4626 (!UsePartialMad64_32 || !CarryIn.empty())) {
4629 unsigned j1 = DstIndex - j0;
4630 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4634 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4636 LocalAccum[0] =
Mul.getReg(0);
4638 if (CarryIn.empty()) {
4639 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4642 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4648 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4652 if (j0 <= DstIndex) {
4653 bool HaveSmallAccum =
false;
4656 if (LocalAccum[0]) {
4657 if (LocalAccum.size() == 1) {
4658 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4659 HaveSmallAccum =
true;
4660 }
else if (LocalAccum[1]) {
4661 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4662 HaveSmallAccum =
false;
4664 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4665 HaveSmallAccum =
true;
4668 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4670 HaveSmallAccum =
true;
4674 unsigned j1 = DstIndex - j0;
4675 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4679 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4680 {Src0[j0], Src1[j1], Tmp});
4681 Tmp = Mad.getReg(0);
4682 if (!HaveSmallAccum)
4683 CarryOut.push_back(Mad.getReg(1));
4684 HaveSmallAccum =
false;
4687 }
while (j0 <= DstIndex);
4689 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4690 LocalAccum[0] = Unmerge.getReg(0);
4691 if (LocalAccum.size() > 1)
4692 LocalAccum[1] = Unmerge.getReg(1);
4699 LocalAccum[0] = getZero32();
4703 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4704 "Uninitialized accumulator part");
4730 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4731 Carry OddCarryIn = std::move(OddCarry);
4732 Carry EvenCarryIn = std::move(EvenCarry);
4737 if (2 * i < Accum.
size()) {
4738 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4739 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4744 if (!SeparateOddAlignedProducts) {
4745 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4746 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4748 bool IsHighest = 2 * i >= Accum.
size();
4751 .take_front(IsHighest ? 1 : 2);
4752 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4758 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4760 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4762 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4765 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4768 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4769 Lo->getOperand(1).getReg());
4770 Accum[2 * i] =
Hi.getReg(0);
4771 SeparateOddCarry =
Hi.getReg(1);
4778 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4779 EvenCarryIn.push_back(CarryOut);
4781 if (2 * i < Accum.
size()) {
4782 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4783 OddCarry.push_back(CarryOut);
4795 assert(ST.hasMad64_32());
4796 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4805 LLT Ty =
MRI.getType(DstReg);
4808 unsigned Size = Ty.getSizeInBits();
4809 if (ST.useVMulU64Inst() &&
Size == 64)
4824 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4828 for (
unsigned i = 0; i <
NumParts; ++i) {
4829 Src0Parts.
push_back(
MRI.createGenericVirtualRegister(I32));
4830 Src1Parts.
push_back(
MRI.createGenericVirtualRegister(I32));
4832 B.buildUnmerge(Src0Parts, Src0);
4833 B.buildUnmerge(Src1Parts, Src1);
4836 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4837 SeparateOddAlignedProducts);
4839 B.buildMergeLikeInstr(DstReg, AccumRegs);
4840 MI.eraseFromParent();
4852 LLT DstTy =
MRI.getType(Dst);
4853 LLT SrcTy =
MRI.getType(Src);
4855 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4856 ? AMDGPU::G_AMDGPU_FFBH_U32
4857 : AMDGPU::G_AMDGPU_FFBL_B32;
4858 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4861 MI.eraseFromParent();
4870 LLT SrcTy =
MRI.getType(Src);
4871 TypeSize NumBits = SrcTy.getSizeInBits();
4876 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4877 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4878 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4879 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4880 B.buildTrunc(Dst, Ctlz);
4881 MI.eraseFromParent();
4890 LLT SrcTy =
MRI.getType(Src);
4892 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4893 unsigned BitWidth = SrcTy.getSizeInBits();
4895 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4896 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4897 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4898 MI.eraseFromParent();
4904 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4907 return ConstVal == -1;
4914 Register CondDef =
MI.getOperand(0).getReg();
4915 if (!
MRI.hasOneNonDBGUse(CondDef))
4923 if (!
MRI.hasOneNonDBGUse(NegatedCond))
4929 UseMI = &*
MRI.use_instr_nodbg_begin(NegatedCond);
4933 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4942 UncondBrTarget = &*NextMBB;
4944 if (
Next->getOpcode() != AMDGPU::G_BR)
4963 *ArgRC,
B.getDebugLoc(), ArgTy);
4967 const unsigned Mask = Arg->
getMask();
4975 auto ShiftAmt =
B.buildConstant(I32, Shift);
4976 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4979 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4981 B.buildCopy(DstReg, LiveIn);
4991 if (!ST.hasClusters()) {
4994 MI.eraseFromParent();
5006 Register ClusterIdXYZ =
MRI.createGenericVirtualRegister(I32);
5007 Register ClusterMaxIdXYZ =
MRI.createGenericVirtualRegister(I32);
5008 Register ClusterWorkGroupIdXYZ =
MRI.createGenericVirtualRegister(I32);
5014 auto One =
B.buildConstant(I32, 1);
5015 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
5016 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
5017 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
5024 B.buildCopy(DstReg, GlobalIdXYZ);
5025 MI.eraseFromParent();
5029 B.buildCopy(DstReg, ClusterIdXYZ);
5030 MI.eraseFromParent();
5035 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5036 Register ClusterId =
MRI.createGenericVirtualRegister(I32);
5037 MRI.setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5038 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5040 .addImm(ClusterIdField);
5041 auto Zero =
B.buildConstant(I32, 0);
5044 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5045 MI.eraseFromParent();
5087 auto LoadConstant = [&](
unsigned N) {
5088 B.buildConstant(DstReg,
N);
5092 if (ST.hasArchitectedSGPRs() &&
5100 Arg = &WorkGroupIDX;
5101 ArgRC = &AMDGPU::SReg_32RegClass;
5105 Arg = &WorkGroupIDY;
5106 ArgRC = &AMDGPU::SReg_32RegClass;
5110 Arg = &WorkGroupIDZ;
5111 ArgRC = &AMDGPU::SReg_32RegClass;
5115 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5116 return LoadConstant(0);
5117 Arg = &ClusterWorkGroupIDX;
5118 ArgRC = &AMDGPU::SReg_32RegClass;
5122 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5123 return LoadConstant(0);
5124 Arg = &ClusterWorkGroupIDY;
5125 ArgRC = &AMDGPU::SReg_32RegClass;
5129 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5130 return LoadConstant(0);
5131 Arg = &ClusterWorkGroupIDZ;
5132 ArgRC = &AMDGPU::SReg_32RegClass;
5137 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5138 Arg = &ClusterWorkGroupMaxIDX;
5139 ArgRC = &AMDGPU::SReg_32RegClass;
5144 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5145 Arg = &ClusterWorkGroupMaxIDY;
5146 ArgRC = &AMDGPU::SReg_32RegClass;
5151 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5152 Arg = &ClusterWorkGroupMaxIDZ;
5153 ArgRC = &AMDGPU::SReg_32RegClass;
5157 Arg = &ClusterWorkGroupMaxFlatID;
5158 ArgRC = &AMDGPU::SReg_32RegClass;
5173 return LoadConstant(0);
5178 B.buildUndef(DstReg);
5182 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5194 MI.eraseFromParent();
5200 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5201 MI.eraseFromParent();
5208 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5222 B.buildUndef(DstReg);
5223 MI.eraseFromParent();
5227 if (Arg->isMasked()) {
5241 MI.eraseFromParent();
5256 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5265 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5273 Align Alignment)
const {
5277 "unexpected kernarg parameter type");
5284 MI.eraseFromParent();
5292 LLT DstTy =
MRI.getType(Dst);
5316 auto FloatY =
B.buildUITOFP(
F32,
Y);
5317 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5319 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5320 auto Z =
B.buildFPTOUI(I32, ScaledY);
5323 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5324 auto NegYZ =
B.buildMul(I32, NegY, Z);
5325 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5328 auto Q =
B.buildUMulH(I32,
X, Z);
5329 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5332 auto One =
B.buildConstant(I32, 1);
5335 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5336 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5341 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5344 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5363 auto Unmerge =
B.buildUnmerge(I32, Val);
5365 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5366 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5368 auto Mad =
B.buildFMAD(
5372 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5373 auto Mul1 =
B.buildFMul(
5377 auto Mul2 =
B.buildFMul(
5379 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5382 auto Mad2 =
B.buildFMAD(
5386 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5387 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5389 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5404 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5406 auto Zero64 =
B.buildConstant(I64, 0);
5407 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5409 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5410 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5412 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5413 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5414 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5416 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5417 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5418 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5420 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5421 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5422 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5423 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5424 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5426 auto Zero32 =
B.buildConstant(I32, 0);
5427 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5428 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5429 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5431 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5432 Register NumerLo = UnmergeNumer.getReg(0);
5433 Register NumerHi = UnmergeNumer.getReg(1);
5435 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5436 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5437 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5438 Register Mul3_Lo = UnmergeMul3.getReg(0);
5439 Register Mul3_Hi = UnmergeMul3.getReg(1);
5440 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5441 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5442 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5443 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5445 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5446 Register DenomLo = UnmergeDenom.getReg(0);
5447 Register DenomHi = UnmergeDenom.getReg(1);
5450 auto C1 =
B.buildSExt(I32, CmpHi);
5453 auto C2 =
B.buildSExt(I32, CmpLo);
5456 auto C3 =
B.buildSelect(I32, CmpEq, C2,
C1);
5463 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5464 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5465 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5466 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5468 auto One64 =
B.buildConstant(I64, 1);
5469 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5475 auto C6 =
B.buildSelect(
5479 auto Add4 =
B.buildAdd(I64, Add3, One64);
5480 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5482 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5483 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5484 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5490 auto Sel1 =
B.buildSelect(
5497 auto Sel2 =
B.buildSelect(
5508 switch (
MI.getOpcode()) {
5511 case AMDGPU::G_UDIV: {
5512 DstDivReg =
MI.getOperand(0).getReg();
5515 case AMDGPU::G_UREM: {
5516 DstRemReg =
MI.getOperand(0).getReg();
5519 case AMDGPU::G_UDIVREM: {
5520 DstDivReg =
MI.getOperand(0).getReg();
5521 DstRemReg =
MI.getOperand(1).getReg();
5528 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5529 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5530 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5531 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
5540 MI.eraseFromParent();
5550 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
5551 if (Ty != I32 && Ty != I64)
5554 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5555 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5556 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5558 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5559 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5560 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5562 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5563 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5565 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5566 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5568 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5569 switch (
MI.getOpcode()) {
5572 case AMDGPU::G_SDIV: {
5573 DstDivReg =
MI.getOperand(0).getReg();
5574 TmpDivReg =
MRI.createGenericVirtualRegister(Ty);
5577 case AMDGPU::G_SREM: {
5578 DstRemReg =
MI.getOperand(0).getReg();
5579 TmpRemReg =
MRI.createGenericVirtualRegister(Ty);
5582 case AMDGPU::G_SDIVREM: {
5583 DstDivReg =
MI.getOperand(0).getReg();
5584 DstRemReg =
MI.getOperand(1).getReg();
5585 TmpDivReg =
MRI.createGenericVirtualRegister(Ty);
5586 TmpRemReg =
MRI.createGenericVirtualRegister(Ty);
5597 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5598 auto SignXor =
B.buildXor(Ty, TmpDivReg,
Sign).getReg(0);
5599 B.buildSub(DstDivReg, SignXor,
Sign);
5603 auto Sign = LHSign.getReg(0);
5604 auto SignXor =
B.buildXor(Ty, TmpRemReg,
Sign).getReg(0);
5605 B.buildSub(DstRemReg, SignXor,
Sign);
5608 MI.eraseFromParent();
5618 uint16_t Flags =
MI.getFlags();
5619 LLT ResTy =
MRI.getType(Res);
5624 if (!AllowInaccurateRcp && ResTy !=
F16)
5635 if (CLHS->isOne()) {
5636 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5640 MI.eraseFromParent();
5645 if (CLHS->isMinusOne()) {
5646 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5647 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5648 .addUse(FNeg.getReg(0))
5651 MI.eraseFromParent();
5658 if (!AllowInaccurateRcp &&
5663 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5666 B.buildFMul(Res, LHS, RCP, Flags);
5668 MI.eraseFromParent();
5678 uint16_t Flags =
MI.getFlags();
5679 LLT ResTy =
MRI.getType(Res);
5683 if (!AllowInaccurateRcp)
5691 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5693 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5694 auto One =
B.buildFConstant(ResTy, 1.0);
5696 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5700 R =
B.buildFNeg(ResTy, R);
5702 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5703 R =
B.buildFMA(ResTy, Tmp0, R, R);
5705 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5706 R =
B.buildFMA(ResTy, Tmp1, R, R);
5709 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5710 B.buildCopy(Res, R);
5711 MI.eraseFromParent();
5715 auto Ret =
B.buildFMul(ResTy,
X, R);
5716 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5718 B.buildFMA(Res, Tmp2, R, Ret);
5719 MI.eraseFromParent();
5733 uint16_t Flags =
MI.getFlags();
5750 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5751 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5752 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5753 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5754 .addUse(RHSExt.getReg(0))
5756 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5758 if (ST.hasMadMacF32Insts()) {
5759 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5760 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5761 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5763 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5764 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5765 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5767 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5768 auto TmpInt =
B.buildBitcast(I32, Tmp);
5769 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5770 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5771 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5772 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5773 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5774 .addUse(RDst.getReg(0))
5779 MI.eraseFromParent();
5792 unsigned SPDenormMode =
5795 if (ST.hasDenormModeInst()) {
5797 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5799 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5800 B.buildInstr(AMDGPU::S_DENORM_MODE)
5801 .addImm(NewDenormModeValue);
5804 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5805 .addImm(SPDenormMode)
5822 uint16_t Flags =
MI.getFlags();
5826 auto One =
B.buildFConstant(
F32, 1.0f);
5828 auto DenominatorScaled =
5829 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5834 auto NumeratorScaled =
5835 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5841 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5842 .addUse(DenominatorScaled.getReg(0))
5844 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5847 const bool HasDynamicDenormals =
5852 if (!PreservesDenormals) {
5853 if (HasDynamicDenormals) {
5854 SavedSPDenormMode =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5855 B.buildInstr(AMDGPU::S_GETREG_B32)
5856 .addDef(SavedSPDenormMode)
5862 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5863 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5864 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5865 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5866 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5867 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5869 if (!PreservesDenormals) {
5870 if (HasDynamicDenormals) {
5871 assert(SavedSPDenormMode);
5872 B.buildInstr(AMDGPU::S_SETREG_B32)
5873 .addReg(SavedSPDenormMode)
5879 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5880 .addUse(Fma4.getReg(0))
5881 .addUse(Fma1.getReg(0))
5882 .addUse(Fma3.getReg(0))
5883 .addUse(NumeratorScaled.getReg(1))
5886 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5887 .addUse(Fmas.getReg(0))
5892 MI.eraseFromParent();
5906 uint16_t Flags =
MI.getFlags();
5910 auto One =
B.buildFConstant(
F64, 1.0);
5912 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5918 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5920 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5921 .addUse(DivScale0.getReg(0))
5924 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5925 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5926 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5928 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5934 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5935 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5936 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5939 if (!ST.hasUsableDivScaleConditionOutput()) {
5946 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5947 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5948 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5949 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5952 Scale1Unmerge.getReg(1));
5954 Scale0Unmerge.getReg(1));
5955 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5957 Scale = DivScale1.getReg(1);
5960 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5961 .addUse(Fma4.getReg(0))
5962 .addUse(Fma3.getReg(0))
5963 .addUse(
Mul.getReg(0))
5967 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5968 .addUse(Fmas.getReg(0))
5973 MI.eraseFromParent();
5983 uint16_t Flags =
MI.getFlags();
5985 LLT Ty =
MRI.getType(Res0);
5988 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5991 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5995 if (ST.hasFractBug()) {
5996 auto Fabs =
B.buildFAbs(Ty, Val);
6000 auto Zero =
B.buildConstant(InstrExpTy, 0);
6001 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp,
Zero);
6002 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
6005 B.buildCopy(Res0, Mant);
6006 B.buildSExtOrTrunc(Res1, Exp);
6008 MI.eraseFromParent();
6018 uint16_t Flags =
MI.getFlags();
6022 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
6024 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
6025 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
6026 auto C2 =
B.buildFConstant(
F32, 1.0f);
6029 auto Sel =
B.buildSelect(
F32, CmpRes,
C1, C2, Flags);
6031 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6033 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6034 .addUse(Mul0.getReg(0))
6037 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6039 B.buildFMul(Res, Sel, Mul1, Flags);
6041 MI.eraseFromParent();
6050 unsigned Flags =
MI.getFlags();
6051 assert(!ST.has16BitInsts());
6052 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6053 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6054 .addUse(Ext.getReg(0))
6056 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6057 MI.eraseFromParent();
6067 const unsigned Flags =
MI.getFlags();
6075 MI.eraseFromParent();
6079 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6081 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6082 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6083 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6088 .addUse(SqrtX.getReg(0))
6091 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6092 auto NegOne =
B.buildConstant(I32, -1);
6093 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6095 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6096 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6098 auto PosOne =
B.buildConstant(I32, 1);
6099 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6101 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6102 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6104 auto Zero =
B.buildFConstant(
F32, 0.0f);
6108 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6112 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6115 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6116 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6118 auto Half =
B.buildFConstant(
F32, 0.5f);
6119 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6120 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6121 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6122 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6123 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6124 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6125 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6126 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6129 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6131 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6133 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6136 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6138 MI.eraseFromParent();
6169 assert(
MRI.getType(Dst) ==
F64 &&
"only expect to lower f64 sqrt");
6172 unsigned Flags =
MI.getFlags();
6177 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6179 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6183 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6184 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6185 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6188 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6190 auto Half =
B.buildFConstant(
F64, 0.5);
6191 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6192 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6194 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6195 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6197 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6198 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6200 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6201 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6203 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6205 Register SqrtRet = SqrtS2.getReg(0);
6207 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6208 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6209 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6212 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6213 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6214 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6219 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6222 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6228 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6230 MI.eraseFromParent();
6237 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
6261 auto Flags =
MI.getFlags();
6263 LLT Ty =
MRI.getType(Dst);
6273 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6283 auto ClampMax = UseIEEE && !ST.hasIEEEMinimumMaximumInsts()
6284 ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags)
6285 :
B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6289 if (UseIEEE && !ST.hasIEEEMinimumMaximumInsts())
6290 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6292 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6293 MI.eraseFromParent();
6305 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6306 IID == Intrinsic::amdgcn_permlanex16;
6307 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6308 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6309 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6310 IID == Intrinsic::amdgcn_permlane_up ||
6311 IID == Intrinsic::amdgcn_permlane_down ||
6312 IID == Intrinsic::amdgcn_permlane_xor;
6316 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6318 case Intrinsic::amdgcn_readfirstlane:
6319 case Intrinsic::amdgcn_permlane64:
6320 return LaneOp.getReg(0);
6321 case Intrinsic::amdgcn_readlane:
6322 case Intrinsic::amdgcn_set_inactive:
6323 case Intrinsic::amdgcn_set_inactive_chain_arg:
6324 return LaneOp.addUse(Src1).getReg(0);
6325 case Intrinsic::amdgcn_writelane:
6326 case Intrinsic::amdgcn_permlane_bcast:
6327 case Intrinsic::amdgcn_permlane_up:
6328 case Intrinsic::amdgcn_permlane_down:
6329 case Intrinsic::amdgcn_permlane_xor:
6330 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6331 case Intrinsic::amdgcn_permlane16:
6332 case Intrinsic::amdgcn_permlanex16: {
6334 int64_t Src4 =
MI.getOperand(6).getImm();
6335 int64_t Src5 =
MI.getOperand(7).getImm();
6336 return LaneOp.addUse(Src1)
6343 case Intrinsic::amdgcn_mov_dpp8:
6344 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6345 case Intrinsic::amdgcn_update_dpp:
6346 return LaneOp.addUse(Src1)
6347 .addImm(
MI.getOperand(4).getImm())
6348 .addImm(
MI.getOperand(5).getImm())
6349 .addImm(
MI.getOperand(6).getImm())
6350 .addImm(
MI.getOperand(7).getImm())
6360 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6361 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6362 IsPermlaneShuffle) {
6363 Src1 =
MI.getOperand(3).getReg();
6364 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6365 IsPermlaneShuffle) {
6366 Src2 =
MI.getOperand(4).getReg();
6370 LLT Ty =
MRI.getType(DstReg);
6371 unsigned Size = Ty.getSizeInBits();
6373 unsigned SplitSize = 32;
6374 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6375 ST.hasDPALU_DPP() &&
6379 if (
Size == SplitSize) {
6386 bool IsFloat = Ty.getScalarType().isFloat();
6390 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6391 if (Src1 &&
MRI.getType(Src1).getScalarType().isFloat())
6392 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6393 if (Src2 &&
MRI.getType(Src2).getScalarType().isFloat())
6394 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6398 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6400 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6401 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6403 if (IID == Intrinsic::amdgcn_writelane)
6404 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6406 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6408 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6410 B.buildTrunc(DstReg, LaneOpDst);
6411 MI.eraseFromParent();
6415 if (
Size % SplitSize != 0)
6419 bool NeedsBitcast =
false;
6420 if (IntTy.isVector()) {
6423 if (EltSize == SplitSize) {
6424 PartialResTy = EltTy;
6425 }
else if (EltSize == 16 || EltSize == 32) {
6426 unsigned NElem = SplitSize / EltSize;
6429 NeedsBitcast =
true;
6438 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6439 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6441 if (IID == Intrinsic::amdgcn_writelane)
6442 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6444 for (
unsigned i = 0; i <
NumParts; ++i) {
6445 Src0 = Src0Parts.
getReg(i);
6447 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6448 Src1 = Src1Parts.
getReg(i);
6450 if (IID == Intrinsic::amdgcn_writelane)
6451 Src2 = Src2Parts.
getReg(i);
6453 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6456 if (NeedsBitcast || IsFloat)
6459 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6461 B.buildMergeLikeInstr(DstReg, PartialRes);
6463 MI.eraseFromParent();
6471 ST.getTargetLowering()->getImplicitParameterOffset(
6473 LLT DstTy =
MRI.getType(DstReg);
6476 Register KernargPtrReg =
MRI.createGenericVirtualRegister(DstTy);
6481 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6482 B.buildConstant(IdxTy,
Offset).getReg(0));
6493 Register Pointer =
MI.getOperand(2).getReg();
6495 Register NumRecords =
MI.getOperand(4).getReg();
6501 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6503 auto ExtStride =
B.buildAnyExt(I32, Stride);
6505 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6506 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6508 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6514 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6515 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6516 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6517 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6521 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6522 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6523 auto ExtShiftedStride =
6524 B.buildMergeValues(I64, {
Zero, ShiftedStride.getReg(0)});
6525 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6526 auto ExtShiftedFlags =
6527 B.buildMergeValues(I64, {
Zero, ShiftedFlags.getReg(0)});
6528 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6530 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6531 B.buildMergeValues(Result, {LowHalf, HighHalf});
6533 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6534 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6535 auto LowHalf = Unmerge.getReg(0);
6536 auto HighHalf = Unmerge.getReg(1);
6538 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6539 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6540 auto ShiftConst =
B.buildConstant(I32, 16);
6541 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6542 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6543 Register NewHighHalfReg = NewHighHalf.getReg(0);
6544 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6547 MI.eraseFromParent();
6564 MI.eraseFromParent();
6571 unsigned AddrSpace)
const {
6573 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6577 ST.hasGloballyAddressableScratch()) {
6579 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6580 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6582 MRI.setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6584 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6586 B.buildConstant(I32, 1u << 26));
6591 MI.eraseFromParent();
6601std::pair<Register, unsigned>
6613 bool CheckNUW = ST.hasGFX1250Insts();
6615 MRI, OrigOffset,
nullptr, CheckNUW);
6618 if (
MRI.getType(BaseReg).isPointer())
6619 BaseReg =
B.buildPtrToInt(
MRI.getType(OrigOffset), BaseReg).getReg(0);
6629 unsigned Overflow = ImmOffset & ~MaxImm;
6630 ImmOffset -= Overflow;
6631 if ((int32_t)Overflow < 0) {
6632 Overflow += ImmOffset;
6636 if (Overflow != 0) {
6638 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6640 auto OverflowVal =
B.buildConstant(I32, Overflow);
6641 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6646 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6648 return std::pair(BaseReg, ImmOffset);
6655 bool ImageStore)
const {
6658 LLT StoreVT =
MRI.getType(Reg);
6663 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6665 if (ST.hasUnpackedD16VMem()) {
6666 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6669 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6670 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6678 if (ImageStore && ST.hasImageStoreD16Bug()) {
6681 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6683 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6690 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6691 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6693 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6701 auto Unmerge =
B.buildUnmerge(I32, Reg);
6702 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6704 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6714 Reg =
B.buildPadVectorWithUndefElements(
6723 bool IsFormat)
const {
6725 LLT Ty =
MRI->getType(VData);
6733 VData =
B.buildBitcast(Ty, VData).getReg(0);
6735 if (Ty.isFloat(16)) {
6737 VData =
B.buildBitcast(Ty, VData).getReg(0);
6744 if (Ty.isVector()) {
6745 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6757 bool IsFormat)
const {
6762 LLT Ty =
MRI.getType(VData);
6764 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6771 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6772 const Function &Fn =
B.getMF().getFunction();
6774 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6775 MI.eraseFromParent();
6787 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6790 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6794 VIndex =
MI.getOperand(3).getReg();
6797 VIndex =
B.buildConstant(I32, 0).getReg(0);
6800 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6801 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6805 Format =
MI.getOperand(5 + OpOffset).getImm();
6809 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6815 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6816 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6817 }
else if (IsFormat) {
6818 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6819 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6823 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6826 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6829 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6834 auto MIB =
B.buildInstr(
Opc)
6845 MIB.addImm(AuxiliaryData)
6846 .addImm(HasVIndex ? -1 : 0)
6847 .addMemOperand(MMO);
6849 MI.eraseFromParent();
6855 unsigned ImmOffset,
unsigned Format,
6858 auto MIB =
B.buildInstr(
Opc)
6869 MIB.addImm(AuxiliaryData)
6870 .addImm(HasVIndex ? -1 : 0)
6871 .addMemOperand(MMO);
6877 Register SOffset,
unsigned ImmOffset,
6878 unsigned Format,
unsigned AuxiliaryData,
6882 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6884 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6887 B.buildUnmerge(Unmerge, LoadDstReg);
6893 bool IsTyped)
const {
6907 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6908 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6910 StatusDst =
MI.getOperand(1).getReg();
6915 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6918 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6921 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6924 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6927 VIndex =
B.buildConstant(I32, 0).getReg(0);
6930 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6931 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6935 Format =
MI.getOperand(5 + OpOffset).getImm();
6939 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6942 LLT Ty =
MRI.getType(Dst);
6949 Dst =
MI.getOperand(0).getReg();
6950 B.setInsertPt(
B.getMBB(),
MI);
6957 Dst =
MI.getOperand(0).getReg();
6958 B.setInsertPt(
B.getMBB(),
MI);
6962 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6963 const bool Unpacked = ST.hasUnpackedD16VMem();
6965 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6966 const Function &Fn =
B.getMF().getFunction();
6968 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6971 B.buildUndef(StatusDst);
6972 MI.eraseFromParent();
6976 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6977 const Function &Fn =
B.getMF().getFunction();
6979 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6982 B.buildUndef(StatusDst);
6983 MI.eraseFromParent();
6995 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6996 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6997 }
else if (IsFormat) {
6999 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
7000 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
7002 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
7003 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
7008 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
7009 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7012 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7013 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7016 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7017 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7022 if (IsTFE && IsD16 && Ty.isVector()) {
7024 const unsigned NumElts = Ty.getNumElements();
7025 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7028 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7029 ValueDWords.
push_back(
MRI.createGenericVirtualRegister(I32));
7031 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7036 R =
B.buildTrunc(EltTy, R).getReg(0);
7037 B.buildMergeLikeInstr(Dst, ValueDWords);
7046 if (PackedTy == Ty) {
7047 B.buildBitcast(Dst, Merged);
7049 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7050 B.buildDeleteTrailingVectorElements(Dst, Packed);
7054 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7056 EltTy.
isFloat() ?
MRI.createGenericVirtualRegister(Ty.changeElementType(
7060 Register ExtDst =
MRI.createGenericVirtualRegister(I32);
7062 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7064 B.buildTrunc(DstInt, ExtDst);
7065 }
else if (NumValueDWords == 1) {
7067 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7071 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7072 ValueDWords.
push_back(
MRI.createGenericVirtualRegister(I32));
7074 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7075 IsTyped, HasVIndex,
B);
7076 B.buildMergeLikeInstr(DstInt, ValueDWords);
7079 B.buildBitcast(Dst, DstInt);
7081 (IsD16 && !Ty.isVector())) {
7082 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7084 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7085 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7086 B.buildTrunc(Dst, LoadDstReg);
7087 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7089 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7091 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7092 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7094 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7096 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7097 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7098 B.buildMergeLikeInstr(Dst, Repack);
7101 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7104 MI.eraseFromParent();
7110 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7111 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7112 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7113 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7114 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7115 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7116 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7117 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7118 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7119 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7120 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7121 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7122 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7123 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7124 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7125 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7126 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7127 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7128 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7129 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7130 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7132 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7133 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7134 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7135 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7136 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7137 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7138 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7139 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7140 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7141 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7142 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7143 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7144 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7145 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7147 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7148 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7149 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7150 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7151 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7152 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7153 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7154 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7155 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7156 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7157 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7158 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7159 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7160 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7161 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7162 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7163 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7164 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7165 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7166 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7167 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7168 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7169 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7170 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7171 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7172 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7173 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7174 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7175 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7176 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7177 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7178 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7179 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7180 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7182 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7183 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7184 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7185 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7186 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7187 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7188 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7189 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7190 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7191 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7192 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7194 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7195 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7197 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7198 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7199 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7208 const bool IsCmpSwap =
7209 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7210 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7211 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7212 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7223 CmpVal =
MI.getOperand(3).getReg();
7228 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7229 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7232 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7235 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7241 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7242 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7243 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7262 .addImm(AuxiliaryData)
7263 .addImm(HasVIndex ? -1 : 0)
7264 .addMemOperand(MMO);
7266 MI.eraseFromParent();
7276 bool IsA16,
bool IsG16) {
7290 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7295 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7299 "Bias needs to be converted to 16 bit in A16 mode");
7301 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7305 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7309 if (((
I + 1) >= EndIdx) ||
7316 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7318 B.buildBuildVector(V2EltTy,
7319 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7324 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7335 int DimIdx,
int NumVAddrs) {
7337 for (
int I = 0;
I != NumVAddrs; ++
I) {
7339 if (
SrcOp.isReg()) {
7342 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7343 if (
B.getMRI()->getType(
Reg) != I32)
7344 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7349 int NumAddrRegs = AddrRegs.
size();
7350 if (NumAddrRegs != 1) {
7351 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7354 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7357 for (
int I = 1;
I != NumVAddrs; ++
I) {
7360 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7382 const unsigned NumDefs =
MI.getNumExplicitDefs();
7383 const unsigned ArgOffset = NumDefs + 1;
7384 bool IsTFE = NumDefs == 2;
7402 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7403 Ty =
MRI->getType(VData);
7406 const bool IsAtomicPacked16Bit =
7407 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7408 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7415 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7416 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7417 const bool DataTyIs16 =
7418 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7420 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7421 const bool IsA16 = AddrTyIs16;
7422 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7425 if (!BaseOpcode->
Atomic) {
7426 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7429 }
else if (DMask != 0) {
7431 }
else if (!IsTFE && !BaseOpcode->
Store) {
7433 B.buildUndef(
MI.getOperand(0));
7434 MI.eraseFromParent();
7442 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7443 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7444 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7445 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7446 unsigned NewOpcode = LoadOpcode;
7447 if (BaseOpcode->
Store)
7448 NewOpcode = StoreOpcode;
7450 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7453 MI.setDesc(
B.getTII().get(NewOpcode));
7457 if (IsTFE && DMask == 0) {
7460 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7463 if (BaseOpcode->
Atomic) {
7465 LLT Ty =
MRI->getType(VData0);
7468 if (Ty.isVector() && !IsAtomicPacked16Bit)
7475 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7476 MI.getOperand(2).setReg(
Concat.getReg(0));
7477 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7481 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7484 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7490 if (IsA16 && !ST.hasA16()) {
7495 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7496 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7498 if (IsA16 || IsG16) {
7506 const bool UseNSA = ST.hasNSAEncoding() &&
7507 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7508 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7509 const bool UsePartialNSA =
7510 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7512 if (UsePartialNSA) {
7516 auto Concat =
B.buildConcatVectors(
7517 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7518 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7519 PackedRegs.
resize(NSAMaxSize);
7520 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7522 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7523 PackedRegs[0] =
Concat.getReg(0);
7527 const unsigned NumPacked = PackedRegs.
size();
7530 if (!
SrcOp.isReg()) {
7540 SrcOp.setReg(AMDGPU::NoRegister);
7557 const bool UseNSA = ST.hasNSAEncoding() &&
7558 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7559 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7560 const bool UsePartialNSA =
7561 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7563 if (UsePartialNSA) {
7565 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7567 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7582 if (!Ty.isVector() || !IsD16)
7586 if (RepackedReg != VData) {
7587 MI.getOperand(1).setReg(RepackedReg);
7595 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7598 if (NumElts < DMaskLanes)
7601 if (NumElts > 4 || DMaskLanes > 4)
7612 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7613 const LLT AdjustedTy =
7629 if (IsD16 && ST.hasUnpackedD16VMem()) {
7636 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7637 unsigned RoundedSize = 32 * RoundedElts;
7641 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7646 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7652 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7656 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7657 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7659 Register NewResultReg =
MRI->createGenericVirtualRegister(LoadResultTy);
7661 MI.getOperand(0).setReg(NewResultReg);
7669 Dst1Reg =
MI.getOperand(1).getReg();
7670 if (
MRI->getType(Dst1Reg) != I32)
7674 MI.removeOperand(1);
7677 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7678 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7679 B.buildBitcast(DstReg, Unmerge.getReg(0));
7680 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7689 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7691 if (ResultNumRegs == 1) {
7693 ResultRegs[0] = NewResultReg;
7696 for (
int I = 0;
I != NumDataRegs; ++
I)
7697 ResultRegs[
I] =
MRI->createGenericVirtualRegister(RegTy);
7698 B.buildUnmerge(ResultRegs, NewResultReg);
7703 ResultRegs.
resize(NumDataRegs);
7708 if (IsD16 && !Ty.isVector()) {
7709 B.buildTrunc(DstReg, ResultRegs[0]);
7714 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7715 !ST.hasUnpackedD16VMem()) {
7716 B.buildBitcast(DstReg, ResultRegs[0]);
7728 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7730 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7731 }
else if (ST.hasUnpackedD16VMem()) {
7733 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7737 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7741 for (
int I = 0;
I != NumElts; ++
I)
7746 LLT ResTy =
MRI->getType(ResultRegs[0]);
7748 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7749 B.buildBuildVector(DstReg, ResultRegs);
7753 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7754 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7759 if (Ty == V3I16 || Ty == V3F16) {
7761 if (ResultRegs.
size() == 1) {
7762 NewResultReg = ResultRegs[0];
7763 }
else if (ResultRegs.
size() == 2) {
7765 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7771 LLT DstTy =
MRI->getType(DstReg);
7772 LLT NewResTy =
MRI->getType(NewResultReg);
7776 :
MRI->createGenericVirtualRegister(
7780 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7782 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7784 if (ResizeDst != DstReg)
7785 B.buildBitcast(DstReg, ResizeDst);
7789 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7790 B.buildConcatVectors(DstReg, ResultRegs);
7799 Register OrigDst =
MI.getOperand(0).getReg();
7801 LLT Ty =
B.getMRI()->getType(OrigDst);
7802 unsigned Size = Ty.getSizeInBits();
7804 bool HasMMO = !
MI.memoperands_empty();
7809 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7810 if (
Size % 32 != 0 && !IsSubwordLoad) {
7813 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7814 B.buildUndef(OrigDst);
7815 MI.eraseFromParent();
7820 if (IsSubwordLoad) {
7822 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7823 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7826 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7828 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7837 B.setInsertPt(
B.getMBB(),
MI);
7842 B.setInsertPt(
B.getMBB(),
MI);
7845 MI.setDesc(
B.getTII().get(
Opc));
7846 MI.removeOperand(1);
7852 const unsigned MemSize = (
Size + 7) / 8;
7853 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7860 MI.addMemOperand(MF, MMO);
7862 if (Dst != OrigDst) {
7863 MI.getOperand(0).setReg(Dst);
7864 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7865 B.buildTrunc(OrigDst, Dst);
7887 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7888 MI.removeOperand(0);
7899 if (!ST.hasTrapHandler() ||
7918 MI.eraseFromParent();
7930 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7939 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7941 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7945 MI.eraseFromParent();
7954 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7961 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7963 Register KernargPtrReg =
MRI.createGenericVirtualRegister(
7979 Register LoadAddr =
MRI.createGenericVirtualRegister(
7981 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7984 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7985 B.buildCopy(SGPR01, Temp);
7986 B.buildInstr(AMDGPU::S_TRAP)
7989 MI.eraseFromParent();
8000 B.buildCopy(SGPR01, LiveIn);
8001 B.buildInstr(AMDGPU::S_TRAP)
8005 MI.eraseFromParent();
8016 if (ST.hasPrivEnabledTrap2NopBug()) {
8028 ST.getInstrInfo()->insertSimulatedTrap(
MRI,
MBB,
MI,
MI.getDebugLoc());
8031 MI.eraseFromParent();
8035 B.buildInstr(AMDGPU::S_TRAP)
8037 MI.eraseFromParent();
8046 if (!ST.hasTrapHandler() ||
8050 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8053 B.buildInstr(AMDGPU::S_TRAP)
8057 MI.eraseFromParent();
8071 Register NodePtr =
MI.getOperand(2).getReg();
8072 Register RayExtent =
MI.getOperand(3).getReg();
8073 Register RayOrigin =
MI.getOperand(4).getReg();
8075 Register RayInvDir =
MI.getOperand(6).getReg();
8078 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8083 const bool IsA16 =
MRI.getType(RayDir).getElementType().getSizeInBits() == 16;
8084 const bool Is64 =
MRI.getType(NodePtr).getSizeInBits() == 64;
8085 const unsigned NumVDataDwords = 4;
8086 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8087 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8089 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8091 const unsigned BaseOpcodes[2][2] = {
8092 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8093 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8094 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8098 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8099 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8100 : AMDGPU::MIMGEncGfx10NSA,
8101 NumVDataDwords, NumVAddrDwords);
8105 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8106 : AMDGPU::MIMGEncGfx10Default,
8107 NumVDataDwords, NumVAddrDwords);
8112 if (UseNSA && IsGFX11Plus) {
8113 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8114 auto SrcInt =
B.buildBitcast(V3I32, Src);
8115 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8116 auto Merged =
B.buildMergeLikeInstr(
8117 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8118 Ops.push_back(Merged.getReg(0));
8121 Ops.push_back(NodePtr);
8122 Ops.push_back(RayExtent);
8123 packLanes(RayOrigin);
8126 auto UnmergeRayDir =
8127 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8128 auto UnmergeRayInvDir =
8129 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8130 auto MergedDir =
B.buildMergeLikeInstr(
8133 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8134 UnmergeRayDir.getReg(0)}))
8137 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8138 UnmergeRayDir.getReg(1)}))
8141 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8142 UnmergeRayDir.getReg(2)}))
8144 Ops.push_back(MergedDir.getReg(0));
8147 packLanes(RayInvDir);
8151 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8152 Ops.push_back(Unmerge.getReg(0));
8153 Ops.push_back(Unmerge.getReg(1));
8155 Ops.push_back(NodePtr);
8157 Ops.push_back(RayExtent);
8159 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8160 auto SrcInt =
B.buildBitcast(V3I32, Src);
8161 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8162 Ops.push_back(Unmerge.getReg(0));
8163 Ops.push_back(Unmerge.getReg(1));
8164 Ops.push_back(Unmerge.getReg(2));
8167 packLanes(RayOrigin);
8169 auto UnmergeRayDir =
8170 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8171 auto UnmergeRayInvDir =
8172 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8173 Register R1 =
MRI.createGenericVirtualRegister(I32);
8175 Register R3 =
MRI.createGenericVirtualRegister(I32);
8176 B.buildMergeLikeInstr(R1,
8177 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8178 B.buildMergeLikeInstr(
8179 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8180 B.buildMergeLikeInstr(
8181 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8187 packLanes(RayInvDir);
8196 Ops.push_back(MergedOps);
8199 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8208 .addImm(IsA16 ? 1 : 0)
8211 MI.eraseFromParent();
8221 Register DstOrigin =
MI.getOperand(1).getReg();
8223 Register NodePtr =
MI.getOperand(4).getReg();
8224 Register RayExtent =
MI.getOperand(5).getReg();
8225 Register InstanceMask =
MI.getOperand(6).getReg();
8226 Register RayOrigin =
MI.getOperand(7).getReg();
8228 Register Offsets =
MI.getOperand(9).getReg();
8229 Register TDescr =
MI.getOperand(10).getReg();
8232 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8233 const unsigned NumVDataDwords = 10;
8234 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8236 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8237 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8238 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8241 auto RayExtentInstanceMaskVec =
8242 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8243 B.buildAnyExt(I32, InstanceMask)});
8245 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8246 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8252 .addUse(RayExtentInstanceMaskVec.getReg(0))
8259 MI.eraseFromParent();
8268 Register StackPtr = Info->getStackPtrOffsetReg();
8270 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8271 MI.eraseFromParent();
8278 if (!ST.hasArchitectedSGPRs())
8282 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8283 auto LSB =
B.buildConstant(I32, 25);
8284 auto Width =
B.buildConstant(I32, 5);
8285 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8286 MI.eraseFromParent();
8294 unsigned Width)
const {
8298 {&AMDGPU::SReg_32RegClass,
MRI.getType(DstReg)});
8299 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8302 B.buildCopy(DstReg, Result);
8303 MI.eraseFromParent();
8319 if (
MRI.getType(Src) != I64)
8323 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8327 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8330 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8331 MI.eraseFromParent();
8341 if (
MRI.getType(Src) != I64)
8344 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8348 .addReg(Unmerge.getReg(0));
8352 .addReg(Unmerge.getReg(1));
8353 MI.eraseFromParent();
8365 case Intrinsic::sponentry:
8370 Register TmpReg =
MRI.createGenericVirtualRegister(I32);
8371 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8374 B.buildIntToPtr(DstReg, TmpReg);
8375 MI.eraseFromParent();
8377 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8379 B.buildFrameIndex(
MI.getOperand(0), FI);
8380 MI.eraseFromParent();
8383 case Intrinsic::amdgcn_if:
8384 case Intrinsic::amdgcn_else: {
8387 bool Negated =
false;
8397 MRI.createVirtualRegister({WaveMaskRC,
MRI.getType(Def)});
8399 MRI.createVirtualRegister({WaveMaskRC,
MRI.getType(
Use)});
8404 std::swap(CondBrTarget, UncondBrTarget);
8406 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8407 B.buildCopy(NewUse,
Use);
8408 if (IntrID == Intrinsic::amdgcn_if) {
8409 B.buildInstr(AMDGPU::SI_IF)
8412 .addMBB(UncondBrTarget)
8415 B.buildInstr(AMDGPU::SI_ELSE)
8418 .addMBB(UncondBrTarget)
8428 B.buildBr(*CondBrTarget);
8431 MI.eraseFromParent();
8432 BrCond->eraseFromParent();
8436 MRI.replaceRegWith(Def, NewDef);
8443 case Intrinsic::amdgcn_loop: {
8446 bool Negated =
false;
8455 {
TRI->getWaveMaskRegClass(),
MRI.getType(Reg)});
8458 std::swap(CondBrTarget, UncondBrTarget);
8460 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8461 B.buildCopy(NewReg, Reg);
8462 B.buildInstr(AMDGPU::SI_LOOP)
8464 .addMBB(UncondBrTarget)
8470 B.buildBr(*CondBrTarget);
8472 MI.eraseFromParent();
8473 BrCond->eraseFromParent();
8479 case Intrinsic::amdgcn_wave_reduce_min:
8480 case Intrinsic::amdgcn_wave_reduce_umin:
8481 case Intrinsic::amdgcn_wave_reduce_fmin:
8482 case Intrinsic::amdgcn_wave_reduce_max:
8483 case Intrinsic::amdgcn_wave_reduce_umax:
8484 case Intrinsic::amdgcn_wave_reduce_fmax:
8485 case Intrinsic::amdgcn_wave_reduce_add:
8486 case Intrinsic::amdgcn_wave_reduce_fadd:
8487 case Intrinsic::amdgcn_wave_reduce_sub:
8488 case Intrinsic::amdgcn_wave_reduce_fsub:
8489 case Intrinsic::amdgcn_wave_reduce_and:
8490 case Intrinsic::amdgcn_wave_reduce_or:
8491 case Intrinsic::amdgcn_wave_reduce_xor: {
8493 if (
MRI.getType(SrcReg).getSizeInBits() != 16)
8496 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8497 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8498 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8499 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8500 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8501 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8502 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8503 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8504 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8511 .addUse(Ext.getReg(0))
8512 .addImm(
MI.getOperand(3).getImm());
8514 B.buildFPTrunc(DstReg, NewDst);
8516 B.buildTrunc(DstReg, NewDst);
8517 MI.eraseFromParent();
8520 case Intrinsic::amdgcn_make_buffer_rsrc:
8522 case Intrinsic::amdgcn_kernarg_segment_ptr:
8525 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8526 MI.eraseFromParent();
8532 case Intrinsic::amdgcn_implicitarg_ptr:
8534 case Intrinsic::amdgcn_workitem_id_x:
8537 case Intrinsic::amdgcn_workitem_id_y:
8540 case Intrinsic::amdgcn_workitem_id_z:
8543 case Intrinsic::amdgcn_workgroup_id_x:
8548 case Intrinsic::amdgcn_workgroup_id_y:
8553 case Intrinsic::amdgcn_workgroup_id_z:
8558 case Intrinsic::amdgcn_cluster_id_x:
8559 return ST.hasClusters() &&
8562 case Intrinsic::amdgcn_cluster_id_y:
8563 return ST.hasClusters() &&
8566 case Intrinsic::amdgcn_cluster_id_z:
8567 return ST.hasClusters() &&
8570 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8571 return ST.hasClusters() &&
8574 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8575 return ST.hasClusters() &&
8578 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8579 return ST.hasClusters() &&
8582 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8583 return ST.hasClusters() &&
8585 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8586 return ST.hasClusters() &&
8589 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8590 return ST.hasClusters() &&
8593 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8594 return ST.hasClusters() &&
8597 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8598 return ST.hasClusters() &&
8602 case Intrinsic::amdgcn_wave_id:
8604 case Intrinsic::amdgcn_lds_kernel_id:
8607 case Intrinsic::amdgcn_dispatch_ptr:
8610 case Intrinsic::amdgcn_queue_ptr:
8613 case Intrinsic::amdgcn_implicit_buffer_ptr: {
8614 const Function &Fn =
B.getMF().getFunction();
8619 ST.hasArchitectedFlatScratch()
8620 ?
"intrinsic not supported on subtarget"
8621 : !ST.isMesa3DOS() ?
"intrinsic not supported for OS"
8622 :
"intrinsic not supported for calling convention";
8625 B.buildUndef(
MI.getOperand(0).getReg());
8626 MI.eraseFromParent();
8632 case Intrinsic::amdgcn_dispatch_id:
8635 case Intrinsic::r600_read_ngroups_x:
8639 case Intrinsic::r600_read_ngroups_y:
8642 case Intrinsic::r600_read_ngroups_z:
8645 case Intrinsic::r600_read_local_size_x:
8648 case Intrinsic::r600_read_local_size_y:
8652 case Intrinsic::r600_read_local_size_z:
8655 case Intrinsic::amdgcn_fdiv_fast:
8657 case Intrinsic::amdgcn_is_shared:
8659 case Intrinsic::amdgcn_is_private:
8661 case Intrinsic::amdgcn_wavefrontsize: {
8662 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8663 MI.eraseFromParent();
8666 case Intrinsic::amdgcn_s_buffer_load:
8667 case Intrinsic::amdgcn_ptr_s_buffer_load:
8669 case Intrinsic::amdgcn_raw_buffer_store:
8670 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8671 case Intrinsic::amdgcn_struct_buffer_store:
8672 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8674 case Intrinsic::amdgcn_raw_buffer_store_format:
8675 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8676 case Intrinsic::amdgcn_struct_buffer_store_format:
8677 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8679 case Intrinsic::amdgcn_raw_tbuffer_store:
8680 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8681 case Intrinsic::amdgcn_struct_tbuffer_store:
8682 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8684 case Intrinsic::amdgcn_raw_buffer_load:
8685 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8686 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8687 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8688 case Intrinsic::amdgcn_struct_buffer_load:
8689 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8690 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8691 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8693 case Intrinsic::amdgcn_raw_buffer_load_format:
8694 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8695 case Intrinsic::amdgcn_struct_buffer_load_format:
8696 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8698 case Intrinsic::amdgcn_raw_tbuffer_load:
8699 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8700 case Intrinsic::amdgcn_struct_tbuffer_load:
8701 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8703 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8704 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8705 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8706 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8707 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8708 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8709 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8710 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8711 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8712 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8713 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8714 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8715 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8716 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8717 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8718 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8719 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8720 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8721 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8722 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8723 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8724 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8725 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8726 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8727 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8728 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8729 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8730 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8731 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8732 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8733 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8734 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8735 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8736 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8737 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8738 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8739 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8740 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8741 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8742 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8743 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8744 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8745 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8746 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8747 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8748 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8749 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8750 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8751 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8752 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8753 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8754 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8755 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8756 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8757 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8758 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8759 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8760 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8761 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8762 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8763 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8764 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8765 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8766 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8767 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8768 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8769 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8770 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8771 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8772 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8773 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8774 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8776 case Intrinsic::amdgcn_rsq_clamp:
8778 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8780 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8781 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8783 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8784 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8785 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8786 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8787 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8788 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8789 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8790 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8793 LLT IndexArgTy =
MRI.getType(Index);
8794 if (IndexArgTy != I64) {
8795 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8796 :
B.buildAnyExt(I64, Index);
8797 MI.getOperand(5).setReg(NewIndex.getReg(0));
8801 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8802 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8803 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8804 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8805 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8806 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8807 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8808 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8811 if (
MRI.getType(Index) != I32)
8812 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8815 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8816 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8817 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8818 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8819 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8820 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8821 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8822 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8823 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8825 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8828 LLT IndexArgTy =
MRI.getType(Index);
8829 if (IndexArgTy != IdxTy) {
8830 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8831 :
B.buildAnyExt(IdxTy, Index);
8832 MI.getOperand(7).setReg(NewIndex.getReg(0));
8837 case Intrinsic::amdgcn_fmed3: {
8843 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8844 MI.removeOperand(1);
8848 case Intrinsic::amdgcn_readlane:
8849 case Intrinsic::amdgcn_writelane:
8850 case Intrinsic::amdgcn_readfirstlane:
8851 case Intrinsic::amdgcn_permlane16:
8852 case Intrinsic::amdgcn_permlanex16:
8853 case Intrinsic::amdgcn_permlane64:
8854 case Intrinsic::amdgcn_set_inactive:
8855 case Intrinsic::amdgcn_set_inactive_chain_arg:
8856 case Intrinsic::amdgcn_mov_dpp8:
8857 case Intrinsic::amdgcn_update_dpp:
8858 case Intrinsic::amdgcn_permlane_bcast:
8859 case Intrinsic::amdgcn_permlane_up:
8860 case Intrinsic::amdgcn_permlane_down:
8861 case Intrinsic::amdgcn_permlane_xor:
8863 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8865 case Intrinsic::amdgcn_dead: {
8869 MI.eraseFromParent();
8872 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8873 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8874 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8875 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8876 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8877 MI.eraseFromParent();
8879 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8880 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8881 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8882 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8883 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8884 MI.eraseFromParent();
8886 case Intrinsic::amdgcn_av_load_b8:
8887 case Intrinsic::amdgcn_av_load_b16:
8888 case Intrinsic::amdgcn_av_load_b32:
8889 case Intrinsic::amdgcn_av_load_b64:
8890 case Intrinsic::amdgcn_av_load_b128:
8891 case Intrinsic::amdgcn_av_store_b8:
8892 case Intrinsic::amdgcn_av_store_b16:
8893 case Intrinsic::amdgcn_av_store_b32:
8894 case Intrinsic::amdgcn_av_store_b64:
8895 case Intrinsic::amdgcn_av_store_b128: {
8896 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8897 if (
MI.getNumExplicitDefs())
8898 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8900 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8901 **
MI.memoperands_begin());
8902 MI.eraseFromParent();
8905 case Intrinsic::amdgcn_flat_load_monitor_b32:
8906 case Intrinsic::amdgcn_flat_load_monitor_b64:
8907 case Intrinsic::amdgcn_flat_load_monitor_b128:
8908 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8909 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8910 .add(
MI.getOperand(0))
8911 .add(
MI.getOperand(2))
8912 .addMemOperand(*
MI.memoperands_begin());
8913 MI.eraseFromParent();
8915 case Intrinsic::amdgcn_global_load_monitor_b32:
8916 case Intrinsic::amdgcn_global_load_monitor_b64:
8917 case Intrinsic::amdgcn_global_load_monitor_b128:
8918 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8919 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8920 .add(
MI.getOperand(0))
8921 .add(
MI.getOperand(2))
8922 .addMemOperand(*
MI.memoperands_begin());
8923 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static 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 bool loadStoreBitcastWorkaround(const GCNSubtarget &ST, const LLT Ty)
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 LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static void buildTFEBufferLoad(unsigned Opc, ArrayRef< Register > ValueDsts, Register StatusDst, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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
bool legalizeTrapHsa(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 legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Lightweight error class with error context and mandatory checking.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasImplicitBufferPtr() const
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
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 Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
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...
GCNUserSGPRUsageInfo & getUserSGPRInfo()
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)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
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.
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
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.