37#include "llvm/IR/IntrinsicsAMDGPU.h"
38#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
488 if (!ST.hasDwordx3LoadStores())
501 if (AlignBits < MemSize) {
504 Align(AlignBits / 8)))
534 const unsigned Size = Ty.getSizeInBits();
535 if (Ty.isPointerVector())
545 unsigned EltSize = Ty.getScalarSizeInBits();
546 return EltSize != 32 && EltSize != 64;
560 const unsigned Size = Ty.getSizeInBits();
561 if (
Size != MemSizeInBits)
562 return Size <= 32 && Ty.isVector();
568 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
577 uint64_t AlignInBits,
unsigned AddrSpace,
587 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
598 if (AlignInBits < RoundedSize)
605 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
617 Query.
Types[1].getAddressSpace(), Opcode);
637 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
641 std::array<Register, 4> VectorElems;
642 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
643 for (
unsigned I = 0;
I < NumParts; ++
I)
645 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
646 B.buildMergeValues(MO, VectorElems);
651 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
652 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
653 B.buildIntToPtr(MO, Scalar);
673 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
675 for (
unsigned I = 0;
I < NumParts; ++
I)
677 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
679 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
680 return B.buildBitcast(VectorTy, Scalar).getReg(0);
699 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
712 const LLT BufferStridedPtr =
715 const LLT CodePtr = FlatPtr;
717 const std::initializer_list<LLT> AddrSpaces64 = {
718 GlobalPtr, ConstantPtr, FlatPtr
721 const std::initializer_list<LLT> AddrSpaces32 = {
722 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
725 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
727 const std::initializer_list<LLT> FPTypesBase = {
731 const std::initializer_list<LLT> FPTypes16 = {
735 const std::initializer_list<LLT> FPTypesPK16 = {
739 const std::initializer_list<LLT> ExtendedFPTypesBase = {
F32,
F64};
740 const std::initializer_list<LLT> ExtendedFPTypes16 = {
F32,
F64,
F16};
741 const std::initializer_list<LLT> ExtendedFPTypesPK16 = {
F32,
F64,
F16,
V2F16};
742 const std::initializer_list<LLT> ExtendedFPTypesPK16_64 = {
F32,
F64,
F16,
745 const LLT MinExtendedFPTy = ST.has16BitInsts() ?
F16 :
F32;
773 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
775 if (ST.hasAnyPackedU64Ops()) {
778 .clampMaxNumElementsStrict(0,
S16, 2)
784 }
else if (ST.hasScalarAddSub64()) {
787 .clampMaxNumElementsStrict(0,
S16, 2)
795 .clampMaxNumElementsStrict(0,
S16, 2)
802 if (ST.hasScalarSMulU64()) {
805 .clampMaxNumElementsStrict(0,
S16, 2)
813 .clampMaxNumElementsStrict(0,
S16, 2)
823 .minScalarOrElt(0,
S16)
828 }
else if (ST.has16BitInsts()) {
862 .widenScalarToNextMultipleOf(0, 32)
872 if (ST.hasMad64_32())
877 if (ST.hasIntClamp()) {
900 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
910 if (ST.hasVOP3PInsts()) {
912 .clampMaxNumElements(0,
S8, 2)
933 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
949 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
956 .clampScalar(0,
S16,
S64);
992 G_STRICT_FADD, G_STRICT_FMUL, G_STRICT_FMA})
998 if (ST.has16BitInsts()) {
999 if (ST.hasVOP3PInsts())
1000 FPOpActions.legalFor({
F16,
V2F16});
1002 FPOpActions.legalFor({
F16});
1004 TrigActions.customFor({
F16});
1005 FDIVActions.customFor({
F16});
1008 if (ST.hasAnyPackedFP32Ops()) {
1009 FPOpActions.legalFor({
V2F32});
1010 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1013 if (ST.hasAnyPackedFP64Ops()) {
1014 FPOpActions.legalFor({
V2F64});
1015 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1018 if (ST.hasAnyPackedFP64Ops()) {
1019 FPOpActions.legalFor({
V2F64});
1020 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1023 auto &MinNumMaxNumIeee =
1026 if (ST.hasVOP3PInsts()) {
1027 MinNumMaxNumIeee.legalFor(ExtendedFPTypesPK16)
1029 .clampMaxNumElements(0,
F16, 2)
1031 }
else if (ST.has16BitInsts()) {
1032 MinNumMaxNumIeee.legalFor(ExtendedFPTypes16).scalarize(0);
1034 MinNumMaxNumIeee.legalFor(ExtendedFPTypesBase).scalarize(0);
1038 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1040 if (ST.hasAnyPackedFP64Ops()) {
1041 MinNumMaxNum.customFor(ExtendedFPTypesPK16_64)
1043 .clampMaxNumElements(0,
F16, 2)
1044 .clampMaxNumElements(0,
F64, 2)
1046 }
else if (ST.hasVOP3PInsts()) {
1047 MinNumMaxNum.customFor(ExtendedFPTypesPK16)
1049 .clampMaxNumElements(0,
F16, 2)
1051 }
else if (ST.has16BitInsts()) {
1052 MinNumMaxNum.customFor(ExtendedFPTypes16).scalarize(0);
1054 MinNumMaxNum.customFor(ExtendedFPTypesBase).scalarize(0);
1057 if (!ST.has16BitInsts()) {
1058 MinNumMaxNumIeee.minScalar(0,
F32);
1059 MinNumMaxNum.minScalar(0,
F32);
1062 if (ST.hasVOP3PInsts())
1068 if (!ST.has16BitInsts()) {
1069 FPOpActions.minScalar(0,
F32);
1070 TrigActions.minScalar(0,
F32);
1071 FDIVActions.minScalar(0,
F32);
1076 .
legalFor(ST.hasAnyPackedFP32Ops(), {V2S32})
1078 if (ST.hasAnyPackedFP32Ops())
1082 if (ST.has16BitInsts()) {
1116 if (ST.hasFractBug()) {
1150 if (ST.hasCvtPkF16F32Inst()) {
1152 .clampMaxNumElements(0,
F16, 2);
1165 if (ST.has16BitInsts()) {
1179 if (ST.hasAnyPackedFP32Ops())
1187 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1188 FMad.customFor({
F32,
F16});
1189 else if (ST.hasMadMacF32Insts())
1190 FMad.customFor({
F32});
1191 else if (ST.hasMadF16())
1192 FMad.customFor({
F16});
1197 if (ST.has16BitInsts()) {
1200 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1208 .clampMaxNumElements(0,
S16, 2)
1224 .legalFor({{
F32, I32}, {
F64, I32}})
1228 if (ST.has16BitInsts())
1236 .legalFor({{I32,
F32}, {I32,
F64}})
1237 .customFor({{I64,
F32}, {I64,
F64}})
1240 if (ST.has16BitInsts())
1249 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1250 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1251 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1255 if (
ST.has16BitInsts())
1258 if (
ST.hasVCvtPkIU16F32())
1268 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1269 .clampScalar(0,
S16,
S64)
1273 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1279 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1283 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1284 .clampScalar(0,
S16,
S64)
1288 auto &RoundingActions = getActionDefinitionsBuilder(
1289 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1290 if (
ST.has16BitInsts())
1298 if (!
ST.has16BitInsts())
1301 getActionDefinitionsBuilder(G_PTR_ADD)
1307 getActionDefinitionsBuilder(G_PTRMASK)
1309 .scalarSameSizeAs(1, 0)
1313 getActionDefinitionsBuilder(G_ICMP)
1325 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1326 .legalForCartesianProduct(
1327 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1328 if (
ST.has16BitInsts()) {
1329 CmpBuilder.legalFor({{
S1,
S16}});
1340 {
S1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1342 if (
ST.hasSALUFloatInsts())
1351 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1352 if (
ST.has16BitInsts())
1353 ExpOps.customFor({{
F32}, {
F16}});
1355 ExpOps.customFor({
F32});
1356 ExpOps.clampScalar(0, MinExtendedFPTy,
F32).scalarize(0);
1358 getActionDefinitionsBuilder(G_FPOWI)
1359 .clampScalar(0, MinExtendedFPTy,
F32)
1362 getActionDefinitionsBuilder(G_FLOG2)
1363 .legalFor(
ST.has16BitInsts(), {F16})
1368 getActionDefinitionsBuilder(G_FEXP2)
1369 .legalFor(
ST.has16BitInsts(), {F16})
1374 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1378 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1383 getActionDefinitionsBuilder(G_CTPOP)
1385 .clampScalar(0,
S32,
S32)
1386 .widenScalarToNextPow2(1, 32)
1387 .clampScalar(1,
S32,
S64)
1389 .widenScalarToNextPow2(0, 32);
1392 if (
ST.has16BitInsts())
1393 getActionDefinitionsBuilder(G_IS_FPCLASS)
1394 .legalForCartesianProduct({
S1}, FPTypes16)
1395 .widenScalarToNextPow2(1)
1399 getActionDefinitionsBuilder(G_IS_FPCLASS)
1400 .legalForCartesianProduct({
S1}, FPTypesBase)
1401 .lowerFor({
S1,
S16})
1402 .widenScalarToNextPow2(1)
1409 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1411 .clampScalar(0,
S32,
S32)
1412 .clampScalar(1,
S32,
S64)
1413 .widenScalarToNextPow2(0, 32)
1414 .widenScalarToNextPow2(1, 32)
1418 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1421 .clampScalar(0,
S32,
S32)
1422 .clampScalar(1,
S32,
S64)
1424 .widenScalarToNextPow2(0, 32)
1425 .widenScalarToNextPow2(1, 32);
1427 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1429 .clampScalar(0,
S32,
S32)
1430 .clampScalar(1,
S32,
S64)
1432 .widenScalarToNextPow2(0, 32)
1433 .widenScalarToNextPow2(1, 32);
1435 getActionDefinitionsBuilder(G_CTLS)
1438 .clampScalar(0,
S32,
S32)
1439 .clampScalar(1,
S32,
S32);
1443 getActionDefinitionsBuilder(G_BITREVERSE)
1445 .clampScalar(0,
S32,
S64)
1447 .widenScalarToNextPow2(0);
1449 if (
ST.has16BitInsts()) {
1450 getActionDefinitionsBuilder(G_BSWAP)
1452 .clampMaxNumElementsStrict(0,
S16, 2)
1455 .widenScalarToNextPow2(0)
1456 .clampScalar(0,
S16,
S32)
1459 if (
ST.hasVOP3PInsts()) {
1460 getActionDefinitionsBuilder(G_ABS)
1462 .clampMaxNumElements(0,
S16, 2)
1464 .widenScalarToNextPow2(0)
1467 if (
ST.hasMinMaxI64Insts()) {
1468 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1470 .clampMaxNumElements(0,
S16, 2)
1472 .widenScalarToNextPow2(0)
1476 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1478 .clampMaxNumElements(0,
S16, 2)
1480 .widenScalarToNextPow2(0)
1485 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1487 .widenScalarToNextPow2(0)
1494 getActionDefinitionsBuilder(G_BSWAP)
1499 .widenScalarToNextPow2(0)
1504 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1507 .widenScalarToNextPow2(0)
1512 getActionDefinitionsBuilder(G_INTTOPTR)
1514 .legalForCartesianProduct(AddrSpaces64, {
S64})
1515 .legalForCartesianProduct(AddrSpaces32, {
S32})
1528 getActionDefinitionsBuilder(G_PTRTOINT)
1530 .legalForCartesianProduct(AddrSpaces64, {
S64})
1531 .legalForCartesianProduct(AddrSpaces32, {
S32})
1544 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1548 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1549 bool IsLoad) ->
bool {
1553 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1567 unsigned NumRegs = (MemSize + 31) / 32;
1569 if (!
ST.hasDwordx3LoadStores())
1580 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1581 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1582 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1588 for (
unsigned Op : {G_LOAD, G_STORE}) {
1589 const bool IsStore =
Op == G_STORE;
1591 auto &Actions = getActionDefinitionsBuilder(
Op);
1594 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1597 {
S64, GlobalPtr,
S64, GlobalAlign32},
1600 {
S32, GlobalPtr,
S8, GlobalAlign8},
1601 {
S32, GlobalPtr,
S16, GlobalAlign16},
1603 {
S32, LocalPtr,
S32, 32},
1604 {
S64, LocalPtr,
S64, 32},
1606 {
S32, LocalPtr,
S8, 8},
1607 {
S32, LocalPtr,
S16, 16},
1610 {
S32, PrivatePtr,
S32, 32},
1611 {
S32, PrivatePtr,
S8, 8},
1612 {
S32, PrivatePtr,
S16, 16},
1615 {
S32, ConstantPtr,
S32, GlobalAlign32},
1618 {
S64, ConstantPtr,
S64, GlobalAlign32},
1619 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1621 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1622 {{S16, GlobalPtr, S8, GlobalAlign8},
1623 {S16, GlobalPtr, S16, GlobalAlign16},
1624 {S16, LocalPtr, S8, 8},
1625 {S16, LocalPtr, S16, 16},
1626 {S16, PrivatePtr, S8, 8},
1627 {S16, PrivatePtr, S16, 16}});
1637 Actions.unsupportedIf(
1638 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1652 Actions.customIf(
typeIs(1, Constant32Ptr));
1678 return !Query.
Types[0].isVector() &&
1679 needToSplitMemOp(Query,
Op == G_LOAD);
1681 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1686 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1689 if (DstSize > MemSize)
1695 if (MemSize > MaxSize)
1703 return Query.
Types[0].isVector() &&
1704 needToSplitMemOp(Query,
Op == G_LOAD);
1706 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1720 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1721 if (MemSize > MaxSize) {
1725 if (MaxSize % EltSize == 0) {
1731 unsigned NumPieces = MemSize / MaxSize;
1735 if (NumPieces == 1 || NumPieces >= NumElts ||
1736 NumElts % NumPieces != 0)
1737 return std::pair(0, EltTy);
1745 return std::pair(0, EltTy);
1760 return std::pair(0, EltTy);
1765 .widenScalarToNextPow2(0)
1772 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1773 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1774 {
S32, GlobalPtr,
S16, 2 * 8},
1775 {
S32, LocalPtr,
S8, 8},
1776 {
S32, LocalPtr,
S16, 16},
1777 {
S32, PrivatePtr,
S8, 8},
1778 {
S32, PrivatePtr,
S16, 16},
1779 {
S32, ConstantPtr,
S8, 8},
1780 {
S32, ConstantPtr,
S16, 2 * 8}})
1781 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1782 {{S16, GlobalPtr, S8, GlobalAlign8},
1783 {S16, LocalPtr, S8, GlobalAlign8},
1784 {S16, PrivatePtr, S8, GlobalAlign8},
1785 {S16, ConstantPtr, S8, GlobalAlign8}})
1790 if (
ST.hasFlatAddressSpace()) {
1791 ExtLoads.legalForTypesWithMemDesc(
1792 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1794 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1795 {{S16, FlatPtr, S8, GlobalAlign8}});
1803 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1805 ExtLoads.narrowScalarIf(
1812 ExtLoads.clampScalar(0,
S32,
S32)
1813 .widenScalarToNextPow2(0)
1816 auto &Atomics = getActionDefinitionsBuilder(
1817 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1818 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1819 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1820 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1821 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1822 {
S64, GlobalPtr}, {
S64, LocalPtr},
1823 {
S32, RegionPtr}, {
S64, RegionPtr}});
1824 if (
ST.hasFlatAddressSpace()) {
1825 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1829 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1830 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1831 if (
ST.hasFlatAddressSpace()) {
1832 Atomics32.legalFor({{
S32, FlatPtr}});
1836 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1837 if (
ST.hasLDSFPAtomicAddF32()) {
1838 Atomic.legalFor({{
S32, LocalPtr}, {
S32, RegionPtr}});
1839 if (
ST.hasLdsAtomicAddF64())
1840 Atomic.legalFor({{
S64, LocalPtr}});
1841 if (
ST.hasAtomicDsPkAdd16Insts())
1842 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1844 if (
ST.hasAtomicFaddInsts())
1845 Atomic.legalFor({{
S32, GlobalPtr}});
1846 if (
ST.hasFlatAtomicFaddF32Inst())
1847 Atomic.legalFor({{
S32, FlatPtr}});
1849 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1860 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1861 ST.hasAtomicBufferGlobalPkAddF16Insts())
1862 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1863 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1864 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1865 if (
ST.hasAtomicFlatPkAdd16Insts())
1866 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1871 auto &AtomicFMinFMax =
1872 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1873 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1875 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1876 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1877 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1878 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1879 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1880 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1881 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1882 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1886 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1887 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1888 {
S32, FlatPtr}, {
S64, FlatPtr}})
1889 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1890 {
S32, RegionPtr}, {
S64, RegionPtr}});
1894 getActionDefinitionsBuilder(G_SELECT)
1896 LocalPtr, FlatPtr, PrivatePtr,
1900 .clampScalar(0,
S16,
S64)
1904 .clampMaxNumElements(0,
S32, 2)
1905 .clampMaxNumElements(0, LocalPtr, 2)
1906 .clampMaxNumElements(0, PrivatePtr, 2)
1908 .widenScalarToNextPow2(0)
1913 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1915 if (
ST.has16BitInsts()) {
1916 if (
ST.hasVOP3PInsts()) {
1918 .clampMaxNumElements(0,
S16, 2);
1920 Shifts.legalFor({{
S16,
S16}});
1923 Shifts.widenScalarIf(
1928 const LLT AmountTy = Query.
Types[1];
1934 Shifts.clampScalar(1,
S32,
S32);
1935 Shifts.widenScalarToNextPow2(0, 16);
1936 Shifts.clampScalar(0,
S16,
S64);
1938 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1946 Shifts.clampScalar(1,
S32,
S32);
1947 Shifts.widenScalarToNextPow2(0, 32);
1948 Shifts.clampScalar(0,
S32,
S64);
1950 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1955 Shifts.scalarize(0);
1957 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1958 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1959 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1960 unsigned IdxTypeIdx = 2;
1962 getActionDefinitionsBuilder(
Op)
1964 const LLT EltTy = Query.
Types[EltTypeIdx];
1965 const LLT VecTy = Query.
Types[VecTypeIdx];
1966 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1968 const bool isLegalVecType =
1978 return (EltSize == 32 || EltSize == 64) &&
1994 const LLT EltTy = Query.
Types[EltTypeIdx];
1995 const LLT VecTy = Query.
Types[VecTypeIdx];
1999 const unsigned TargetEltSize =
2000 DstEltSize % 64 == 0 ? 64 : 32;
2001 return std::pair(VecTypeIdx,
2005 .clampScalar(EltTypeIdx,
S32,
S64)
2006 .clampScalar(VecTypeIdx,
S32,
S64)
2007 .clampScalar(IdxTypeIdx,
S32,
S32)
2008 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2017 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2019 const LLT &EltTy = Query.
Types[1].getElementType();
2020 return Query.
Types[0] != EltTy;
2023 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2024 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2025 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2026 getActionDefinitionsBuilder(
Op)
2029 const LLT BigTy = Query.
Types[BigTyIdx];
2035 const LLT LitTy = Query.
Types[LitTyIdx];
2040 .widenScalarToNextPow2(BigTyIdx, 32)
2048 const LLT BigTy = Query.
Types[BigTyIdx];
2049 const LLT LitTy = Query.
Types[LitTyIdx];
2057 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2067 if (
ST.hasScalarPackInsts()) {
2070 .minScalarOrElt(0,
S16)
2073 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2077 BuildVector.customFor({
V2S16,
S16});
2078 BuildVector.minScalarOrElt(0,
S32);
2080 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2088 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2090 .clampMaxNumElements(0,
S32, 32)
2091 .clampMaxNumElements(1,
S16, 2)
2092 .clampMaxNumElements(0,
S16, 64);
2094 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2097 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2098 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2099 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2101 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2102 const LLT Ty = Query.
Types[TypeIdx];
2114 getActionDefinitionsBuilder(
Op)
2118 const LLT BigTy = Query.
Types[BigTyIdx];
2124 .widenScalarToNextPow2(LitTyIdx, 16)
2133 .clampScalar(LitTyIdx,
S32,
S512)
2134 .widenScalarToNextPow2(LitTyIdx, 32)
2138 return notValidElt(Query, LitTyIdx);
2143 return notValidElt(Query, BigTyIdx);
2148 if (
Op == G_MERGE_VALUES) {
2149 Builder.widenScalarIf(
2152 const LLT Ty = Query.
Types[LitTyIdx];
2158 Builder.widenScalarIf(
2160 const LLT Ty = Query.
Types[BigTyIdx];
2166 const LLT &Ty = Query.
Types[BigTyIdx];
2168 if (NewSizeInBits >= 256) {
2170 if (RoundedTo < NewSizeInBits)
2171 NewSizeInBits = RoundedTo;
2173 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2182 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2183 .legalFor({{
S32}, {
S64}})
2184 .clampScalar(0,
S32,
S64);
2186 if (
ST.hasVOP3PInsts()) {
2187 SextInReg.lowerFor({{
V2S16}})
2191 .clampMaxNumElementsStrict(0,
S16, 2);
2192 }
else if (
ST.has16BitInsts()) {
2193 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2197 SextInReg.lowerFor({{
S32}, {
S64}});
2202 .clampScalar(0,
S32,
S64)
2205 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2209 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2210 FSHRActionDefs.legalFor({{
S32,
S32}})
2211 .clampMaxNumElementsStrict(0,
S16, 2);
2212 if (
ST.hasVOP3PInsts())
2214 FSHRActionDefs.scalarize(0).lower();
2216 if (
ST.hasVOP3PInsts()) {
2217 getActionDefinitionsBuilder(G_FSHL)
2219 .clampMaxNumElementsStrict(0,
S16, 2)
2223 getActionDefinitionsBuilder(G_FSHL)
2228 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2231 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2233 getActionDefinitionsBuilder(G_FENCE)
2236 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2241 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2243 .clampScalar(1,
S32,
S32)
2244 .clampScalar(0,
S32,
S64)
2245 .widenScalarToNextPow2(0)
2248 getActionDefinitionsBuilder(
2252 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2253 G_READ_REGISTER, G_WRITE_REGISTER,
2258 if (
ST.hasIEEEMinimumMaximumInsts()) {
2259 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2260 .legalFor(ExtendedFPTypesPK16)
2261 .clampMaxNumElements(0,
F16, 2)
2263 }
else if (
ST.hasVOP3PInsts()) {
2264 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2266 .clampMaxNumElementsStrict(0,
F16, 2)
2270 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2272 .clampScalar(0,
F32,
F64)
2276 getActionDefinitionsBuilder(
2277 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2280 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2282 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2283 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2284 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2287 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2289 getActionDefinitionsBuilder(
2290 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2291 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2292 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2293 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2298 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2299 G_INTRINSIC_CONVERGENT,
2300 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2312 switch (
MI.getOpcode()) {
2313 case TargetOpcode::G_ADDRSPACE_CAST:
2315 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2317 case TargetOpcode::G_FCEIL:
2319 case TargetOpcode::G_FREM:
2321 case TargetOpcode::G_INTRINSIC_TRUNC:
2323 case TargetOpcode::G_SITOFP:
2325 case TargetOpcode::G_UITOFP:
2327 case TargetOpcode::G_FPTOSI:
2329 case TargetOpcode::G_FPTOUI:
2331 case TargetOpcode::G_FMINNUM:
2332 case TargetOpcode::G_FMAXNUM:
2333 case TargetOpcode::G_FMINIMUMNUM:
2334 case TargetOpcode::G_FMAXIMUMNUM:
2336 case TargetOpcode::G_EXTRACT:
2338 case TargetOpcode::G_INSERT:
2340 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2342 case TargetOpcode::G_INSERT_VECTOR_ELT:
2344 case TargetOpcode::G_FSIN:
2345 case TargetOpcode::G_FCOS:
2347 case TargetOpcode::G_GLOBAL_VALUE:
2349 case TargetOpcode::G_LOAD:
2350 case TargetOpcode::G_SEXTLOAD:
2351 case TargetOpcode::G_ZEXTLOAD:
2353 case TargetOpcode::G_STORE:
2355 case TargetOpcode::G_FMAD:
2357 case TargetOpcode::G_FDIV:
2359 case TargetOpcode::G_FFREXP:
2361 case TargetOpcode::G_FSQRT:
2363 case TargetOpcode::G_UDIV:
2364 case TargetOpcode::G_UREM:
2365 case TargetOpcode::G_UDIVREM:
2367 case TargetOpcode::G_SDIV:
2368 case TargetOpcode::G_SREM:
2369 case TargetOpcode::G_SDIVREM:
2371 case TargetOpcode::G_ATOMIC_CMPXCHG:
2373 case TargetOpcode::G_FLOG2:
2375 case TargetOpcode::G_FLOG:
2376 case TargetOpcode::G_FLOG10:
2378 case TargetOpcode::G_FEXP2:
2380 case TargetOpcode::G_FEXP:
2381 case TargetOpcode::G_FEXP10:
2383 case TargetOpcode::G_FPOW:
2385 case TargetOpcode::G_FFLOOR:
2387 case TargetOpcode::G_BUILD_VECTOR:
2388 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2390 case TargetOpcode::G_MUL:
2392 case TargetOpcode::G_CTLZ:
2393 case TargetOpcode::G_CTTZ:
2395 case TargetOpcode::G_CTLS:
2397 case TargetOpcode::G_CTLZ_ZERO_POISON:
2399 case TargetOpcode::G_STACKSAVE:
2401 case TargetOpcode::G_GET_FPENV:
2403 case TargetOpcode::G_SET_FPENV:
2405 case TargetOpcode::G_TRAP:
2407 case TargetOpcode::G_DEBUGTRAP:
2427 if (ST.hasApertureRegs()) {
2432 ? AMDGPU::SRC_SHARED_BASE
2433 : AMDGPU::SRC_PRIVATE_BASE;
2434 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2435 !ST.hasGloballyAddressableScratch()) &&
2436 "Cannot use src_private_base with globally addressable scratch!");
2439 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2440 return B.buildUnmerge(I32, Dst).getReg(1);
2455 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2471 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2474 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2496 B.buildObjectPtrOffset(
2499 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2507 switch (Def->getOpcode()) {
2508 case AMDGPU::G_FRAME_INDEX:
2509 case AMDGPU::G_GLOBAL_VALUE:
2510 case AMDGPU::G_BLOCK_ADDR:
2512 case AMDGPU::G_CONSTANT: {
2513 const ConstantInt *CI = Def->getOperand(1).getCImm();
2530 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2532 Intrinsic::amdgcn_addrspacecast_nonnull));
2538 :
MI.getOperand(1).getReg();
2542 unsigned SrcAS = SrcTy.getAddressSpace();
2552 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2559 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2561 ST.hasGloballyAddressableScratch()) {
2564 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2566 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2567 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2569 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2570 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2571 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2575 return B.buildExtract(Dst, Src, 0).getReg(0);
2581 castFlatToLocalOrPrivate(Dst);
2582 MI.eraseFromParent();
2588 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2589 auto FlatNull =
B.buildConstant(SrcTy, 0);
2592 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2596 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2598 MI.eraseFromParent();
2605 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2608 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2611 ST.hasGloballyAddressableScratch()) {
2615 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2616 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2620 if (ST.isWave64()) {
2621 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2627 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2628 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2630 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2634 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2635 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2637 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2638 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2647 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2653 castLocalOrPrivateToFlat(Dst);
2654 MI.eraseFromParent();
2658 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2665 SegmentNull.getReg(0));
2667 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2669 MI.eraseFromParent();
2674 SrcTy.getSizeInBits() == 64) {
2676 B.buildExtract(Dst, Src, 0);
2677 MI.eraseFromParent();
2684 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2685 auto PtrLo =
B.buildPtrToInt(I32, Src);
2686 if (AddrHiVal == 0) {
2687 auto Zext =
B.buildZExt(I64, PtrLo);
2688 B.buildIntToPtr(Dst, Zext);
2690 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2691 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2694 MI.eraseFromParent();
2701 MI.eraseFromParent();
2710 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2715 auto C1 =
B.buildFConstant(Ty, C1Val);
2716 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2719 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2720 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2722 auto C2 =
B.buildFConstant(Ty, C2Val);
2723 auto Fabs =
B.buildFAbs(Ty, Src);
2726 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2727 MI.eraseFromParent();
2744 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2746 const auto Zero =
B.buildFConstant(
F64, 0.0);
2747 const auto One =
B.buildFConstant(
F64, 1.0);
2750 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2751 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2754 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2755 MI.eraseFromParent();
2763 Register Src0Reg =
MI.getOperand(1).getReg();
2764 Register Src1Reg =
MI.getOperand(2).getReg();
2765 auto Flags =
MI.getFlags();
2768 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2769 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2770 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2771 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2772 MI.eraseFromParent();
2778 const unsigned FractBits = 52;
2779 const unsigned ExpBits = 11;
2782 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2783 auto Const1 =
B.buildConstant(I32, ExpBits);
2785 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2787 .addUse(Const0.getReg(0))
2788 .addUse(Const1.getReg(0));
2790 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2803 auto SrcInt =
B.buildBitcast(I64, Src);
2806 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2813 const unsigned FractBits = 52;
2816 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2817 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2819 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2821 const auto Zero32 =
B.buildConstant(I32, 0);
2824 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2826 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2827 auto Not =
B.buildNot(I64, Shr);
2828 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2829 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2834 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2835 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2836 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2837 MI.eraseFromParent();
2853 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2854 auto ThirtyTwo =
B.buildConstant(I32, 32);
2857 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2858 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2860 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2861 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2864 B.buildFAdd(Dst, LdExp, CvtLo);
2865 MI.eraseFromParent();
2871 auto One =
B.buildConstant(I32, 1);
2875 auto ThirtyOne =
B.buildConstant(I32, 31);
2876 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2877 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2878 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2879 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2880 .addUse(Unmerge.getReg(1));
2881 auto LS2 =
B.buildSub(I32, LS, One);
2882 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2884 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2885 auto Norm =
B.buildShl(I64, Src, ShAmt);
2886 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2887 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2888 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2889 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2890 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2891 B.buildFLdexp(Dst, FVal, Scale);
2892 MI.eraseFromParent();
2912 unsigned Flags =
MI.getFlags();
2923 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2931 auto SrcInt =
B.buildBitcast(I32, Src);
2932 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2933 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2937 K0 =
B.buildFConstant(
2939 K1 =
B.buildFConstant(
2942 K0 =
B.buildFConstant(
2944 K1 =
B.buildFConstant(
2948 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2949 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2950 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2952 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2953 :
B.buildFPTOUI(I32, FloorMul);
2954 auto Lo =
B.buildFPTOUI(I32, Fma);
2958 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2960 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2963 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2964 MI.eraseFromParent();
2996 unsigned StartIdx =
Offset / 32;
3000 if (DstCount == 1) {
3002 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3007 for (
unsigned I = 0;
I < DstCount; ++
I)
3008 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3009 B.buildMergeLikeInstr(DstReg, MergeVec);
3012 MI.eraseFromParent();
3022 Register InsertSrc =
MI.getOperand(2).getReg();
3031 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3035 unsigned DstCount = DstSize / 32;
3036 unsigned InsertCount = InsertSize / 32;
3037 unsigned StartIdx =
Offset / 32;
3039 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3042 for (
unsigned I = 0;
I < StartIdx; ++
I)
3045 if (InsertCount == 1) {
3049 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3052 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3053 for (
unsigned I = 0;
I < InsertCount; ++
I)
3057 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3060 B.buildMergeLikeInstr(DstReg, MergeVec);
3062 MI.eraseFromParent();
3089 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3090 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3091 B.buildIntToPtr(Dst, IntElt);
3093 MI.eraseFromParent();
3100 std::optional<ValueAndVReg> MaybeIdxVal =
3104 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3107 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3108 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3113 MI.eraseFromParent();
3142 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3143 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3144 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3146 B.buildIntToPtr(Dst, IntVecDest);
3147 MI.eraseFromParent();
3154 std::optional<ValueAndVReg> MaybeIdxVal =
3159 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3162 if (IdxVal < NumElts) {
3164 for (
unsigned i = 0; i < NumElts; ++i)
3166 B.buildUnmerge(SrcRegs, Vec);
3168 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3169 B.buildMergeLikeInstr(Dst, SrcRegs);
3174 MI.eraseFromParent();
3185 unsigned Flags =
MI.getFlags();
3189 if (ST.hasTrigReducedRange()) {
3190 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3191 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3192 .addUse(MulVal.getReg(0))
3196 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3199 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3203 MI.eraseFromParent();
3211 unsigned GAFlags)
const {
3240 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3242 if (ST.has64BitLiterals()) {
3246 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3250 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3259 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3260 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3263 B.buildExtract(DstReg, PCReg, 0);
3273 if (RequiresHighHalf && ST.has64BitLiterals()) {
3275 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3276 B.buildInstr(AMDGPU::S_MOV_B64)
3291 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3294 B.buildInstr(AMDGPU::S_MOV_B32)
3299 if (RequiresHighHalf) {
3301 "Must provide a 64-bit pointer type!");
3304 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3306 B.buildInstr(AMDGPU::S_MOV_B32)
3317 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3319 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3323 if (AddrDst != DstReg)
3324 B.buildCast(DstReg, AddrDst);
3325 }
else if (AddrLo != DstReg) {
3328 B.buildCast(DstReg, AddrLo);
3337 unsigned AS = Ty.getAddressSpace();
3345 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3349 Fn,
"local memory global used by non-kernel function",
3358 B.buildUndef(DstReg);
3359 MI.eraseFromParent();
3383 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3384 B.buildIntToPtr(DstReg, Sz);
3385 MI.eraseFromParent();
3391 MI.eraseFromParent();
3395 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3397 MI.eraseFromParent();
3405 MI.eraseFromParent();
3411 MI.eraseFromParent();
3427 if (Ty.getSizeInBits() == 32) {
3429 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3430 B.buildExtract(DstReg,
Load, 0);
3432 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3434 MI.eraseFromParent();
3457 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3459 MI.getOperand(1).setReg(Cast.getReg(0));
3464 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3490 if (WideMemSize == ValSize) {
3496 MI.setMemRefs(MF, {WideMMO});
3502 if (ValSize > WideMemSize)
3509 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3510 B.buildTrunc(ValReg, WideLoad).getReg(0);
3517 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3518 B.buildExtract(ValReg, WideLoad, 0);
3522 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3523 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3527 MI.eraseFromParent();
3540 Register DataReg =
MI.getOperand(0).getReg();
3585 "this should not have been custom lowered");
3590 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3592 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3596 .setMemRefs(
MI.memoperands());
3598 MI.eraseFromParent();
3606 switch (
DefMI->getOpcode()) {
3607 case TargetOpcode::G_INTRINSIC: {
3609 case Intrinsic::amdgcn_frexp_mant:
3610 case Intrinsic::amdgcn_log:
3611 case Intrinsic::amdgcn_log_clamp:
3612 case Intrinsic::amdgcn_exp2:
3613 case Intrinsic::amdgcn_sqrt:
3621 case TargetOpcode::G_FSQRT:
3623 case TargetOpcode::G_FFREXP: {
3624 if (
DefMI->getOperand(0).getReg() == Src)
3628 case TargetOpcode::G_FPEXT: {
3649std::pair<Register, Register>
3651 unsigned Flags)
const {
3655 auto SmallestNormal =
B.buildFConstant(
3657 auto IsLtSmallestNormal =
3660 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3661 auto One =
B.buildFConstant(
F32, 1.0);
3663 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3664 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3666 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3679 LLT Ty =
B.getMRI()->getType(Dst);
3680 unsigned Flags =
MI.getFlags();
3684 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3685 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3686 .addUse(Ext.getReg(0))
3688 B.buildFPTrunc(Dst,
Log2, Flags);
3689 MI.eraseFromParent();
3697 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3700 MI.eraseFromParent();
3704 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3705 .addUse(ScaledInput)
3708 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3709 auto Zero =
B.buildFConstant(Ty, 0.0);
3711 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3712 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3714 MI.eraseFromParent();
3720 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3721 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3726 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3727 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3732 unsigned Flags =
MI.getFlags();
3742 auto PromoteSrc =
B.buildFPExt(
F32,
X);
3744 B.buildFPTrunc(Dst, LogVal);
3749 MI.eraseFromParent();
3758 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3761 if (ST.hasFastFMAF32()) {
3763 const float c_log10 = 0x1.344134p-2f;
3764 const float cc_log10 = 0x1.09f79ep-26f;
3767 const float c_log = 0x1.62e42ep-1f;
3768 const float cc_log = 0x1.efa39ep-25f;
3770 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3771 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3775 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3776 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3777 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3778 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3779 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3782 const float ch_log10 = 0x1.344000p-2f;
3783 const float ct_log10 = 0x1.3509f6p-18f;
3786 const float ch_log = 0x1.62e000p-1f;
3787 const float ct_log = 0x1.0bfbe8p-15f;
3789 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3790 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3793 auto YInt =
B.buildBitcast(I32,
Y);
3794 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3795 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3796 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3800 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3803 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3805 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3808 const bool IsFiniteOnly =
3811 if (!IsFiniteOnly) {
3814 auto Fabs =
B.buildFAbs(Ty,
Y);
3817 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3821 auto Zero =
B.buildFConstant(Ty, 0.0);
3823 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3824 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3825 B.buildFSub(Dst, R, Shift, Flags);
3827 B.buildCopy(Dst, R);
3830 MI.eraseFromParent();
3836 unsigned Flags)
const {
3837 const double Log2BaseInverted =
3840 LLT Ty =
B.getMRI()->getType(Dst);
3845 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3848 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3849 auto Zero =
B.buildFConstant(Ty, 0.0);
3851 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3852 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3854 if (ST.hasFastFMAF32())
3855 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3857 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3858 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3865 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3866 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3869 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3870 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3881 unsigned Flags =
MI.getFlags();
3882 LLT Ty =
B.getMRI()->getType(Dst);
3889 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3890 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3891 .addUse(Ext.getReg(0))
3893 B.buildFPTrunc(Dst,
Log2, Flags);
3894 MI.eraseFromParent();
3904 MI.eraseFromParent();
3912 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3914 RangeCheckConst, Flags);
3916 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3917 auto Zero =
B.buildFConstant(Ty, 0.0);
3918 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3919 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3921 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3922 .addUse(AddInput.getReg(0))
3925 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3926 auto One =
B.buildFConstant(Ty, 1.0);
3927 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3928 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3929 MI.eraseFromParent();
3934 const SrcOp &Src,
unsigned Flags) {
3935 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3938 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3939 .addUse(Src.getReg())
3942 return B.buildFExp2(Dst, Src, Flags);
3948 bool IsExp10)
const {
3949 LLT Ty =
B.getMRI()->getType(
X);
3953 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3954 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3961 LLT Ty =
B.getMRI()->getType(Dst);
3967 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3970 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3971 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3972 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3975 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3977 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3978 .addUse(ExpInput.getReg(0))
3981 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3982 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3983 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
3989 unsigned Flags)
const {
3990 LLT Ty =
B.getMRI()->getType(Dst);
3994 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
3995 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
3997 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
3998 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
3999 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4000 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4001 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4011 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4015 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4016 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4017 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4019 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4020 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4022 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4023 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4024 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4025 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4027 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4028 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4029 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4031 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4049 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4051 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4053 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4055 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4056 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4057 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4058 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4060 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4061 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4062 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4063 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4065 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4066 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4067 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4068 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4069 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4071 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4072 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4073 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4074 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4077 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4078 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4079 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4081 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4082 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4083 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4084 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4085 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4089 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4090 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4092 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4094 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4096 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4098 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4100 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4101 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4102 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4103 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4105 auto One =
B.buildFConstant(
F64, 1.0);
4106 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4107 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4110 auto DnInt =
B.buildFPTOSI(I32, Dn);
4111 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4118 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4125 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4127 MI.eraseFromParent();
4135 const unsigned Flags =
MI.getFlags();
4143 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4151 MI.eraseFromParent();
4162 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4165 B.buildFPTrunc(Dst, Lowered, Flags);
4166 MI.eraseFromParent();
4177 MI.eraseFromParent();
4205 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4208 if (ST.hasFastFMAF32()) {
4210 const float cc_exp = 0x1.4ae0bep-26f;
4211 const float c_exp10 = 0x1.a934f0p+1f;
4212 const float cc_exp10 = 0x1.2f346ep-24f;
4214 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4215 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4216 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4217 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4219 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4220 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4222 const float ch_exp = 0x1.714000p+0f;
4223 const float cl_exp = 0x1.47652ap-12f;
4225 const float ch_exp10 = 0x1.a92000p+1f;
4226 const float cl_exp10 = 0x1.4f0978p-11f;
4229 auto XInt =
B.buildBitcast(I32,
X);
4230 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4231 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4232 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4234 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4235 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4237 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4238 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4241 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4242 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4245 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4248 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4249 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4251 auto IntE =
B.buildFPTOSI(I32, E);
4253 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4254 .addUse(
A.getReg(0))
4256 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4258 auto UnderflowCheckConst =
4259 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4260 auto Zero =
B.buildFConstant(Ty, 0.0);
4264 R =
B.buildSelect(Ty, Underflow, Zero, R);
4267 auto OverflowCheckConst =
4268 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4273 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4276 B.buildCopy(Dst, R);
4277 MI.eraseFromParent();
4286 unsigned Flags =
MI.getFlags();
4287 LLT Ty =
B.getMRI()->getType(Dst);
4290 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4291 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4292 .addUse(Log.getReg(0))
4295 B.buildFExp2(Dst,
Mul, Flags);
4296 }
else if (Ty ==
F16) {
4298 auto Log =
B.buildFLog2(
F16, Src0, Flags);
4299 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4300 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4301 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4302 .addUse(Ext0.getReg(0))
4303 .addUse(Ext1.getReg(0))
4305 B.buildFExp2(Dst,
B.buildFPTrunc(
F16,
Mul), Flags);
4309 MI.eraseFromParent();
4317 ModSrc = SrcFNeg->getOperand(1).getReg();
4319 ModSrc = SrcFAbs->getOperand(1).getReg();
4321 ModSrc = SrcFAbs->getOperand(1).getReg();
4331 Register OrigSrc =
MI.getOperand(1).getReg();
4332 unsigned Flags =
MI.getFlags();
4334 "this should not have been custom lowered");
4344 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4364 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4366 B.buildFMinNum(Min, Fract, Const, Flags);
4371 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4374 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4375 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4377 MI.eraseFromParent();
4395 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4397 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4398 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4401 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4402 B.buildBitcast(Dst,
Merge);
4404 MI.eraseFromParent();
4421 bool UsePartialMad64_32,
4422 bool SeparateOddAlignedProducts)
const {
4437 auto getZero32 = [&]() ->
Register {
4439 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4442 auto getZero64 = [&]() ->
Register {
4444 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4449 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4460 if (CarryIn.empty())
4463 bool HaveCarryOut =
true;
4465 if (CarryIn.size() == 1) {
4467 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4471 CarryAccum = getZero32();
4473 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4474 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4476 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4481 LocalAccum = getZero32();
4482 HaveCarryOut =
false;
4487 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4488 LocalAccum =
Add.getReg(0);
4502 auto buildMadChain =
4505 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4506 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4513 if (LocalAccum.size() == 1 &&
4514 (!UsePartialMad64_32 || !CarryIn.empty())) {
4517 unsigned j1 = DstIndex - j0;
4518 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4522 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4524 LocalAccum[0] =
Mul.getReg(0);
4526 if (CarryIn.empty()) {
4527 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4530 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4536 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4540 if (j0 <= DstIndex) {
4541 bool HaveSmallAccum =
false;
4544 if (LocalAccum[0]) {
4545 if (LocalAccum.size() == 1) {
4546 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4547 HaveSmallAccum =
true;
4548 }
else if (LocalAccum[1]) {
4549 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4550 HaveSmallAccum =
false;
4552 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4553 HaveSmallAccum =
true;
4556 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4558 HaveSmallAccum =
true;
4562 unsigned j1 = DstIndex - j0;
4563 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4567 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4568 {Src0[j0], Src1[j1], Tmp});
4569 Tmp = Mad.getReg(0);
4570 if (!HaveSmallAccum)
4571 CarryOut.push_back(Mad.getReg(1));
4572 HaveSmallAccum =
false;
4575 }
while (j0 <= DstIndex);
4577 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4578 LocalAccum[0] = Unmerge.getReg(0);
4579 if (LocalAccum.size() > 1)
4580 LocalAccum[1] = Unmerge.getReg(1);
4607 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4608 Carry OddCarryIn = std::move(OddCarry);
4609 Carry EvenCarryIn = std::move(EvenCarry);
4614 if (2 * i < Accum.
size()) {
4615 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4616 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4621 if (!SeparateOddAlignedProducts) {
4622 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4623 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4625 bool IsHighest = 2 * i >= Accum.
size();
4628 .take_front(IsHighest ? 1 : 2);
4629 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4635 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4637 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4639 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4642 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4645 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4646 Lo->getOperand(1).getReg());
4647 Accum[2 * i] =
Hi.getReg(0);
4648 SeparateOddCarry =
Hi.getReg(1);
4655 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4656 EvenCarryIn.push_back(CarryOut);
4658 if (2 * i < Accum.
size()) {
4659 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4660 OddCarry.push_back(CarryOut);
4672 assert(ST.hasMad64_32());
4673 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4685 unsigned Size = Ty.getSizeInBits();
4686 if (ST.hasVMulU64Inst() &&
Size == 64)
4689 unsigned NumParts =
Size / 32;
4701 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4705 for (
unsigned i = 0; i < NumParts; ++i) {
4709 B.buildUnmerge(Src0Parts, Src0);
4710 B.buildUnmerge(Src1Parts, Src1);
4713 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4714 SeparateOddAlignedProducts);
4716 B.buildMergeLikeInstr(DstReg, AccumRegs);
4717 MI.eraseFromParent();
4732 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4733 ? AMDGPU::G_AMDGPU_FFBH_U32
4734 : AMDGPU::G_AMDGPU_FFBL_B32;
4735 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4738 MI.eraseFromParent();
4748 TypeSize NumBits = SrcTy.getSizeInBits();
4753 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4754 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4755 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4756 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4757 B.buildTrunc(Dst, Ctlz);
4758 MI.eraseFromParent();
4769 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4770 unsigned BitWidth = SrcTy.getSizeInBits();
4772 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4773 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4774 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4775 MI.eraseFromParent();
4781 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4784 return ConstVal == -1;
4791 Register CondDef =
MI.getOperand(0).getReg();
4810 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4819 UncondBrTarget = &*NextMBB;
4821 if (
Next->getOpcode() != AMDGPU::G_BR)
4840 *ArgRC,
B.getDebugLoc(), ArgTy);
4844 const unsigned Mask = Arg->
getMask();
4852 auto ShiftAmt =
B.buildConstant(I32, Shift);
4853 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4856 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4858 B.buildCopy(DstReg, LiveIn);
4868 if (!ST.hasClusters()) {
4871 MI.eraseFromParent();
4891 auto One =
B.buildConstant(I32, 1);
4892 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4893 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4894 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4901 B.buildCopy(DstReg, GlobalIdXYZ);
4902 MI.eraseFromParent();
4906 B.buildCopy(DstReg, ClusterIdXYZ);
4907 MI.eraseFromParent();
4912 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4914 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4915 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4917 .addImm(ClusterIdField);
4918 auto Zero =
B.buildConstant(I32, 0);
4921 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4922 MI.eraseFromParent();
4964 auto LoadConstant = [&](
unsigned N) {
4965 B.buildConstant(DstReg,
N);
4969 if (ST.hasArchitectedSGPRs() &&
4976 Arg = &WorkGroupIDX;
4977 ArgRC = &AMDGPU::SReg_32RegClass;
4981 Arg = &WorkGroupIDY;
4982 ArgRC = &AMDGPU::SReg_32RegClass;
4986 Arg = &WorkGroupIDZ;
4987 ArgRC = &AMDGPU::SReg_32RegClass;
4991 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
4992 return LoadConstant(0);
4993 Arg = &ClusterWorkGroupIDX;
4994 ArgRC = &AMDGPU::SReg_32RegClass;
4998 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
4999 return LoadConstant(0);
5000 Arg = &ClusterWorkGroupIDY;
5001 ArgRC = &AMDGPU::SReg_32RegClass;
5005 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5006 return LoadConstant(0);
5007 Arg = &ClusterWorkGroupIDZ;
5008 ArgRC = &AMDGPU::SReg_32RegClass;
5013 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5014 Arg = &ClusterWorkGroupMaxIDX;
5015 ArgRC = &AMDGPU::SReg_32RegClass;
5020 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5021 Arg = &ClusterWorkGroupMaxIDY;
5022 ArgRC = &AMDGPU::SReg_32RegClass;
5027 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5028 Arg = &ClusterWorkGroupMaxIDZ;
5029 ArgRC = &AMDGPU::SReg_32RegClass;
5033 Arg = &ClusterWorkGroupMaxFlatID;
5034 ArgRC = &AMDGPU::SReg_32RegClass;
5049 return LoadConstant(0);
5054 B.buildUndef(DstReg);
5058 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5070 MI.eraseFromParent();
5076 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5077 MI.eraseFromParent();
5084 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5098 B.buildUndef(DstReg);
5099 MI.eraseFromParent();
5103 if (Arg->isMasked()) {
5117 MI.eraseFromParent();
5132 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5141 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5149 Align Alignment)
const {
5153 "unexpected kernarg parameter type");
5160 MI.eraseFromParent();
5192 auto FloatY =
B.buildUITOFP(
F32,
Y);
5193 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5195 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5196 auto Z =
B.buildFPTOUI(I32, ScaledY);
5199 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5200 auto NegYZ =
B.buildMul(I32, NegY, Z);
5201 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5204 auto Q =
B.buildUMulH(I32,
X, Z);
5205 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5208 auto One =
B.buildConstant(I32, 1);
5211 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5212 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5217 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5220 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5239 auto Unmerge =
B.buildUnmerge(I32, Val);
5241 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5242 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5244 auto Mad =
B.buildFMAD(
5248 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5249 auto Mul1 =
B.buildFMul(
5253 auto Mul2 =
B.buildFMul(
5255 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5258 auto Mad2 =
B.buildFMAD(
5262 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5263 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5265 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5280 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5282 auto Zero64 =
B.buildConstant(I64, 0);
5283 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5285 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5286 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5288 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5289 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5290 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5292 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5293 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5294 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5296 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5297 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5298 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5299 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5300 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5302 auto Zero32 =
B.buildConstant(I32, 0);
5303 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5304 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5305 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5307 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5308 Register NumerLo = UnmergeNumer.getReg(0);
5309 Register NumerHi = UnmergeNumer.getReg(1);
5311 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5312 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5313 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5314 Register Mul3_Lo = UnmergeMul3.getReg(0);
5315 Register Mul3_Hi = UnmergeMul3.getReg(1);
5316 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5317 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5318 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5319 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5321 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5322 Register DenomLo = UnmergeDenom.getReg(0);
5323 Register DenomHi = UnmergeDenom.getReg(1);
5326 auto C1 =
B.buildSExt(I32, CmpHi);
5329 auto C2 =
B.buildSExt(I32, CmpLo);
5332 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5339 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5340 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5341 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5342 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5344 auto One64 =
B.buildConstant(I64, 1);
5345 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5351 auto C6 =
B.buildSelect(
5355 auto Add4 =
B.buildAdd(I64, Add3, One64);
5356 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5358 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5359 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5360 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5366 auto Sel1 =
B.buildSelect(
5373 auto Sel2 =
B.buildSelect(
5384 switch (
MI.getOpcode()) {
5387 case AMDGPU::G_UDIV: {
5388 DstDivReg =
MI.getOperand(0).getReg();
5391 case AMDGPU::G_UREM: {
5392 DstRemReg =
MI.getOperand(0).getReg();
5395 case AMDGPU::G_UDIVREM: {
5396 DstDivReg =
MI.getOperand(0).getReg();
5397 DstRemReg =
MI.getOperand(1).getReg();
5404 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5405 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5406 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5416 MI.eraseFromParent();
5427 if (Ty != I32 && Ty != I64)
5430 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5431 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5432 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5434 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5435 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5436 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5438 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5439 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5441 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5442 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5444 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5445 switch (
MI.getOpcode()) {
5448 case AMDGPU::G_SDIV: {
5449 DstDivReg =
MI.getOperand(0).getReg();
5453 case AMDGPU::G_SREM: {
5454 DstRemReg =
MI.getOperand(0).getReg();
5458 case AMDGPU::G_SDIVREM: {
5459 DstDivReg =
MI.getOperand(0).getReg();
5460 DstRemReg =
MI.getOperand(1).getReg();
5473 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5474 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5475 B.buildSub(DstDivReg, SignXor, Sign);
5479 auto Sign = LHSign.getReg(0);
5480 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5481 B.buildSub(DstRemReg, SignXor, Sign);
5484 MI.eraseFromParent();
5500 if (!AllowInaccurateRcp && ResTy !=
F16)
5511 if (CLHS->isOne()) {
5512 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5516 MI.eraseFromParent();
5521 if (CLHS->isMinusOne()) {
5522 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5523 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5524 .addUse(FNeg.getReg(0))
5527 MI.eraseFromParent();
5534 if (!AllowInaccurateRcp &&
5539 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5542 B.buildFMul(Res, LHS, RCP, Flags);
5544 MI.eraseFromParent();
5559 if (!AllowInaccurateRcp)
5567 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5569 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5570 auto One =
B.buildFConstant(ResTy, 1.0);
5572 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5576 R =
B.buildFNeg(ResTy, R);
5578 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5579 R =
B.buildFMA(ResTy, Tmp0, R, R);
5581 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5582 R =
B.buildFMA(ResTy, Tmp1, R, R);
5585 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5586 B.buildCopy(Res, R);
5587 MI.eraseFromParent();
5591 auto Ret =
B.buildFMul(ResTy,
X, R);
5592 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5594 B.buildFMA(Res, Tmp2, R, Ret);
5595 MI.eraseFromParent();
5626 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5627 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5628 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5629 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5630 .addUse(RHSExt.getReg(0))
5632 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5634 if (ST.hasMadMacF32Insts()) {
5635 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5636 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5637 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5639 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5640 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5641 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5643 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5644 auto TmpInt =
B.buildBitcast(I32, Tmp);
5645 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5646 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5647 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5648 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5649 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5650 .addUse(RDst.getReg(0))
5655 MI.eraseFromParent();
5668 unsigned SPDenormMode =
5671 if (ST.hasDenormModeInst()) {
5673 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5675 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5676 B.buildInstr(AMDGPU::S_DENORM_MODE)
5677 .addImm(NewDenormModeValue);
5680 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5681 .addImm(SPDenormMode)
5702 auto One =
B.buildFConstant(
F32, 1.0f);
5704 auto DenominatorScaled =
5705 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5710 auto NumeratorScaled =
5711 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5717 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5718 .addUse(DenominatorScaled.getReg(0))
5720 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5723 const bool HasDynamicDenormals =
5728 if (!PreservesDenormals) {
5729 if (HasDynamicDenormals) {
5731 B.buildInstr(AMDGPU::S_GETREG_B32)
5732 .addDef(SavedSPDenormMode)
5738 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5739 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5740 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5741 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5742 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5743 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5745 if (!PreservesDenormals) {
5746 if (HasDynamicDenormals) {
5747 assert(SavedSPDenormMode);
5748 B.buildInstr(AMDGPU::S_SETREG_B32)
5749 .addReg(SavedSPDenormMode)
5755 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5756 .addUse(Fma4.getReg(0))
5757 .addUse(Fma1.getReg(0))
5758 .addUse(Fma3.getReg(0))
5759 .addUse(NumeratorScaled.getReg(1))
5762 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5763 .addUse(Fmas.getReg(0))
5768 MI.eraseFromParent();
5786 auto One =
B.buildFConstant(
F64, 1.0);
5788 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5794 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5796 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5797 .addUse(DivScale0.getReg(0))
5800 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5801 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5802 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5804 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5810 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5811 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5812 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5815 if (!ST.hasUsableDivScaleConditionOutput()) {
5822 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5823 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5824 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5825 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5828 Scale1Unmerge.getReg(1));
5830 Scale0Unmerge.getReg(1));
5831 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5833 Scale = DivScale1.getReg(1);
5836 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5837 .addUse(Fma4.getReg(0))
5838 .addUse(Fma3.getReg(0))
5839 .addUse(
Mul.getReg(0))
5843 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5844 .addUse(Fmas.getReg(0))
5849 MI.eraseFromParent();
5864 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5867 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5871 if (ST.hasFractBug()) {
5872 auto Fabs =
B.buildFAbs(Ty, Val);
5876 auto Zero =
B.buildConstant(InstrExpTy, 0);
5877 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5878 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5881 B.buildCopy(Res0, Mant);
5882 B.buildSExtOrTrunc(Res1, Exp);
5884 MI.eraseFromParent();
5898 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5901 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5902 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5903 auto C2 =
B.buildFConstant(
F32, 1.0f);
5906 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5908 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5910 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5911 .addUse(Mul0.getReg(0))
5914 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5916 B.buildFMul(Res, Sel, Mul1, Flags);
5918 MI.eraseFromParent();
5927 unsigned Flags =
MI.getFlags();
5928 assert(!ST.has16BitInsts());
5929 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5930 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5931 .addUse(Ext.getReg(0))
5933 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5934 MI.eraseFromParent();
5944 const unsigned Flags =
MI.getFlags();
5952 MI.eraseFromParent();
5956 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5958 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5959 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5960 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5965 .addUse(SqrtX.getReg(0))
5968 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
5969 auto NegOne =
B.buildConstant(I32, -1);
5970 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
5972 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
5973 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
5975 auto PosOne =
B.buildConstant(I32, 1);
5976 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
5978 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
5979 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
5981 auto Zero =
B.buildFConstant(
F32, 0.0f);
5985 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
5989 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
5992 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
5993 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
5995 auto Half =
B.buildFConstant(
F32, 0.5f);
5996 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
5997 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
5998 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
5999 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6000 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6001 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6002 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6003 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6006 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6008 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6010 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6013 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6015 MI.eraseFromParent();
6049 unsigned Flags =
MI.getFlags();
6054 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6056 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6060 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6061 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6062 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6065 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6067 auto Half =
B.buildFConstant(
F64, 0.5);
6068 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6069 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6071 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6072 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6074 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6075 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6077 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6078 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6080 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6082 Register SqrtRet = SqrtS2.getReg(0);
6084 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6085 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6086 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6089 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6090 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6091 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6096 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6105 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6107 MI.eraseFromParent();
6138 auto Flags =
MI.getFlags();
6150 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6160 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6161 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6166 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6168 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6169 MI.eraseFromParent();
6181 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6182 IID == Intrinsic::amdgcn_permlanex16;
6183 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6184 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6185 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6186 IID == Intrinsic::amdgcn_permlane_up ||
6187 IID == Intrinsic::amdgcn_permlane_down ||
6188 IID == Intrinsic::amdgcn_permlane_xor;
6192 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6194 case Intrinsic::amdgcn_readfirstlane:
6195 case Intrinsic::amdgcn_permlane64:
6196 return LaneOp.getReg(0);
6197 case Intrinsic::amdgcn_readlane:
6198 case Intrinsic::amdgcn_set_inactive:
6199 case Intrinsic::amdgcn_set_inactive_chain_arg:
6200 return LaneOp.addUse(Src1).getReg(0);
6201 case Intrinsic::amdgcn_writelane:
6202 case Intrinsic::amdgcn_permlane_bcast:
6203 case Intrinsic::amdgcn_permlane_up:
6204 case Intrinsic::amdgcn_permlane_down:
6205 case Intrinsic::amdgcn_permlane_xor:
6206 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6207 case Intrinsic::amdgcn_permlane16:
6208 case Intrinsic::amdgcn_permlanex16: {
6210 int64_t Src4 =
MI.getOperand(6).getImm();
6211 int64_t Src5 =
MI.getOperand(7).getImm();
6212 return LaneOp.addUse(Src1)
6219 case Intrinsic::amdgcn_mov_dpp8:
6220 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6221 case Intrinsic::amdgcn_update_dpp:
6222 return LaneOp.addUse(Src1)
6223 .addImm(
MI.getOperand(4).getImm())
6224 .addImm(
MI.getOperand(5).getImm())
6225 .addImm(
MI.getOperand(6).getImm())
6226 .addImm(
MI.getOperand(7).getImm())
6236 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6237 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6238 IsPermlaneShuffle) {
6239 Src1 =
MI.getOperand(3).getReg();
6240 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6241 IsPermlaneShuffle) {
6242 Src2 =
MI.getOperand(4).getReg();
6247 unsigned Size = Ty.getSizeInBits();
6249 unsigned SplitSize = 32;
6250 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6251 ST.hasDPALU_DPP() &&
6255 if (
Size == SplitSize) {
6262 bool IsFloat = Ty.getScalarType().isFloat();
6266 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6268 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6270 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6274 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6276 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6277 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6279 if (IID == Intrinsic::amdgcn_writelane)
6280 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6282 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6284 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6286 B.buildTrunc(DstReg, LaneOpDst);
6287 MI.eraseFromParent();
6291 if (
Size % SplitSize != 0)
6295 bool NeedsBitcast =
false;
6296 if (IntTy.isVector()) {
6299 if (EltSize == SplitSize) {
6300 PartialResTy = EltTy;
6301 }
else if (EltSize == 16 || EltSize == 32) {
6302 unsigned NElem = SplitSize / EltSize;
6305 NeedsBitcast =
true;
6310 unsigned NumParts =
Size / SplitSize;
6314 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6315 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6317 if (IID == Intrinsic::amdgcn_writelane)
6318 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6320 for (
unsigned i = 0; i < NumParts; ++i) {
6321 Src0 = Src0Parts.
getReg(i);
6323 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6324 Src1 = Src1Parts.
getReg(i);
6326 if (IID == Intrinsic::amdgcn_writelane)
6327 Src2 = Src2Parts.
getReg(i);
6329 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6332 if (NeedsBitcast || IsFloat)
6335 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6337 B.buildMergeLikeInstr(DstReg, PartialRes);
6339 MI.eraseFromParent();
6347 ST.getTargetLowering()->getImplicitParameterOffset(
6357 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6358 B.buildConstant(IdxTy,
Offset).getReg(0));
6369 Register Pointer =
MI.getOperand(2).getReg();
6371 Register NumRecords =
MI.getOperand(4).getReg();
6377 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6379 auto ExtStride =
B.buildAnyExt(I32, Stride);
6381 if (ST.has45BitNumRecordsBufferResource()) {
6382 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6386 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6387 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6388 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6389 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6393 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6394 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6395 auto ExtShiftedStride =
6396 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6397 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6398 auto ExtShiftedFlags =
6399 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6400 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6402 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6403 B.buildMergeValues(Result, {LowHalf, HighHalf});
6405 NumRecords =
B.buildTrunc(I32, NumRecords).getReg(0);
6406 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6407 auto LowHalf = Unmerge.getReg(0);
6408 auto HighHalf = Unmerge.getReg(1);
6410 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6411 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6412 auto ShiftConst =
B.buildConstant(I32, 16);
6413 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6414 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6415 Register NewHighHalfReg = NewHighHalf.getReg(0);
6416 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6419 MI.eraseFromParent();
6436 MI.eraseFromParent();
6444 std::optional<uint32_t> KnownSize =
6446 if (KnownSize.has_value())
6447 B.buildConstant(DstReg, *KnownSize);
6465 MI.eraseFromParent();
6472 unsigned AddrSpace)
const {
6474 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6478 ST.hasGloballyAddressableScratch()) {
6480 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6481 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6483 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6485 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6487 B.buildConstant(I32, 1u << 26));
6492 MI.eraseFromParent();
6502std::pair<Register, unsigned>
6514 bool CheckNUW = ST.hasGFX1250Insts();
6516 MRI, OrigOffset,
nullptr, CheckNUW);
6520 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6530 unsigned Overflow = ImmOffset & ~MaxImm;
6531 ImmOffset -= Overflow;
6532 if ((int32_t)Overflow < 0) {
6533 Overflow += ImmOffset;
6537 if (Overflow != 0) {
6539 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6541 auto OverflowVal =
B.buildConstant(I32, Overflow);
6542 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6547 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6549 return std::pair(BaseReg, ImmOffset);
6556 bool ImageStore)
const {
6564 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6566 if (ST.hasUnpackedD16VMem()) {
6567 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6570 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6571 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6579 if (ImageStore && ST.hasImageStoreD16Bug()) {
6582 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6584 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6591 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6592 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6594 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6602 auto Unmerge =
B.buildUnmerge(I32, Reg);
6603 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6605 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6615 Reg =
B.buildPadVectorWithUndefElements(
6624 bool IsFormat)
const {
6634 VData =
B.buildBitcast(Ty, VData).getReg(0);
6642 if (Ty.isVector()) {
6643 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6655 bool IsFormat)
const {
6662 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6669 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6670 const Function &Fn =
B.getMF().getFunction();
6672 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6673 MI.eraseFromParent();
6685 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6688 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6692 VIndex =
MI.getOperand(3).getReg();
6695 VIndex =
B.buildConstant(I32, 0).getReg(0);
6698 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6699 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6703 Format =
MI.getOperand(5 + OpOffset).getImm();
6707 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6713 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6714 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6715 }
else if (IsFormat) {
6716 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6717 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6721 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6724 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6727 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6732 auto MIB =
B.buildInstr(
Opc)
6743 MIB.addImm(AuxiliaryData)
6744 .addImm(HasVIndex ? -1 : 0)
6745 .addMemOperand(MMO);
6747 MI.eraseFromParent();
6753 unsigned ImmOffset,
unsigned Format,
6756 auto MIB =
B.buildInstr(
Opc)
6767 MIB.addImm(AuxiliaryData)
6768 .addImm(HasVIndex ? -1 : 0)
6769 .addMemOperand(MMO);
6775 bool IsTyped)
const {
6789 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6790 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6792 StatusDst =
MI.getOperand(1).getReg();
6797 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6800 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6803 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6806 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6809 VIndex =
B.buildConstant(I32, 0).getReg(0);
6812 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6813 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6817 Format =
MI.getOperand(5 + OpOffset).getImm();
6821 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6831 Dst =
MI.getOperand(0).getReg();
6832 B.setInsertPt(
B.getMBB(),
MI);
6839 Dst =
MI.getOperand(0).getReg();
6840 B.setInsertPt(
B.getMBB(),
MI);
6844 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6845 const bool Unpacked = ST.hasUnpackedD16VMem();
6847 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6848 const Function &Fn =
B.getMF().getFunction();
6850 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6853 B.buildUndef(StatusDst);
6854 MI.eraseFromParent();
6866 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6867 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6868 }
else if (IsFormat) {
6872 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6874 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6875 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6880 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6881 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6884 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6885 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6888 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6889 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6895 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6896 unsigned NumLoadDWords = NumValueDWords + 1;
6898 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6900 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6901 bool IsFloat = Ty.getScalarType().isFloat();
6906 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6908 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6909 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6910 B.buildTrunc(DstInt, ExtDst);
6911 }
else if (NumValueDWords == 1) {
6912 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6915 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6916 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6918 B.buildUnmerge(LoadElts, LoadDstReg);
6920 B.buildMergeLikeInstr(DstInt, LoadElts);
6923 B.buildBitcast(Dst, DstInt);
6925 (IsD16 && !Ty.isVector())) {
6926 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6928 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6929 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6930 B.buildTrunc(Dst, LoadDstReg);
6931 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6933 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6935 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6936 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6938 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6940 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6941 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6942 B.buildMergeLikeInstr(Dst, Repack);
6945 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6948 MI.eraseFromParent();
6954 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6955 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6956 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6957 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6958 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6959 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6960 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6961 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6962 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6963 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6964 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6965 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6966 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6967 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6968 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6969 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6970 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6971 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6972 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6973 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6974 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6975 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6976 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6977 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
6978 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
6979 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
6980 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
6981 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
6982 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
6983 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
6984 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
6985 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
6986 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
6987 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
6988 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
6989 case Intrinsic::amdgcn_raw_buffer_atomic_and:
6990 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
6991 case Intrinsic::amdgcn_struct_buffer_atomic_and:
6992 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
6993 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
6994 case Intrinsic::amdgcn_raw_buffer_atomic_or:
6995 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
6996 case Intrinsic::amdgcn_struct_buffer_atomic_or:
6997 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
6998 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
6999 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7000 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7001 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7002 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7003 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7004 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7005 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7006 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7007 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7008 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7009 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7010 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7011 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7012 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7013 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7014 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7015 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7016 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7017 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7018 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7019 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7020 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7021 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7022 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7023 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7024 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7025 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7026 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7027 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7028 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7029 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7030 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7031 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7032 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7033 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7034 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7035 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7036 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7037 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7038 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7039 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7040 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7041 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7042 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7043 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7052 const bool IsCmpSwap =
7053 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7054 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7055 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7056 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7067 CmpVal =
MI.getOperand(3).getReg();
7072 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7073 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7076 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7079 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7085 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7086 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7087 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7106 .addImm(AuxiliaryData)
7107 .addImm(HasVIndex ? -1 : 0)
7108 .addMemOperand(MMO);
7110 MI.eraseFromParent();
7120 bool IsA16,
bool IsG16) {
7134 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7139 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7143 "Bias needs to be converted to 16 bit in A16 mode");
7145 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7149 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7153 if (((
I + 1) >= EndIdx) ||
7160 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7162 B.buildBuildVector(V2EltTy,
7163 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7168 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7179 int DimIdx,
int NumVAddrs) {
7181 for (
int I = 0;
I != NumVAddrs; ++
I) {
7183 if (
SrcOp.isReg()) {
7186 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7187 if (
B.getMRI()->getType(
Reg) != I32)
7188 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7193 int NumAddrRegs = AddrRegs.
size();
7194 if (NumAddrRegs != 1) {
7195 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7198 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7201 for (
int I = 1;
I != NumVAddrs; ++
I) {
7204 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7226 const unsigned NumDefs =
MI.getNumExplicitDefs();
7227 const unsigned ArgOffset = NumDefs + 1;
7228 bool IsTFE = NumDefs == 2;
7246 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7250 const bool IsAtomicPacked16Bit =
7251 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7252 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7259 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7260 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7261 const bool DataTyIs16 =
7262 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7264 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7265 const bool IsA16 = AddrTyIs16;
7266 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7269 if (!BaseOpcode->
Atomic) {
7270 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7273 }
else if (DMask != 0) {
7275 }
else if (!IsTFE && !BaseOpcode->
Store) {
7277 B.buildUndef(
MI.getOperand(0));
7278 MI.eraseFromParent();
7286 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7287 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7288 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7289 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7290 unsigned NewOpcode = LoadOpcode;
7291 if (BaseOpcode->
Store)
7292 NewOpcode = StoreOpcode;
7294 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7297 MI.setDesc(
B.getTII().get(NewOpcode));
7301 if (IsTFE && DMask == 0) {
7304 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7307 if (BaseOpcode->
Atomic) {
7312 if (Ty.isVector() && !IsAtomicPacked16Bit)
7319 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7320 MI.getOperand(2).setReg(
Concat.getReg(0));
7321 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7325 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7328 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7334 if (IsA16 && !ST.hasA16()) {
7339 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7340 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7342 if (IsA16 || IsG16) {
7350 const bool UseNSA = ST.hasNSAEncoding() &&
7351 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7352 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7353 const bool UsePartialNSA =
7354 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7356 if (UsePartialNSA) {
7360 auto Concat =
B.buildConcatVectors(
7361 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7362 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7363 PackedRegs.
resize(NSAMaxSize);
7364 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7366 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7367 PackedRegs[0] =
Concat.getReg(0);
7371 const unsigned NumPacked = PackedRegs.
size();
7374 if (!
SrcOp.isReg()) {
7384 SrcOp.setReg(AMDGPU::NoRegister);
7401 const bool UseNSA = ST.hasNSAEncoding() &&
7402 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7403 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7404 const bool UsePartialNSA =
7405 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7407 if (UsePartialNSA) {
7409 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7411 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7426 if (!Ty.isVector() || !IsD16)
7430 if (RepackedReg != VData) {
7431 MI.getOperand(1).setReg(RepackedReg);
7439 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7442 if (NumElts < DMaskLanes)
7445 if (NumElts > 4 || DMaskLanes > 4)
7456 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7457 const LLT AdjustedTy =
7473 if (IsD16 && ST.hasUnpackedD16VMem()) {
7480 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7481 unsigned RoundedSize = 32 * RoundedElts;
7485 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7490 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7496 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7500 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7501 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7505 MI.getOperand(0).setReg(NewResultReg);
7513 Dst1Reg =
MI.getOperand(1).getReg();
7514 if (MRI->
getType(Dst1Reg) != I32)
7518 MI.removeOperand(1);
7521 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7522 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7523 B.buildBitcast(DstReg, Unmerge.getReg(0));
7524 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7533 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7535 if (ResultNumRegs == 1) {
7537 ResultRegs[0] = NewResultReg;
7540 for (
int I = 0;
I != NumDataRegs; ++
I)
7542 B.buildUnmerge(ResultRegs, NewResultReg);
7547 ResultRegs.
resize(NumDataRegs);
7552 if (IsD16 && !Ty.isVector()) {
7553 B.buildTrunc(DstReg, ResultRegs[0]);
7558 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7559 !ST.hasUnpackedD16VMem()) {
7560 B.buildBitcast(DstReg, ResultRegs[0]);
7572 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7574 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7575 }
else if (ST.hasUnpackedD16VMem()) {
7577 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7581 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7585 for (
int I = 0;
I != NumElts; ++
I)
7592 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7593 B.buildBuildVector(DstReg, ResultRegs);
7597 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7598 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7603 if (Ty == V3I16 || Ty == V3F16) {
7605 if (ResultRegs.
size() == 1) {
7606 NewResultReg = ResultRegs[0];
7607 }
else if (ResultRegs.
size() == 2) {
7609 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7624 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7626 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7628 if (ResizeDst != DstReg)
7629 B.buildBitcast(DstReg, ResizeDst);
7633 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7634 B.buildConcatVectors(DstReg, ResultRegs);
7643 Register OrigDst =
MI.getOperand(0).getReg();
7645 LLT Ty =
B.getMRI()->getType(OrigDst);
7646 unsigned Size = Ty.getSizeInBits();
7648 bool HasMMO = !
MI.memoperands_empty();
7650 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7652 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7653 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7656 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7658 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7667 B.setInsertPt(
B.getMBB(),
MI);
7672 B.setInsertPt(
B.getMBB(),
MI);
7675 MI.setDesc(
B.getTII().get(
Opc));
7676 MI.removeOperand(1);
7682 const unsigned MemSize = (
Size + 7) / 8;
7683 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7690 MI.addMemOperand(MF, MMO);
7692 if (Dst != OrigDst) {
7693 MI.getOperand(0).setReg(Dst);
7694 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7695 B.buildTrunc(OrigDst, Dst);
7717 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7718 MI.removeOperand(0);
7728 if (!ST.hasTrapHandler() ||
7732 return ST.supportsGetDoorbellID() ?
7745 MI.eraseFromParent();
7755 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7757 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7761 MI.eraseFromParent();
7770 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7777 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7797 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7800 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7801 B.buildCopy(SGPR01, Temp);
7802 B.buildInstr(AMDGPU::S_TRAP)
7805 MI.eraseFromParent();
7816 B.buildCopy(SGPR01, LiveIn);
7817 B.buildInstr(AMDGPU::S_TRAP)
7821 MI.eraseFromParent();
7830 if (ST.hasPrivEnabledTrap2NopBug()) {
7831 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7833 MI.eraseFromParent();
7837 B.buildInstr(AMDGPU::S_TRAP)
7839 MI.eraseFromParent();
7848 if (!ST.hasTrapHandler() ||
7852 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7855 B.buildInstr(AMDGPU::S_TRAP)
7859 MI.eraseFromParent();
7873 Register NodePtr =
MI.getOperand(2).getReg();
7874 Register RayExtent =
MI.getOperand(3).getReg();
7875 Register RayOrigin =
MI.getOperand(4).getReg();
7877 Register RayInvDir =
MI.getOperand(6).getReg();
7880 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7887 const unsigned NumVDataDwords = 4;
7888 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7889 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7891 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7893 const unsigned BaseOpcodes[2][2] = {
7894 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7895 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7896 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7900 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7901 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7902 : AMDGPU::MIMGEncGfx10NSA,
7903 NumVDataDwords, NumVAddrDwords);
7907 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7908 : AMDGPU::MIMGEncGfx10Default,
7909 NumVDataDwords, NumVAddrDwords);
7914 if (UseNSA && IsGFX11Plus) {
7915 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7916 auto SrcInt =
B.buildBitcast(V3I32, Src);
7917 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7918 auto Merged =
B.buildMergeLikeInstr(
7919 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7920 Ops.push_back(Merged.getReg(0));
7923 Ops.push_back(NodePtr);
7924 Ops.push_back(RayExtent);
7925 packLanes(RayOrigin);
7928 auto UnmergeRayDir =
7929 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7930 auto UnmergeRayInvDir =
7931 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7932 auto MergedDir =
B.buildMergeLikeInstr(
7935 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7936 UnmergeRayDir.getReg(0)}))
7939 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7940 UnmergeRayDir.getReg(1)}))
7943 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7944 UnmergeRayDir.getReg(2)}))
7946 Ops.push_back(MergedDir.getReg(0));
7949 packLanes(RayInvDir);
7953 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7954 Ops.push_back(Unmerge.getReg(0));
7955 Ops.push_back(Unmerge.getReg(1));
7957 Ops.push_back(NodePtr);
7959 Ops.push_back(RayExtent);
7961 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7962 auto SrcInt =
B.buildBitcast(V3I32, Src);
7963 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7964 Ops.push_back(Unmerge.getReg(0));
7965 Ops.push_back(Unmerge.getReg(1));
7966 Ops.push_back(Unmerge.getReg(2));
7969 packLanes(RayOrigin);
7971 auto UnmergeRayDir =
7972 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7973 auto UnmergeRayInvDir =
7974 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7978 B.buildMergeLikeInstr(R1,
7979 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
7980 B.buildMergeLikeInstr(
7981 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
7982 B.buildMergeLikeInstr(
7983 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
7989 packLanes(RayInvDir);
7998 Ops.push_back(MergedOps);
8001 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8010 .addImm(IsA16 ? 1 : 0)
8013 MI.eraseFromParent();
8023 Register DstOrigin =
MI.getOperand(1).getReg();
8025 Register NodePtr =
MI.getOperand(4).getReg();
8026 Register RayExtent =
MI.getOperand(5).getReg();
8027 Register InstanceMask =
MI.getOperand(6).getReg();
8028 Register RayOrigin =
MI.getOperand(7).getReg();
8030 Register Offsets =
MI.getOperand(9).getReg();
8031 Register TDescr =
MI.getOperand(10).getReg();
8034 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8035 const unsigned NumVDataDwords = 10;
8036 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8038 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8039 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8040 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8043 auto RayExtentInstanceMaskVec =
8044 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8045 B.buildAnyExt(I32, InstanceMask)});
8047 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8048 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8054 .addUse(RayExtentInstanceMaskVec.getReg(0))
8061 MI.eraseFromParent();
8070 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8071 MI.eraseFromParent();
8078 if (!ST.hasArchitectedSGPRs())
8082 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8083 auto LSB =
B.buildConstant(I32, 25);
8084 auto Width =
B.buildConstant(I32, 5);
8085 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8086 MI.eraseFromParent();
8094 unsigned Width)
const {
8098 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8099 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8102 MI.eraseFromParent();
8122 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8126 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8129 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8130 MI.eraseFromParent();
8143 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8147 .addReg(Unmerge.getReg(0));
8151 .addReg(Unmerge.getReg(1));
8152 MI.eraseFromParent();
8164 case Intrinsic::amdgcn_icmp: {
8175 if (!Src1Const || Src1Const->Value != 0)
8179 int64_t Pred =
MI.getOperand(4).getImm();
8185 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8186 MI.eraseFromParent();
8189 case Intrinsic::sponentry:
8195 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8198 B.buildIntToPtr(DstReg, TmpReg);
8199 MI.eraseFromParent();
8201 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8203 B.buildFrameIndex(
MI.getOperand(0), FI);
8204 MI.eraseFromParent();
8207 case Intrinsic::amdgcn_if:
8208 case Intrinsic::amdgcn_else: {
8211 bool Negated =
false;
8223 std::swap(CondBrTarget, UncondBrTarget);
8225 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8226 if (IntrID == Intrinsic::amdgcn_if) {
8227 B.buildInstr(AMDGPU::SI_IF)
8230 .addMBB(UncondBrTarget);
8232 B.buildInstr(AMDGPU::SI_ELSE)
8235 .addMBB(UncondBrTarget);
8244 B.buildBr(*CondBrTarget);
8249 MI.eraseFromParent();
8250 BrCond->eraseFromParent();
8256 case Intrinsic::amdgcn_loop: {
8259 bool Negated =
false;
8269 std::swap(CondBrTarget, UncondBrTarget);
8271 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8272 B.buildInstr(AMDGPU::SI_LOOP)
8274 .addMBB(UncondBrTarget);
8279 B.buildBr(*CondBrTarget);
8281 MI.eraseFromParent();
8282 BrCond->eraseFromParent();
8289 case Intrinsic::amdgcn_wave_reduce_min:
8290 case Intrinsic::amdgcn_wave_reduce_umin:
8291 case Intrinsic::amdgcn_wave_reduce_fmin:
8292 case Intrinsic::amdgcn_wave_reduce_max:
8293 case Intrinsic::amdgcn_wave_reduce_umax:
8294 case Intrinsic::amdgcn_wave_reduce_fmax:
8295 case Intrinsic::amdgcn_wave_reduce_add:
8296 case Intrinsic::amdgcn_wave_reduce_fadd:
8297 case Intrinsic::amdgcn_wave_reduce_sub:
8298 case Intrinsic::amdgcn_wave_reduce_fsub:
8299 case Intrinsic::amdgcn_wave_reduce_and:
8300 case Intrinsic::amdgcn_wave_reduce_or:
8301 case Intrinsic::amdgcn_wave_reduce_xor: {
8306 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8307 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8308 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8309 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8310 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8311 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8312 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8313 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8314 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8321 .addUse(Ext.getReg(0))
8322 .addImm(
MI.getOperand(3).getImm());
8324 B.buildFPTrunc(DstReg, NewDst);
8326 B.buildTrunc(DstReg, NewDst);
8327 MI.eraseFromParent();
8330 case Intrinsic::amdgcn_addrspacecast_nonnull:
8332 case Intrinsic::amdgcn_make_buffer_rsrc:
8334 case Intrinsic::amdgcn_kernarg_segment_ptr:
8337 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8338 MI.eraseFromParent();
8344 case Intrinsic::amdgcn_implicitarg_ptr:
8346 case Intrinsic::amdgcn_workitem_id_x:
8349 case Intrinsic::amdgcn_workitem_id_y:
8352 case Intrinsic::amdgcn_workitem_id_z:
8355 case Intrinsic::amdgcn_workgroup_id_x:
8360 case Intrinsic::amdgcn_workgroup_id_y:
8365 case Intrinsic::amdgcn_workgroup_id_z:
8370 case Intrinsic::amdgcn_cluster_id_x:
8371 return ST.hasClusters() &&
8374 case Intrinsic::amdgcn_cluster_id_y:
8375 return ST.hasClusters() &&
8378 case Intrinsic::amdgcn_cluster_id_z:
8379 return ST.hasClusters() &&
8382 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8383 return ST.hasClusters() &&
8386 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8387 return ST.hasClusters() &&
8390 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8391 return ST.hasClusters() &&
8394 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8395 return ST.hasClusters() &&
8397 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8398 return ST.hasClusters() &&
8401 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8402 return ST.hasClusters() &&
8405 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8406 return ST.hasClusters() &&
8409 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8410 return ST.hasClusters() &&
8414 case Intrinsic::amdgcn_wave_id:
8416 case Intrinsic::amdgcn_lds_kernel_id:
8419 case Intrinsic::amdgcn_dispatch_ptr:
8422 case Intrinsic::amdgcn_queue_ptr:
8425 case Intrinsic::amdgcn_implicit_buffer_ptr:
8428 case Intrinsic::amdgcn_dispatch_id:
8431 case Intrinsic::r600_read_ngroups_x:
8435 case Intrinsic::r600_read_ngroups_y:
8438 case Intrinsic::r600_read_ngroups_z:
8441 case Intrinsic::r600_read_local_size_x:
8444 case Intrinsic::r600_read_local_size_y:
8448 case Intrinsic::r600_read_local_size_z:
8451 case Intrinsic::amdgcn_fdiv_fast:
8453 case Intrinsic::amdgcn_is_shared:
8455 case Intrinsic::amdgcn_is_private:
8457 case Intrinsic::amdgcn_wavefrontsize: {
8458 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8459 MI.eraseFromParent();
8462 case Intrinsic::amdgcn_s_buffer_load:
8463 case Intrinsic::amdgcn_ptr_s_buffer_load:
8465 case Intrinsic::amdgcn_raw_buffer_store:
8466 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8467 case Intrinsic::amdgcn_struct_buffer_store:
8468 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8470 case Intrinsic::amdgcn_raw_buffer_store_format:
8471 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8472 case Intrinsic::amdgcn_struct_buffer_store_format:
8473 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8475 case Intrinsic::amdgcn_raw_tbuffer_store:
8476 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8477 case Intrinsic::amdgcn_struct_tbuffer_store:
8478 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8480 case Intrinsic::amdgcn_raw_buffer_load:
8481 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8482 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8483 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8484 case Intrinsic::amdgcn_struct_buffer_load:
8485 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8486 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8487 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8489 case Intrinsic::amdgcn_raw_buffer_load_format:
8490 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8491 case Intrinsic::amdgcn_struct_buffer_load_format:
8492 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8494 case Intrinsic::amdgcn_raw_tbuffer_load:
8495 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8496 case Intrinsic::amdgcn_struct_tbuffer_load:
8497 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8499 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8500 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8501 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8502 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8503 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8504 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8505 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8506 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8507 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8508 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8509 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8510 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8511 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8512 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8513 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8514 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8515 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8516 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8517 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8518 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8519 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8520 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8521 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8522 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8523 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8524 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8525 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8526 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8527 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8528 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8529 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8530 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8531 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8532 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8533 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8534 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8535 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8536 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8537 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8538 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8539 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8540 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8541 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8542 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8543 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8544 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8545 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8546 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8547 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8548 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8549 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8550 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8551 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8552 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8553 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8554 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8555 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8556 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8557 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8558 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8559 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8560 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8561 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8562 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8563 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8564 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8565 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8566 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8567 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8568 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8569 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8570 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8572 case Intrinsic::amdgcn_rsq_clamp:
8574 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8576 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8577 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8579 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8580 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8581 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8582 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8583 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8584 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8585 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8586 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8590 if (IndexArgTy != I64) {
8591 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8592 :
B.buildAnyExt(I64, Index);
8593 MI.getOperand(5).setReg(NewIndex.getReg(0));
8597 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8598 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8599 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8600 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8601 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8602 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8603 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8604 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8607 if (MRI.
getType(Index) != I32)
8608 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8611 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8612 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8613 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8614 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8615 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8616 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8617 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8618 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8619 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8621 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8625 if (IndexArgTy != IdxTy) {
8626 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8627 :
B.buildAnyExt(IdxTy, Index);
8628 MI.getOperand(7).setReg(NewIndex.getReg(0));
8633 case Intrinsic::amdgcn_fmed3: {
8639 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8640 MI.removeOperand(1);
8644 case Intrinsic::amdgcn_readlane:
8645 case Intrinsic::amdgcn_writelane:
8646 case Intrinsic::amdgcn_readfirstlane:
8647 case Intrinsic::amdgcn_permlane16:
8648 case Intrinsic::amdgcn_permlanex16:
8649 case Intrinsic::amdgcn_permlane64:
8650 case Intrinsic::amdgcn_set_inactive:
8651 case Intrinsic::amdgcn_set_inactive_chain_arg:
8652 case Intrinsic::amdgcn_mov_dpp8:
8653 case Intrinsic::amdgcn_update_dpp:
8654 case Intrinsic::amdgcn_permlane_bcast:
8655 case Intrinsic::amdgcn_permlane_up:
8656 case Intrinsic::amdgcn_permlane_down:
8657 case Intrinsic::amdgcn_permlane_xor:
8659 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8661 case Intrinsic::amdgcn_dead: {
8665 MI.eraseFromParent();
8668 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8669 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8670 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8671 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8672 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8673 MI.eraseFromParent();
8675 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8676 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8677 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8678 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8679 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8680 MI.eraseFromParent();
8682 case Intrinsic::amdgcn_av_load_b128:
8683 case Intrinsic::amdgcn_av_store_b128: {
8684 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8685 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8686 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8688 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8689 **
MI.memoperands_begin());
8690 MI.eraseFromParent();
8693 case Intrinsic::amdgcn_flat_load_monitor_b32:
8694 case Intrinsic::amdgcn_flat_load_monitor_b64:
8695 case Intrinsic::amdgcn_flat_load_monitor_b128:
8696 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8697 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8698 .add(
MI.getOperand(0))
8699 .add(
MI.getOperand(2))
8700 .addMemOperand(*
MI.memoperands_begin());
8701 MI.eraseFromParent();
8703 case Intrinsic::amdgcn_global_load_monitor_b32:
8704 case Intrinsic::amdgcn_global_load_monitor_b64:
8705 case Intrinsic::amdgcn_global_load_monitor_b128:
8706 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8707 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8708 .add(
MI.getOperand(0))
8709 .add(
MI.getOperand(2))
8710 .addMemOperand(*
MI.memoperands_begin());
8711 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFPow(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & unsupported()
The instruction is unsupported.
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 & 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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void truncate(size_type N)
Like resize, but requires that N is less than size().
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
unsigned getPointerSizeInBits(unsigned AS) const
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
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.