36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
154 const LLT Ty = Query.Types[TypeIdx];
156 const unsigned EltSize = Ty.getElementType().getSizeInBits();
159 assert(EltSize == 32 || EltSize == 64);
164 for (NewNumElts = NumElts; NewNumElts < MaxNumElts; ++NewNumElts) {
168 return std::pair(TypeIdx,
183 const unsigned NumElems = Ty.getElementCount().getFixedValue();
188 const unsigned Size = Ty.getSizeInBits();
201 const LLT Ty = Query.Types[TypeIdx];
208 const LLT Ty = Query.Types[TypeIdx];
209 unsigned Size = Ty.getSizeInBits();
211 return std::pair(TypeIdx,
219 const LLT QueryTy = Query.Types[TypeIdx];
226 const LLT QueryTy = Query.Types[TypeIdx];
233 const LLT QueryTy = Query.Types[TypeIdx];
239 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
245 return EltSize == 16 || EltSize % 32 == 0;
249 const int EltSize = Ty.getElementType().getSizeInBits();
250 return EltSize == 32 || EltSize == 64 ||
251 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
252 EltSize == 128 || EltSize == 256;
281 LLT Ty = Query.Types[TypeIdx];
289 const LLT QueryTy = Query.Types[TypeIdx];
377 if (Ty.isPointerOrPointerVector())
378 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
382 (ST.useRealTrue16Insts() && Ty ==
S16) ||
397 const LLT Ty = Query.Types[TypeIdx];
398 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
399 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
407 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
417 bool IsLoad,
bool IsAtomic) {
421 return ST.hasFlatScratchEnabled() ? 128 : 32;
423 return ST.useDS128() ? 128 : 64;
434 return IsLoad ? 512 : 128;
439 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
448 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
450 unsigned RegSize = Ty.getSizeInBits();
453 unsigned AS = Query.
Types[1].getAddressSpace();
460 if (Ty.isVector() && MemSize !=
RegSize)
467 if (IsLoad && MemSize <
Size)
468 MemSize = std::max(MemSize,
Align);
475 if (IsLoad &&
RegSize == 16 && !ST.d16PreservesUnusedBits())
491 if (!ST.hasDwordx3LoadStores())
504 if (AlignBits < MemSize) {
507 Align(AlignBits / 8)))
537 const unsigned Size = Ty.getSizeInBits();
538 if (Ty.isPointerVector())
548 unsigned EltSize = Ty.getScalarSizeInBits();
549 return EltSize != 32 && EltSize != 64;
563 const unsigned Size = Ty.getSizeInBits();
564 if (
Size != MemSizeInBits)
565 return Size <= 32 && Ty.isVector();
571 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
580 uint64_t AlignInBits,
unsigned AddrSpace,
590 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
601 if (AlignInBits < RoundedSize)
608 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
620 Query.
Types[1].getAddressSpace(), Opcode);
640 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
644 std::array<Register, 4> VectorElems;
645 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
646 for (
unsigned I = 0;
I < NumParts; ++
I)
648 B.buildExtractVectorElementConstant(I32, VectorReg,
I).getReg(0);
649 B.buildMergeValues(MO, VectorElems);
654 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
655 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
656 B.buildIntToPtr(MO, Scalar);
676 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
678 for (
unsigned I = 0;
I < NumParts; ++
I)
680 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
682 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
683 return B.buildBitcast(VectorTy, Scalar).getReg(0);
711 const LLT BufferStridedPtr =
714 const LLT CodePtr = FlatPtr;
716 const std::initializer_list<LLT> AddrSpaces64 = {
717 GlobalPtr, ConstantPtr, FlatPtr
720 const std::initializer_list<LLT> AddrSpaces32 = {
721 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
724 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
726 const std::initializer_list<LLT> FPTypesBase = {
F32,
F64};
727 const std::initializer_list<LLT> FPTypes16 = {
F32,
F64,
F16};
728 const std::initializer_list<LLT> FPTypesPK16 = {
F32,
F64,
F16,
V2F16};
757 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
759 if (ST.hasAnyPackedU64Ops()) {
762 .clampMaxNumElementsStrict(0,
S16, 2)
768 }
else if (ST.hasScalarAddSub64()) {
771 .clampMaxNumElementsStrict(0,
S16, 2)
779 .clampMaxNumElementsStrict(0,
S16, 2)
786 if (ST.hasScalarSMulU64()) {
789 .clampMaxNumElementsStrict(0,
S16, 2)
797 .clampMaxNumElementsStrict(0,
S16, 2)
807 .minScalarOrElt(0,
S16)
812 }
else if (ST.has16BitInsts()) {
846 .widenScalarToNextMultipleOf(0, 32)
856 if (ST.hasMad64_32())
861 if (ST.hasIntClamp()) {
884 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
894 if (ST.hasVOP3PInsts()) {
896 .clampMaxNumElements(0,
S8, 2)
917 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
933 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
976 auto &FCanonicalizeActions =
978 auto &StrictFPOpActions =
985 if (ST.has16BitInsts()) {
986 if (ST.hasVOP3PInsts()) {
988 FCanonicalizeActions.legalFor({
F16,
V2F16});
989 StrictFPOpActions.legalFor({
F16,
V2F16});
991 FPOpActions.legalFor({
F16});
992 FCanonicalizeActions.legalFor({
F16});
993 StrictFPOpActions.legalFor({
F16});
996 TrigActions.customFor({
F16});
997 FDIVActions.customFor({
F16});
1000 if (ST.hasBF16PackedInsts()) {
1004 .clampMaxNumElementsStrict(0,
BF16, 2);
1007 .clampMaxNumElementsStrict(0,
BF16, 2);
1010 .clampMaxNumElementsStrict(0,
BF16, 2);
1016 if (ST.hasAnyPackedFP32Ops()) {
1017 FPOpActions.legalFor({
V2F32});
1018 FCanonicalizeActions.legalFor({
V2F32});
1019 StrictFPOpActions.legalFor({
V2F32});
1020 FPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1021 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F32, 2);
1022 StrictFPOpActions.clampMaxNumElementsStrict(0,
F32, 2);
1025 if (ST.hasAnyPackedFP64Ops()) {
1026 FPOpActions.legalFor({
V2F64});
1027 FCanonicalizeActions.legalFor({
V2F64});
1028 StrictFPOpActions.legalFor({
V2F64});
1029 FPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1030 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F64, 2);
1031 StrictFPOpActions.clampMaxNumElementsStrict(0,
F64, 2);
1034 auto &MinNumMaxNumIeee =
1037 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1042 if (ST.has16BitInsts()) {
1043 MinNumMaxNumIeee.legalFor({
F16});
1044 MinNumMaxNum.customFor({
F16});
1048 if (ST.hasVOP3PInsts()) {
1049 MinNumMaxNumIeee.legalFor({
V2F16})
1052 .clampMaxNumElements(0,
F16, 2);
1053 MinNumMaxNum.customFor({
V2F16})
1056 .clampMaxNumElements(0,
F16, 2);
1060 if (ST.hasAnyPackedFP64Ops()) {
1061 MinNumMaxNum.customFor({
V2F64})
1064 .clampMaxNumElements(0,
F64, 2);
1068 if (ST.hasBF16PackedInsts()) {
1069 MinNumMaxNumIeee.legalFor({
V2BF16}).clampMaxNumElementsStrict(0,
BF16, 2);
1072 .clampMaxNumElementsStrict(0,
BF16, 2);
1080 if (!ST.has16BitInsts()) {
1081 MinNumMaxNumIeee.minScalar(0,
F32);
1082 MinNumMaxNum.minScalar(0,
F32);
1085 if (ST.hasVOP3PInsts()) {
1086 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1087 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1088 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1096 if (!ST.has16BitInsts()) {
1107 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1110 if (ST.hasAnyPackedFP32Ops())
1114 if (ST.has16BitInsts()) {
1117 .legalFor(ST.hasBF16TransInsts(), {BF16})
1127 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1149 if (ST.hasFractBug()) {
1163 .legalFor({{
F32, I32}, {
F64, I32}})
1183 if (ST.hasCvtPkF16F32Inst()) {
1185 .clampMaxNumElements(0,
F16, 2);
1198 if (ST.has16BitInsts()) {
1212 if (ST.hasBF16PackedInsts()) {
1215 .clampMaxNumElementsStrict(0,
BF16, 2);
1220 if (ST.hasAnyPackedFP32Ops())
1228 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1229 FMad.customFor({
F32,
F16});
1230 else if (ST.hasMadMacF32Insts())
1231 FMad.customFor({
F32});
1232 else if (ST.hasMadF16())
1233 FMad.customFor({
F16});
1238 if (ST.has16BitInsts()) {
1241 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1249 .clampMaxNumElements(0,
S16, 2)
1265 .legalFor({{
F32, I32}, {
F64, I32}})
1269 if (ST.has16BitInsts())
1277 .legalFor({{I32,
F32}, {I32,
F64}})
1278 .customFor({{I64,
F32}, {I64,
F64}})
1281 .widenScalarFor({{I16,
BF16}, {I32,
BF16}, {I64,
BF16}},
1283 if (ST.has16BitInsts())
1292 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1293 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1294 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1298 if (
ST.has16BitInsts())
1301 if (
ST.hasVCvtPkIU16F32())
1311 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1312 .clampScalar(0, I16, I64)
1316 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1322 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1326 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1327 .clampScalar(0, I16, I64)
1331 auto &RoundingActions = getActionDefinitionsBuilder(
1332 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1333 if (
ST.has16BitInsts())
1341 if (!
ST.has16BitInsts())
1344 getActionDefinitionsBuilder(G_PTR_ADD)
1350 getActionDefinitionsBuilder(G_PTRMASK)
1352 .scalarSameSizeAs(1, 0)
1356 getActionDefinitionsBuilder(G_ICMP)
1368 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1369 .legalForCartesianProduct(
1370 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1371 if (
ST.has16BitInsts()) {
1372 CmpBuilder.legalFor({{
S1,
S16}});
1381 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1384 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1385 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1387 if (
ST.hasSALUFloatInsts())
1388 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1391 .widenScalarToNextPow2(1)
1395 getActionDefinitionsBuilder(G_FPOW)
1397 .clampScalar(0,
F32,
F32)
1400 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1402 getActionDefinitionsBuilder(G_FLOG2)
1403 .legalFor(
ST.has16BitInsts(), {F16})
1404 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1410 getActionDefinitionsBuilder(G_FEXP2)
1411 .legalFor(
ST.has16BitInsts(), {F16})
1412 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1418 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1422 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1427 getActionDefinitionsBuilder(G_CTPOP)
1429 .clampScalar(0,
S32,
S32)
1430 .widenScalarToNextPow2(1, 32)
1431 .clampScalar(1,
S32,
S64)
1433 .widenScalarToNextPow2(0, 32);
1436 if (
ST.has16BitInsts())
1437 getActionDefinitionsBuilder(G_IS_FPCLASS)
1438 .legalForCartesianProduct({
I1}, FPTypes16)
1439 .widenScalarToNextPow2(1)
1443 getActionDefinitionsBuilder(G_IS_FPCLASS)
1444 .legalForCartesianProduct({
I1}, FPTypesBase)
1445 .lowerFor({
I1,
F16})
1446 .widenScalarToNextPow2(1)
1453 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1455 .clampScalar(0,
S32,
S32)
1456 .clampScalar(1,
S32,
S64)
1457 .widenScalarToNextPow2(0, 32)
1458 .widenScalarToNextPow2(1, 32)
1462 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1465 .clampScalar(0,
S32,
S32)
1466 .clampScalar(1,
S32,
S64)
1468 .widenScalarToNextPow2(0, 32)
1469 .widenScalarToNextPow2(1, 32);
1471 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1473 .clampScalar(0,
S32,
S32)
1474 .clampScalar(1,
S32,
S64)
1476 .widenScalarToNextPow2(0, 32)
1477 .widenScalarToNextPow2(1, 32);
1479 getActionDefinitionsBuilder(G_CTLS)
1482 .clampScalar(0,
S32,
S32)
1483 .clampScalar(1,
S32,
S32);
1487 getActionDefinitionsBuilder(G_BITREVERSE)
1489 .clampScalar(0,
S32,
S64)
1491 .widenScalarToNextPow2(0);
1493 if (
ST.has16BitInsts()) {
1494 getActionDefinitionsBuilder(G_BSWAP)
1496 .clampMaxNumElementsStrict(0,
S16, 2)
1499 .widenScalarToNextPow2(0)
1500 .clampScalar(0,
S16,
S32)
1503 if (
ST.hasVOP3PInsts()) {
1504 getActionDefinitionsBuilder(G_ABS)
1506 .clampMaxNumElements(0,
S16, 2)
1508 .widenScalarToNextPow2(0)
1511 if (
ST.useMinMaxI64Insts()) {
1512 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1514 .clampMaxNumElements(0,
S16, 2)
1516 .widenScalarToNextPow2(0)
1520 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1522 .clampMaxNumElements(0,
S16, 2)
1524 .widenScalarToNextPow2(0)
1529 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1531 .widenScalarToNextPow2(0)
1538 getActionDefinitionsBuilder(G_BSWAP)
1543 .widenScalarToNextPow2(0)
1548 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1551 .widenScalarToNextPow2(0)
1556 getActionDefinitionsBuilder(G_INTTOPTR)
1558 .legalForCartesianProduct(AddrSpaces64, {
S64})
1559 .legalForCartesianProduct(AddrSpaces32, {
S32})
1572 getActionDefinitionsBuilder(G_PTRTOINT)
1574 .legalForCartesianProduct(AddrSpaces64, {
S64})
1575 .legalForCartesianProduct(AddrSpaces32, {
S32})
1588 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1592 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1593 bool IsLoad) ->
bool {
1597 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1610 !
ST.hasUsableDSOffset() && Query.
MMODescrs[0].AlignInBits == 32)
1615 unsigned NumRegs = (MemSize + 31) / 32;
1617 if (!
ST.hasDwordx3LoadStores())
1628 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1629 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1630 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1631 unsigned LocalAlign64 =
ST.hasUsableDSOffset() ? 32 : 64;
1637 for (
unsigned Op : {G_LOAD, G_STORE}) {
1638 const bool IsStore =
Op == G_STORE;
1640 auto &Actions = getActionDefinitionsBuilder(
Op);
1643 Actions.legalForTypesWithMemDesc(
1644 {{
S32, GlobalPtr,
S32, GlobalAlign32},
1647 {
S64, GlobalPtr,
S64, GlobalAlign32},
1650 {
S32, GlobalPtr,
S8, GlobalAlign8},
1651 {
S32, GlobalPtr,
S16, GlobalAlign16},
1653 {
S32, LocalPtr,
S32, 32},
1654 {
S64, LocalPtr,
S64, LocalAlign64},
1656 {
S32, LocalPtr,
S8, 8},
1657 {
S32, LocalPtr,
S16, 16},
1660 {
S32, PrivatePtr,
S32, 32},
1661 {
S32, PrivatePtr,
S8, 8},
1662 {
S32, PrivatePtr,
S16, 16},
1665 {
S32, ConstantPtr,
S32, GlobalAlign32},
1668 {
S64, ConstantPtr,
S64, GlobalAlign32}});
1670 if (IsStore ||
ST.d16PreservesUnusedBits()) {
1671 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1672 {{S16, GlobalPtr, S8, GlobalAlign8},
1673 {S16, GlobalPtr, S16, GlobalAlign16},
1674 {S16, LocalPtr, S8, 8},
1675 {S16, LocalPtr, S16, 16},
1676 {S16, PrivatePtr, S8, 8},
1677 {S16, PrivatePtr, S16, 16}});
1688 Actions.unsupportedIf(
1689 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1703 Actions.customIf(
typeIs(1, Constant32Ptr));
1729 return !Query.
Types[0].isVector() &&
1730 needToSplitMemOp(Query,
Op == G_LOAD);
1732 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1737 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1740 if (DstSize > MemSize)
1746 if (MemSize > MaxSize)
1754 return Query.
Types[0].isVector() &&
1755 needToSplitMemOp(Query,
Op == G_LOAD);
1757 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1771 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1772 if (MemSize > MaxSize) {
1776 if (MaxSize % EltSize == 0) {
1782 unsigned NumPieces = MemSize / MaxSize;
1786 if (NumPieces == 1 || NumPieces >= NumElts ||
1787 NumElts % NumPieces != 0)
1788 return std::pair(0, EltTy);
1796 return std::pair(0, EltTy);
1811 return std::pair(0, EltTy);
1816 .widenScalarToNextPow2(0)
1823 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1824 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1825 {
S32, GlobalPtr,
S16, 2 * 8},
1826 {
S32, LocalPtr,
S8, 8},
1827 {
S32, LocalPtr,
S16, 16},
1828 {
S32, PrivatePtr,
S8, 8},
1829 {
S32, PrivatePtr,
S16, 16},
1830 {
S32, ConstantPtr,
S8, 8},
1831 {
S32, ConstantPtr,
S16, 2 * 8}})
1832 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1833 {{S16, GlobalPtr, S8, GlobalAlign8},
1834 {S16, LocalPtr, S8, GlobalAlign8},
1835 {S16, PrivatePtr, S8, GlobalAlign8},
1836 {S16, ConstantPtr, S8, GlobalAlign8}})
1841 if (
ST.hasFlatAddressSpace()) {
1842 ExtLoads.legalForTypesWithMemDesc(
1843 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1845 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1846 {{S16, FlatPtr, S8, GlobalAlign8}});
1854 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1856 ExtLoads.narrowScalarIf(
1863 ExtLoads.clampScalar(0,
S32,
S32)
1864 .widenScalarToNextPow2(0)
1867 auto &Atomics = getActionDefinitionsBuilder(
1868 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1869 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1870 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1871 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1872 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1873 {
S64, GlobalPtr}, {
S64, LocalPtr},
1874 {
S32, RegionPtr}, {
S64, RegionPtr}});
1875 if (
ST.hasFlatAddressSpace()) {
1876 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1880 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1881 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1882 if (
ST.hasFlatAddressSpace()) {
1883 Atomics32.legalFor({{
S32, FlatPtr}});
1887 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1888 if (
ST.hasLDSFPAtomicAddF32()) {
1890 if (
ST.hasLdsAtomicAddF64())
1892 if (
ST.hasAtomicDsPkAdd16Insts())
1895 if (
ST.hasAtomicFaddInsts())
1897 if (
ST.hasFlatAtomicFaddF32Inst())
1900 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1904 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1907 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1908 ST.hasAtomicBufferGlobalPkAddF16Insts())
1910 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1912 if (
ST.hasAtomicFlatPkAdd16Insts())
1918 auto &AtomicFMinFMax =
1919 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1920 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1922 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1923 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1924 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1925 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1926 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1927 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1928 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1929 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1933 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1934 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1935 {
S32, FlatPtr}, {
S64, FlatPtr}})
1936 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1937 {
S32, RegionPtr}, {
S64, RegionPtr}});
1941 getActionDefinitionsBuilder(G_SELECT)
1943 LocalPtr, FlatPtr, PrivatePtr,
1947 .clampScalar(0,
S16,
S64)
1951 .clampMaxNumElements(0,
S32, 2)
1952 .clampMaxNumElements(0, LocalPtr, 2)
1953 .clampMaxNumElements(0, PrivatePtr, 2)
1955 .widenScalarToNextPow2(0)
1960 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1962 if (
ST.has16BitInsts()) {
1963 if (
ST.hasVOP3PInsts()) {
1965 .clampMaxNumElements(0,
S16, 2);
1967 Shifts.legalFor({{
S16,
S16}});
1970 Shifts.widenScalarIf(
1975 const LLT AmountTy = Query.
Types[1];
1981 Shifts.clampScalar(1,
S32,
S32);
1982 Shifts.widenScalarToNextPow2(0, 16);
1983 Shifts.clampScalar(0,
S16,
S64);
1985 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1993 Shifts.clampScalar(1,
S32,
S32);
1994 Shifts.widenScalarToNextPow2(0, 32);
1995 Shifts.clampScalar(0,
S32,
S64);
1997 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2002 Shifts.scalarize(0);
2004 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
2005 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
2006 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
2007 unsigned IdxTypeIdx = 2;
2009 getActionDefinitionsBuilder(
Op)
2011 const LLT EltTy = Query.
Types[EltTypeIdx];
2012 const LLT VecTy = Query.
Types[VecTypeIdx];
2013 const LLT IdxTy = Query.
Types[IdxTypeIdx];
2015 const bool isLegalVecType =
2025 return (EltSize == 32 || EltSize == 64) &&
2041 const LLT EltTy = Query.
Types[EltTypeIdx];
2042 const LLT VecTy = Query.
Types[VecTypeIdx];
2046 const unsigned TargetEltSize =
2047 DstEltSize % 64 == 0 ? 64 : 32;
2048 return std::pair(VecTypeIdx,
2052 .clampScalar(EltTypeIdx,
S32,
S64)
2053 .clampScalar(VecTypeIdx,
S32,
S64)
2054 .clampScalar(IdxTypeIdx,
S32,
S32)
2055 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2064 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2066 const LLT &EltTy = Query.
Types[1].getElementType();
2067 return Query.
Types[0] != EltTy;
2070 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2071 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2072 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2073 getActionDefinitionsBuilder(
Op)
2076 const LLT BigTy = Query.
Types[BigTyIdx];
2082 const LLT LitTy = Query.
Types[LitTyIdx];
2087 .widenScalarToNextPow2(BigTyIdx, 32)
2095 const LLT BigTy = Query.
Types[BigTyIdx];
2096 const LLT LitTy = Query.
Types[LitTyIdx];
2104 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2114 if (
ST.hasScalarPackInsts()) {
2117 .minScalarOrElt(0,
S16)
2120 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2124 BuildVector.customFor({
V2S16,
S16});
2125 BuildVector.minScalarOrElt(0,
S32);
2127 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2135 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2137 .clampMaxNumElements(0,
S32, 32)
2138 .clampMaxNumElements(1,
S16, 2)
2139 .clampMaxNumElements(0,
S16, 64);
2141 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2144 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2145 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2146 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2148 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2149 const LLT Ty = Query.
Types[TypeIdx];
2161 getActionDefinitionsBuilder(
Op)
2165 const LLT BigTy = Query.
Types[BigTyIdx];
2171 .widenScalarToNextPow2(LitTyIdx, 16)
2180 .clampScalar(LitTyIdx,
S32,
S512)
2181 .widenScalarToNextPow2(LitTyIdx, 32)
2185 return notValidElt(Query, LitTyIdx);
2190 return notValidElt(Query, BigTyIdx);
2195 if (
Op == G_MERGE_VALUES) {
2196 Builder.widenScalarIf(
2199 const LLT Ty = Query.
Types[LitTyIdx];
2205 Builder.widenScalarIf(
2207 const LLT Ty = Query.
Types[BigTyIdx];
2213 const LLT &Ty = Query.
Types[BigTyIdx];
2215 if (NewSizeInBits >= 256) {
2217 if (RoundedTo < NewSizeInBits)
2218 NewSizeInBits = RoundedTo;
2220 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2229 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2230 .legalFor({{
S32}, {
S64}})
2231 .clampScalar(0,
S32,
S64);
2233 if (
ST.hasVOP3PInsts()) {
2234 SextInReg.lowerFor({{
V2S16}})
2238 .clampMaxNumElementsStrict(0,
S16, 2);
2239 }
else if (
ST.has16BitInsts()) {
2240 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2244 SextInReg.lowerFor({{
S32}, {
S64}});
2249 .clampScalar(0,
S32,
S64)
2252 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2256 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2257 FSHRActionDefs.legalFor({{
S32,
S32}})
2258 .clampMaxNumElementsStrict(0,
S16, 2);
2259 if (
ST.hasVOP3PInsts())
2261 FSHRActionDefs.scalarize(0).lower();
2263 if (
ST.hasVOP3PInsts()) {
2264 getActionDefinitionsBuilder(G_FSHL)
2266 .clampMaxNumElementsStrict(0,
S16, 2)
2270 getActionDefinitionsBuilder(G_FSHL)
2275 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2278 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2280 getActionDefinitionsBuilder(G_FENCE)
2283 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2288 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2290 .clampScalar(1,
S32,
S32)
2291 .clampScalar(0,
S32,
S64)
2292 .widenScalarToNextPow2(0)
2295 getActionDefinitionsBuilder(
2299 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2305 if (
ST.hasIEEEMinimumMaximumInsts()) {
2306 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2307 .legalFor(FPTypesPK16)
2308 .clampMaxNumElements(0,
F16, 2)
2310 }
else if (
ST.hasVOP3PInsts()) {
2311 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2313 .clampMaxNumElementsStrict(0,
F16, 2)
2317 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2319 .clampScalar(0,
F32,
F64)
2323 getActionDefinitionsBuilder(
2324 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2327 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2329 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2330 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2331 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2334 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2336 getActionDefinitionsBuilder(
2337 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2338 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2339 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2340 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2345 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2346 G_INTRINSIC_CONVERGENT,
2347 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2359 switch (
MI.getOpcode()) {
2360 case TargetOpcode::G_ADDRSPACE_CAST:
2362 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2364 case TargetOpcode::G_FCEIL:
2366 case TargetOpcode::G_FREM:
2368 case TargetOpcode::G_INTRINSIC_TRUNC:
2370 case TargetOpcode::G_SITOFP:
2372 case TargetOpcode::G_UITOFP:
2374 case TargetOpcode::G_FPTOSI:
2376 case TargetOpcode::G_FPTOUI:
2378 case TargetOpcode::G_FMINNUM:
2379 case TargetOpcode::G_FMAXNUM:
2380 case TargetOpcode::G_FMINIMUMNUM:
2381 case TargetOpcode::G_FMAXIMUMNUM:
2383 case TargetOpcode::G_EXTRACT:
2385 case TargetOpcode::G_INSERT:
2387 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2389 case TargetOpcode::G_INSERT_VECTOR_ELT:
2391 case TargetOpcode::G_FSIN:
2392 case TargetOpcode::G_FCOS:
2394 case TargetOpcode::G_GLOBAL_VALUE:
2396 case TargetOpcode::G_LOAD:
2397 case TargetOpcode::G_SEXTLOAD:
2398 case TargetOpcode::G_ZEXTLOAD:
2400 case TargetOpcode::G_STORE:
2402 case TargetOpcode::G_FMAD:
2404 case TargetOpcode::G_FDIV:
2406 case TargetOpcode::G_FFREXP:
2408 case TargetOpcode::G_FSQRT:
2410 case TargetOpcode::G_UDIV:
2411 case TargetOpcode::G_UREM:
2412 case TargetOpcode::G_UDIVREM:
2414 case TargetOpcode::G_SDIV:
2415 case TargetOpcode::G_SREM:
2416 case TargetOpcode::G_SDIVREM:
2418 case TargetOpcode::G_ATOMIC_CMPXCHG:
2420 case TargetOpcode::G_FLOG2:
2422 case TargetOpcode::G_FLOG:
2423 case TargetOpcode::G_FLOG10:
2425 case TargetOpcode::G_FEXP2:
2427 case TargetOpcode::G_FEXP:
2428 case TargetOpcode::G_FEXP10:
2430 case TargetOpcode::G_FPOW:
2432 case TargetOpcode::G_FFLOOR:
2434 case TargetOpcode::G_BUILD_VECTOR:
2435 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2437 case TargetOpcode::G_MUL:
2439 case TargetOpcode::G_CTLZ:
2440 case TargetOpcode::G_CTTZ:
2442 case TargetOpcode::G_CTLS:
2444 case TargetOpcode::G_CTLZ_ZERO_POISON:
2446 case TargetOpcode::G_STACKSAVE:
2448 case TargetOpcode::G_GET_FPENV:
2450 case TargetOpcode::G_SET_FPENV:
2452 case TargetOpcode::G_TRAP:
2454 case TargetOpcode::G_DEBUGTRAP:
2466 unsigned BaseAS = AS;
2471 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2475 auto Tag =
B.buildConstant(
S32, SANum);
2476 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2482Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2492 if (ST.hasApertureRegs()) {
2496 const unsigned ApertureRegNo =
2497 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2498 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2499 !ST.hasGloballyAddressableScratch()) &&
2500 "Cannot use src_private_base with globally addressable scratch!");
2503 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2504 return B.buildUnmerge(I32, Dst).getReg(1);
2519 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2535 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2538 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2552 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2560 B.buildObjectPtrOffset(
2563 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2571 switch (Def->getOpcode()) {
2572 case AMDGPU::G_FRAME_INDEX:
2573 case AMDGPU::G_GLOBAL_VALUE:
2574 case AMDGPU::G_BLOCK_ADDR:
2576 case AMDGPU::G_CONSTANT: {
2577 const ConstantInt *CI = Def->getOperand(1).getCImm();
2592 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2601 unsigned SrcAS = SrcTy.getAddressSpace();
2615 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2622 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2624 ST.hasGloballyAddressableScratch()) {
2627 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2629 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2630 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2632 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2633 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2634 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2637 return B.buildExtract(Dst, Src, 0).getReg(0);
2641 castFlatToLocalOrPrivate(Dst);
2642 MI.eraseFromParent();
2648 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2649 auto FlatNull =
B.buildConstant(SrcTy, 0);
2652 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2656 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2658 MI.eraseFromParent();
2665 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2668 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2671 ST.hasGloballyAddressableScratch()) {
2675 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2676 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2680 if (ST.isWave64()) {
2681 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2687 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2688 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2690 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2694 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2695 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2697 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2698 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2707 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2711 castLocalOrPrivateToFlat(Dst);
2712 MI.eraseFromParent();
2716 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2723 SegmentNull.getReg(0));
2725 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2727 MI.eraseFromParent();
2732 SrcTy.getSizeInBits() == 64) {
2734 B.buildExtract(Dst, Src, 0);
2735 MI.eraseFromParent();
2742 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2743 auto PtrLo =
B.buildPtrToInt(I32, Src);
2744 if (AddrHiVal == 0) {
2745 auto Zext =
B.buildZExt(I64, PtrLo);
2746 B.buildIntToPtr(Dst, Zext);
2748 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2749 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2752 MI.eraseFromParent();
2759 MI.eraseFromParent();
2768 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2773 auto C1 =
B.buildFConstant(Ty, C1Val);
2774 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2777 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2778 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2780 auto C2 =
B.buildFConstant(Ty, C2Val);
2781 auto Fabs =
B.buildFAbs(Ty, Src);
2784 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2785 MI.eraseFromParent();
2802 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2804 const auto Zero =
B.buildFConstant(
F64, 0.0);
2805 const auto One =
B.buildFConstant(
F64, 1.0);
2808 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2809 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2812 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2813 MI.eraseFromParent();
2821 Register Src0Reg =
MI.getOperand(1).getReg();
2822 Register Src1Reg =
MI.getOperand(2).getReg();
2823 auto Flags =
MI.getFlags();
2826 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2827 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2828 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2829 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2830 MI.eraseFromParent();
2836 const unsigned FractBits = 52;
2837 const unsigned ExpBits = 11;
2840 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2841 auto Const1 =
B.buildConstant(I32, ExpBits);
2843 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2845 .addUse(Const0.getReg(0))
2846 .addUse(Const1.getReg(0));
2848 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2861 auto SrcInt =
B.buildBitcast(I64, Src);
2864 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2871 const unsigned FractBits = 52;
2874 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2875 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2877 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2879 const auto Zero32 =
B.buildConstant(I32, 0);
2882 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2884 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2885 auto Not =
B.buildNot(I64, Shr);
2886 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2887 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2892 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2893 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2894 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2895 MI.eraseFromParent();
2911 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2912 auto ThirtyTwo =
B.buildConstant(I32, 32);
2915 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2916 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2918 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2919 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2922 B.buildFAdd(Dst, LdExp, CvtLo);
2923 MI.eraseFromParent();
2929 auto One =
B.buildConstant(I32, 1);
2933 auto ThirtyOne =
B.buildConstant(I32, 31);
2934 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2935 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2936 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2937 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2938 .addUse(Unmerge.getReg(1));
2939 auto LS2 =
B.buildSub(I32, LS, One);
2940 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2942 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2943 auto Norm =
B.buildShl(I64, Src, ShAmt);
2944 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2945 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2946 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2947 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2948 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2949 B.buildFLdexp(Dst, FVal, Scale);
2950 MI.eraseFromParent();
2970 unsigned Flags =
MI.getFlags();
2981 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2989 auto SrcInt =
B.buildBitcast(I32, Src);
2990 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2991 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2995 K0 =
B.buildFConstant(
2997 K1 =
B.buildFConstant(
3000 K0 =
B.buildFConstant(
3002 K1 =
B.buildFConstant(
3006 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
3007 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
3008 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
3010 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
3011 :
B.buildFPTOUI(I32, FloorMul);
3012 auto Lo =
B.buildFPTOUI(I32, Fma);
3016 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
3018 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
3021 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3022 MI.eraseFromParent();
3045 uint64_t
Offset =
MI.getOperand(2).getImm();
3054 unsigned StartIdx =
Offset / 32;
3058 if (DstCount == 1) {
3060 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3068 for (
unsigned I = 0;
I < DstCount; ++
I)
3069 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3070 B.buildMergeLikeInstr(DstReg, MergeVec);
3073 MI.eraseFromParent();
3083 Register InsertSrc =
MI.getOperand(2).getReg();
3084 uint64_t
Offset =
MI.getOperand(3).getImm();
3092 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3096 unsigned DstCount = DstSize / 32;
3097 unsigned InsertCount = InsertSize / 32;
3098 unsigned StartIdx =
Offset / 32;
3100 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3103 for (
unsigned I = 0;
I < StartIdx; ++
I)
3106 if (InsertCount == 1) {
3110 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3113 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3114 for (
unsigned I = 0;
I < InsertCount; ++
I)
3118 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3121 B.buildMergeLikeInstr(DstReg, MergeVec);
3123 MI.eraseFromParent();
3150 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3151 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3152 B.buildIntToPtr(Dst, IntElt);
3154 MI.eraseFromParent();
3161 std::optional<ValueAndVReg> MaybeIdxVal =
3165 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3168 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3169 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3174 MI.eraseFromParent();
3203 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3204 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3205 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3207 B.buildIntToPtr(Dst, IntVecDest);
3208 MI.eraseFromParent();
3215 std::optional<ValueAndVReg> MaybeIdxVal =
3220 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3223 if (IdxVal < NumElts) {
3225 for (
unsigned i = 0; i < NumElts; ++i)
3227 B.buildUnmerge(SrcRegs, Vec);
3229 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3230 B.buildMergeLikeInstr(Dst, SrcRegs);
3235 MI.eraseFromParent();
3246 unsigned Flags =
MI.getFlags();
3250 if (ST.hasTrigReducedRange()) {
3251 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3252 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3253 .addUse(MulVal.getReg(0))
3257 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3260 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3264 MI.eraseFromParent();
3272 unsigned GAFlags)
const {
3305 if (ST.has64BitLiterals()) {
3309 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3313 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3324 B.buildExtract(DstReg, PCReg, 0);
3326 B.buildCopy(DstReg, PCReg);
3336 if (RequiresHighHalf && ST.has64BitLiterals()) {
3339 B.buildInstr(AMDGPU::S_MOV_B64)
3342 B.buildCopy(DstReg, Addr);
3350 B.buildInstr(AMDGPU::S_MOV_B32)
3355 if (RequiresHighHalf) {
3357 "Must provide a 64-bit pointer type!");
3362 B.buildInstr(AMDGPU::S_MOV_B32)
3369 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3370 B.buildCast(DstReg, AddrDst);
3372 B.buildCast(DstReg, AddrLo);
3381 unsigned AS = Ty.getAddressSpace();
3392 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3394 B.buildUndef(DstReg);
3395 MI.eraseFromParent();
3399 B.buildConstant(DstReg,
3401 MI.eraseFromParent();
3407 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3410 Fn,
"local memory global used by non-kernel function",
3419 B.buildUndef(DstReg);
3420 MI.eraseFromParent();
3444 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3445 B.buildIntToPtr(DstReg, Sz);
3446 MI.eraseFromParent();
3452 MI.eraseFromParent();
3456 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3458 MI.eraseFromParent();
3466 MI.eraseFromParent();
3472 MI.eraseFromParent();
3488 if (Ty.getSizeInBits() == 32) {
3490 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3491 B.buildExtract(DstReg,
Load, 0);
3493 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3495 MI.eraseFromParent();
3518 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3520 MI.getOperand(1).setReg(Cast.getReg(0));
3525 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3543 const uint64_t AlignInBits = 8 * MemAlign.
value();
3551 if (WideMemSize == ValSize) {
3557 MI.setMemRefs(MF, {WideMMO});
3563 if (ValSize > WideMemSize)
3570 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3571 B.buildTrunc(ValReg, WideLoad).getReg(0);
3578 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3579 B.buildExtract(ValReg, WideLoad, 0);
3583 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3584 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3588 MI.eraseFromParent();
3601 Register DataReg =
MI.getOperand(0).getReg();
3646 "this should not have been custom lowered");
3651 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3653 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3657 .setMemRefs(
MI.memoperands());
3659 MI.eraseFromParent();
3667 switch (
DefMI->getOpcode()) {
3668 case TargetOpcode::G_INTRINSIC: {
3670 case Intrinsic::amdgcn_frexp_mant:
3671 case Intrinsic::amdgcn_log:
3672 case Intrinsic::amdgcn_log_clamp:
3673 case Intrinsic::amdgcn_exp2:
3674 case Intrinsic::amdgcn_sqrt:
3682 case TargetOpcode::G_FSQRT:
3684 case TargetOpcode::G_FFREXP: {
3685 if (
DefMI->getOperand(0).getReg() == Src)
3689 case TargetOpcode::G_FPEXT: {
3710std::pair<Register, Register>
3712 unsigned Flags)
const {
3716 auto SmallestNormal =
B.buildFConstant(
3718 auto IsLtSmallestNormal =
3721 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3722 auto One =
B.buildFConstant(
F32, 1.0);
3724 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3725 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3727 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3740 LLT Ty =
B.getMRI()->getType(Dst);
3741 unsigned Flags =
MI.getFlags();
3745 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3746 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3747 .addUse(Ext.getReg(0))
3749 B.buildFPTrunc(Dst,
Log2, Flags);
3750 MI.eraseFromParent();
3758 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3761 MI.eraseFromParent();
3765 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3766 .addUse(ScaledInput)
3769 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3770 auto Zero =
B.buildFConstant(Ty, 0.0);
3772 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3773 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3775 MI.eraseFromParent();
3781 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3782 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3787 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3788 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3793 unsigned Flags =
MI.getFlags();
3803 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3805 B.buildFPTrunc(Dst, LogVal, Flags);
3810 MI.eraseFromParent();
3819 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3822 if (ST.hasFastFMAF32()) {
3824 const float c_log10 = 0x1.344134p-2f;
3825 const float cc_log10 = 0x1.09f79ep-26f;
3828 const float c_log = 0x1.62e42ep-1f;
3829 const float cc_log = 0x1.efa39ep-25f;
3831 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3832 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3836 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3837 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3838 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3839 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3840 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3843 const float ch_log10 = 0x1.344000p-2f;
3844 const float ct_log10 = 0x1.3509f6p-18f;
3847 const float ch_log = 0x1.62e000p-1f;
3848 const float ct_log = 0x1.0bfbe8p-15f;
3850 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3851 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3854 auto YInt =
B.buildBitcast(I32,
Y);
3855 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3856 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3857 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3861 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3864 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3866 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3869 const bool IsFiniteOnly =
3872 if (!IsFiniteOnly) {
3875 auto Fabs =
B.buildFAbs(Ty,
Y);
3878 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3882 auto Zero =
B.buildFConstant(Ty, 0.0);
3884 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3885 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3886 B.buildFSub(Dst, R, Shift, Flags);
3888 B.buildCopy(Dst, R);
3891 MI.eraseFromParent();
3897 unsigned Flags)
const {
3898 const double Log2BaseInverted =
3901 LLT Ty =
B.getMRI()->getType(Dst);
3906 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3907 .addUse(ScaledInput)
3909 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3910 auto Zero =
B.buildFConstant(Ty, 0.0);
3912 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3913 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3915 if (ST.hasFastFMAF32())
3916 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3918 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3919 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3926 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3927 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3930 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3931 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3942 unsigned Flags =
MI.getFlags();
3943 LLT Ty =
B.getMRI()->getType(Dst);
3950 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3951 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3952 .addUse(Ext.getReg(0))
3954 B.buildFPTrunc(Dst,
Log2, Flags);
3955 MI.eraseFromParent();
3965 MI.eraseFromParent();
3973 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3975 RangeCheckConst, Flags);
3977 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3978 auto Zero =
B.buildFConstant(Ty, 0.0);
3979 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3980 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3982 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3983 .addUse(AddInput.getReg(0))
3986 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3987 auto One =
B.buildFConstant(Ty, 1.0);
3988 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3989 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3990 MI.eraseFromParent();
3995 const SrcOp &Src,
unsigned Flags) {
3996 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3999 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
4000 .addUse(Src.getReg())
4003 return B.buildFExp2(Dst, Src, Flags);
4009 bool IsExp10)
const {
4010 LLT Ty =
B.getMRI()->getType(
X);
4014 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
4015 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4022 LLT Ty =
B.getMRI()->getType(Dst);
4028 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4031 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4032 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4033 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4036 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4038 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4039 .addUse(ExpInput.getReg(0))
4042 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4043 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4044 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4050 unsigned Flags)
const {
4051 LLT Ty =
B.getMRI()->getType(Dst);
4055 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4056 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4058 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4059 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4060 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4061 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4062 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4072 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4076 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4077 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4078 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4080 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4081 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4083 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4084 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4085 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4086 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4088 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4089 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4090 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4092 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4110 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4112 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4114 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4116 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4117 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4118 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4119 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4121 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4122 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4123 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4124 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4126 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4127 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4128 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4129 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4130 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4132 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4133 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4134 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4135 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4138 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4139 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4140 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4142 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4143 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4144 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4145 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4146 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4150 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4151 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4153 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4155 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4157 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4159 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4161 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4162 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4163 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4164 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4166 auto One =
B.buildFConstant(
F64, 1.0);
4167 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4168 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4171 auto DnInt =
B.buildFPTOSI(I32, Dn);
4172 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4179 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4186 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4188 MI.eraseFromParent();
4196 const unsigned Flags =
MI.getFlags();
4204 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4212 MI.eraseFromParent();
4223 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4226 B.buildFPTrunc(Dst, Lowered, Flags);
4227 MI.eraseFromParent();
4238 MI.eraseFromParent();
4266 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4269 if (ST.hasFastFMAF32()) {
4271 const float cc_exp = 0x1.4ae0bep-26f;
4272 const float c_exp10 = 0x1.a934f0p+1f;
4273 const float cc_exp10 = 0x1.2f346ep-24f;
4275 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4276 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4277 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4278 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4280 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4281 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4283 const float ch_exp = 0x1.714000p+0f;
4284 const float cl_exp = 0x1.47652ap-12f;
4286 const float ch_exp10 = 0x1.a92000p+1f;
4287 const float cl_exp10 = 0x1.4f0978p-11f;
4290 auto XInt =
B.buildBitcast(I32,
X);
4291 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4292 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4293 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4295 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4296 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4298 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4299 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4302 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4303 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4306 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4309 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4310 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4312 auto IntE =
B.buildFPTOSI(I32, E);
4314 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4315 .addUse(
A.getReg(0))
4317 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4319 auto UnderflowCheckConst =
4320 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4321 auto Zero =
B.buildFConstant(Ty, 0.0);
4325 R =
B.buildSelect(Ty, Underflow, Zero, R);
4328 auto OverflowCheckConst =
4329 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4334 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4337 B.buildCopy(Dst, R);
4338 MI.eraseFromParent();
4349 unsigned Flags =
MI.getFlags();
4358 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4360 .setMIFlags(CoreFlags);
4361 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4363 .addUse(Log.getReg(0))
4364 .setMIFlags(CoreFlags);
4366 MI.eraseFromParent();
4370 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4371 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4372 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4374 .addUse(Log.getReg(0))
4375 .setMIFlags(CoreFlags);
4380 .signBitIsZeroOrNaN()) {
4381 B.buildFExp2(Dst,
Mul, CoreFlags);
4382 MI.eraseFromParent();
4388 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4390 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4391 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4392 auto YIsOdd =
B.buildAnd(
4396 auto Neg =
B.buildFCopysign(
F32, R,
X);
4398 B.buildSelect(Dst, YIsOdd, Neg, R);
4399 MI.eraseFromParent();
4402 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4409 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4411 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4413 B.buildSelect(Dst, NegNonInt, NaN, R);
4415 MI.eraseFromParent();
4423 ModSrc = SrcFNeg->getOperand(1).getReg();
4425 ModSrc = SrcFAbs->getOperand(1).getReg();
4427 ModSrc = SrcFAbs->getOperand(1).getReg();
4437 Register OrigSrc =
MI.getOperand(1).getReg();
4438 unsigned Flags =
MI.getFlags();
4440 "this should not have been custom lowered");
4450 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4470 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4472 B.buildFMinNum(Min, Fract, Const, Flags);
4477 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4480 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4481 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4483 MI.eraseFromParent();
4501 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4503 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4504 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4507 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4508 B.buildBitcast(Dst,
Merge);
4510 MI.eraseFromParent();
4527 bool UsePartialMad64_32,
4528 bool SeparateOddAlignedProducts)
const {
4543 auto getZero32 = [&]() ->
Register {
4545 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4548 auto getZero64 = [&]() ->
Register {
4550 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4555 for (
unsigned i = 0; i < Src0.size(); ++i) {
4566 if (CarryIn.empty())
4569 bool HaveCarryOut =
true;
4571 if (CarryIn.size() == 1) {
4573 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4577 CarryAccum = getZero32();
4579 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4580 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4582 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4587 LocalAccum = getZero32();
4588 HaveCarryOut =
false;
4593 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4594 LocalAccum =
Add.getReg(0);
4608 auto buildMadChain =
4611 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4612 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4619 if (LocalAccum.size() == 1 &&
4620 (!UsePartialMad64_32 || !CarryIn.empty())) {
4623 unsigned j1 = DstIndex - j0;
4624 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4628 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4630 LocalAccum[0] =
Mul.getReg(0);
4632 if (CarryIn.empty()) {
4633 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4636 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4642 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4646 if (j0 <= DstIndex) {
4647 bool HaveSmallAccum =
false;
4650 if (LocalAccum[0]) {
4651 if (LocalAccum.size() == 1) {
4652 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4653 HaveSmallAccum =
true;
4654 }
else if (LocalAccum[1]) {
4655 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4656 HaveSmallAccum =
false;
4658 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4659 HaveSmallAccum =
true;
4662 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4664 HaveSmallAccum =
true;
4668 unsigned j1 = DstIndex - j0;
4669 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4673 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4674 {Src0[j0], Src1[j1], Tmp});
4675 Tmp = Mad.getReg(0);
4676 if (!HaveSmallAccum)
4677 CarryOut.push_back(Mad.getReg(1));
4678 HaveSmallAccum =
false;
4681 }
while (j0 <= DstIndex);
4683 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4684 LocalAccum[0] = Unmerge.getReg(0);
4685 if (LocalAccum.size() > 1)
4686 LocalAccum[1] = Unmerge.getReg(1);
4693 LocalAccum[0] = getZero32();
4697 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4698 "Uninitialized accumulator part");
4724 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4725 Carry OddCarryIn = std::move(OddCarry);
4726 Carry EvenCarryIn = std::move(EvenCarry);
4731 if (2 * i < Accum.
size()) {
4732 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4733 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4738 if (!SeparateOddAlignedProducts) {
4739 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4740 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4742 bool IsHighest = 2 * i >= Accum.
size();
4745 .take_front(IsHighest ? 1 : 2);
4746 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4752 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4754 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4756 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4759 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4762 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4763 Lo->getOperand(1).getReg());
4764 Accum[2 * i] =
Hi.getReg(0);
4765 SeparateOddCarry =
Hi.getReg(1);
4772 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4773 EvenCarryIn.push_back(CarryOut);
4775 if (2 * i < Accum.
size()) {
4776 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4777 OddCarry.push_back(CarryOut);
4789 assert(ST.hasMad64_32());
4790 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4802 unsigned Size = Ty.getSizeInBits();
4803 if (ST.useVMulU64Inst() &&
Size == 64)
4806 unsigned NumParts =
Size / 32;
4818 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4822 for (
unsigned i = 0; i < NumParts; ++i) {
4826 B.buildUnmerge(Src0Parts, Src0);
4827 B.buildUnmerge(Src1Parts, Src1);
4830 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4831 SeparateOddAlignedProducts);
4833 B.buildMergeLikeInstr(DstReg, AccumRegs);
4834 MI.eraseFromParent();
4849 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4850 ? AMDGPU::G_AMDGPU_FFBH_U32
4851 : AMDGPU::G_AMDGPU_FFBL_B32;
4852 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4855 MI.eraseFromParent();
4865 TypeSize NumBits = SrcTy.getSizeInBits();
4870 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4871 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4872 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4873 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4874 B.buildTrunc(Dst, Ctlz);
4875 MI.eraseFromParent();
4886 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4887 unsigned BitWidth = SrcTy.getSizeInBits();
4889 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4890 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4891 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4892 MI.eraseFromParent();
4898 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4901 return ConstVal == -1;
4908 Register CondDef =
MI.getOperand(0).getReg();
4927 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4936 UncondBrTarget = &*NextMBB;
4938 if (
Next->getOpcode() != AMDGPU::G_BR)
4957 *ArgRC,
B.getDebugLoc(), ArgTy);
4961 const unsigned Mask = Arg->
getMask();
4969 auto ShiftAmt =
B.buildConstant(I32, Shift);
4970 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4973 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4975 B.buildCopy(DstReg, LiveIn);
4985 if (!ST.hasClusters()) {
4988 MI.eraseFromParent();
5008 auto One =
B.buildConstant(I32, 1);
5009 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
5010 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
5011 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
5018 B.buildCopy(DstReg, GlobalIdXYZ);
5019 MI.eraseFromParent();
5023 B.buildCopy(DstReg, ClusterIdXYZ);
5024 MI.eraseFromParent();
5029 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5031 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5032 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5034 .addImm(ClusterIdField);
5035 auto Zero =
B.buildConstant(I32, 0);
5038 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5039 MI.eraseFromParent();
5081 auto LoadConstant = [&](
unsigned N) {
5082 B.buildConstant(DstReg,
N);
5086 if (ST.hasArchitectedSGPRs() &&
5093 Arg = &WorkGroupIDX;
5094 ArgRC = &AMDGPU::SReg_32RegClass;
5098 Arg = &WorkGroupIDY;
5099 ArgRC = &AMDGPU::SReg_32RegClass;
5103 Arg = &WorkGroupIDZ;
5104 ArgRC = &AMDGPU::SReg_32RegClass;
5108 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5109 return LoadConstant(0);
5110 Arg = &ClusterWorkGroupIDX;
5111 ArgRC = &AMDGPU::SReg_32RegClass;
5115 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5116 return LoadConstant(0);
5117 Arg = &ClusterWorkGroupIDY;
5118 ArgRC = &AMDGPU::SReg_32RegClass;
5122 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5123 return LoadConstant(0);
5124 Arg = &ClusterWorkGroupIDZ;
5125 ArgRC = &AMDGPU::SReg_32RegClass;
5130 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5131 Arg = &ClusterWorkGroupMaxIDX;
5132 ArgRC = &AMDGPU::SReg_32RegClass;
5137 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5138 Arg = &ClusterWorkGroupMaxIDY;
5139 ArgRC = &AMDGPU::SReg_32RegClass;
5144 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5145 Arg = &ClusterWorkGroupMaxIDZ;
5146 ArgRC = &AMDGPU::SReg_32RegClass;
5150 Arg = &ClusterWorkGroupMaxFlatID;
5151 ArgRC = &AMDGPU::SReg_32RegClass;
5166 return LoadConstant(0);
5171 B.buildUndef(DstReg);
5175 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5187 MI.eraseFromParent();
5193 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5194 MI.eraseFromParent();
5201 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5215 B.buildUndef(DstReg);
5216 MI.eraseFromParent();
5220 if (Arg->isMasked()) {
5234 MI.eraseFromParent();
5249 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5258 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5266 Align Alignment)
const {
5270 "unexpected kernarg parameter type");
5277 MI.eraseFromParent();
5309 auto FloatY =
B.buildUITOFP(
F32,
Y);
5310 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5312 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5313 auto Z =
B.buildFPTOUI(I32, ScaledY);
5316 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5317 auto NegYZ =
B.buildMul(I32, NegY, Z);
5318 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5321 auto Q =
B.buildUMulH(I32,
X, Z);
5322 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5325 auto One =
B.buildConstant(I32, 1);
5328 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5329 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5334 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5337 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5356 auto Unmerge =
B.buildUnmerge(I32, Val);
5358 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5359 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5361 auto Mad =
B.buildFMAD(
5365 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5366 auto Mul1 =
B.buildFMul(
5370 auto Mul2 =
B.buildFMul(
5372 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5375 auto Mad2 =
B.buildFMAD(
5379 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5380 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5382 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5397 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5399 auto Zero64 =
B.buildConstant(I64, 0);
5400 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5402 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5403 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5405 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5406 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5407 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5409 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5410 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5411 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5413 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5414 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5415 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5416 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5417 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5419 auto Zero32 =
B.buildConstant(I32, 0);
5420 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5421 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5422 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5424 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5425 Register NumerLo = UnmergeNumer.getReg(0);
5426 Register NumerHi = UnmergeNumer.getReg(1);
5428 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5429 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5430 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5431 Register Mul3_Lo = UnmergeMul3.getReg(0);
5432 Register Mul3_Hi = UnmergeMul3.getReg(1);
5433 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5434 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5435 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5436 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5438 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5439 Register DenomLo = UnmergeDenom.getReg(0);
5440 Register DenomHi = UnmergeDenom.getReg(1);
5443 auto C1 =
B.buildSExt(I32, CmpHi);
5446 auto C2 =
B.buildSExt(I32, CmpLo);
5449 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5456 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5457 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5458 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5459 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5461 auto One64 =
B.buildConstant(I64, 1);
5462 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5468 auto C6 =
B.buildSelect(
5472 auto Add4 =
B.buildAdd(I64, Add3, One64);
5473 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5475 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5476 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5477 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5483 auto Sel1 =
B.buildSelect(
5490 auto Sel2 =
B.buildSelect(
5501 switch (
MI.getOpcode()) {
5504 case AMDGPU::G_UDIV: {
5505 DstDivReg =
MI.getOperand(0).getReg();
5508 case AMDGPU::G_UREM: {
5509 DstRemReg =
MI.getOperand(0).getReg();
5512 case AMDGPU::G_UDIVREM: {
5513 DstDivReg =
MI.getOperand(0).getReg();
5514 DstRemReg =
MI.getOperand(1).getReg();
5521 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5522 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5523 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5533 MI.eraseFromParent();
5544 if (Ty != I32 && Ty != I64)
5547 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5548 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5549 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5551 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5552 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5553 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5555 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5556 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5558 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5559 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5561 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5562 switch (
MI.getOpcode()) {
5565 case AMDGPU::G_SDIV: {
5566 DstDivReg =
MI.getOperand(0).getReg();
5570 case AMDGPU::G_SREM: {
5571 DstRemReg =
MI.getOperand(0).getReg();
5575 case AMDGPU::G_SDIVREM: {
5576 DstDivReg =
MI.getOperand(0).getReg();
5577 DstRemReg =
MI.getOperand(1).getReg();
5590 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5591 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5592 B.buildSub(DstDivReg, SignXor, Sign);
5596 auto Sign = LHSign.getReg(0);
5597 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5598 B.buildSub(DstRemReg, SignXor, Sign);
5601 MI.eraseFromParent();
5611 uint16_t Flags =
MI.getFlags();
5617 if (!AllowInaccurateRcp && ResTy !=
F16)
5628 if (CLHS->isOne()) {
5629 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5633 MI.eraseFromParent();
5638 if (CLHS->isMinusOne()) {
5639 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5640 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5641 .addUse(FNeg.getReg(0))
5644 MI.eraseFromParent();
5651 if (!AllowInaccurateRcp &&
5656 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5659 B.buildFMul(Res, LHS, RCP, Flags);
5661 MI.eraseFromParent();
5671 uint16_t Flags =
MI.getFlags();
5676 if (!AllowInaccurateRcp)
5684 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5686 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5687 auto One =
B.buildFConstant(ResTy, 1.0);
5689 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5693 R =
B.buildFNeg(ResTy, R);
5695 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5696 R =
B.buildFMA(ResTy, Tmp0, R, R);
5698 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5699 R =
B.buildFMA(ResTy, Tmp1, R, R);
5702 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5703 B.buildCopy(Res, R);
5704 MI.eraseFromParent();
5708 auto Ret =
B.buildFMul(ResTy,
X, R);
5709 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5711 B.buildFMA(Res, Tmp2, R, Ret);
5712 MI.eraseFromParent();
5726 uint16_t Flags =
MI.getFlags();
5743 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5744 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5745 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5746 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5747 .addUse(RHSExt.getReg(0))
5749 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5751 if (ST.hasMadMacF32Insts()) {
5752 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5753 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5754 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5756 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5757 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5758 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5760 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5761 auto TmpInt =
B.buildBitcast(I32, Tmp);
5762 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5763 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5764 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5765 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5766 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5767 .addUse(RDst.getReg(0))
5772 MI.eraseFromParent();
5785 unsigned SPDenormMode =
5788 if (ST.hasDenormModeInst()) {
5790 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5792 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5793 B.buildInstr(AMDGPU::S_DENORM_MODE)
5794 .addImm(NewDenormModeValue);
5797 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5798 .addImm(SPDenormMode)
5815 uint16_t Flags =
MI.getFlags();
5819 auto One =
B.buildFConstant(
F32, 1.0f);
5821 auto DenominatorScaled =
5822 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5827 auto NumeratorScaled =
5828 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5834 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5835 .addUse(DenominatorScaled.getReg(0))
5837 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5840 const bool HasDynamicDenormals =
5845 if (!PreservesDenormals) {
5846 if (HasDynamicDenormals) {
5848 B.buildInstr(AMDGPU::S_GETREG_B32)
5849 .addDef(SavedSPDenormMode)
5855 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5856 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5857 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5858 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5859 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5860 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5862 if (!PreservesDenormals) {
5863 if (HasDynamicDenormals) {
5864 assert(SavedSPDenormMode);
5865 B.buildInstr(AMDGPU::S_SETREG_B32)
5866 .addReg(SavedSPDenormMode)
5872 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5873 .addUse(Fma4.getReg(0))
5874 .addUse(Fma1.getReg(0))
5875 .addUse(Fma3.getReg(0))
5876 .addUse(NumeratorScaled.getReg(1))
5879 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5880 .addUse(Fmas.getReg(0))
5885 MI.eraseFromParent();
5899 uint16_t Flags =
MI.getFlags();
5903 auto One =
B.buildFConstant(
F64, 1.0);
5905 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5911 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5913 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5914 .addUse(DivScale0.getReg(0))
5917 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5918 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5919 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5921 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5927 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5928 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5929 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5932 if (!ST.hasUsableDivScaleConditionOutput()) {
5939 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5940 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5941 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5942 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5945 Scale1Unmerge.getReg(1));
5947 Scale0Unmerge.getReg(1));
5948 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5950 Scale = DivScale1.getReg(1);
5953 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5954 .addUse(Fma4.getReg(0))
5955 .addUse(Fma3.getReg(0))
5956 .addUse(
Mul.getReg(0))
5960 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5961 .addUse(Fmas.getReg(0))
5966 MI.eraseFromParent();
5976 uint16_t Flags =
MI.getFlags();
5981 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5984 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5988 if (ST.hasFractBug()) {
5989 auto Fabs =
B.buildFAbs(Ty, Val);
5993 auto Zero =
B.buildConstant(InstrExpTy, 0);
5994 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5995 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5998 B.buildCopy(Res0, Mant);
5999 B.buildSExtOrTrunc(Res1, Exp);
6001 MI.eraseFromParent();
6011 uint16_t Flags =
MI.getFlags();
6015 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
6018 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
6019 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
6020 auto C2 =
B.buildFConstant(
F32, 1.0f);
6023 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
6025 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6027 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6028 .addUse(Mul0.getReg(0))
6031 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6033 B.buildFMul(Res, Sel, Mul1, Flags);
6035 MI.eraseFromParent();
6044 unsigned Flags =
MI.getFlags();
6045 assert(!ST.has16BitInsts());
6046 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6047 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6048 .addUse(Ext.getReg(0))
6050 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6051 MI.eraseFromParent();
6061 const unsigned Flags =
MI.getFlags();
6069 MI.eraseFromParent();
6073 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6075 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6076 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6077 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6082 .addUse(SqrtX.getReg(0))
6085 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6086 auto NegOne =
B.buildConstant(I32, -1);
6087 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6089 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6090 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6092 auto PosOne =
B.buildConstant(I32, 1);
6093 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6095 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6096 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6098 auto Zero =
B.buildFConstant(
F32, 0.0f);
6102 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6106 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6109 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6110 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6112 auto Half =
B.buildFConstant(
F32, 0.5f);
6113 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6114 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6115 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6116 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6117 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6118 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6119 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6120 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6123 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6125 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6127 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6130 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6132 MI.eraseFromParent();
6166 unsigned Flags =
MI.getFlags();
6171 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6173 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6177 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6178 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6179 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6182 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6184 auto Half =
B.buildFConstant(
F64, 0.5);
6185 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6186 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6188 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6189 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6191 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6192 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6194 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6195 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6197 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6199 Register SqrtRet = SqrtS2.getReg(0);
6201 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6202 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6203 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6206 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6207 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6208 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6213 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6216 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6222 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6224 MI.eraseFromParent();
6255 auto Flags =
MI.getFlags();
6267 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6277 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6278 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6283 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6285 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6286 MI.eraseFromParent();
6298 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6299 IID == Intrinsic::amdgcn_permlanex16;
6300 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6301 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6302 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6303 IID == Intrinsic::amdgcn_permlane_up ||
6304 IID == Intrinsic::amdgcn_permlane_down ||
6305 IID == Intrinsic::amdgcn_permlane_xor;
6309 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6311 case Intrinsic::amdgcn_readfirstlane:
6312 case Intrinsic::amdgcn_permlane64:
6313 return LaneOp.getReg(0);
6314 case Intrinsic::amdgcn_readlane:
6315 case Intrinsic::amdgcn_set_inactive:
6316 case Intrinsic::amdgcn_set_inactive_chain_arg:
6317 return LaneOp.addUse(Src1).getReg(0);
6318 case Intrinsic::amdgcn_writelane:
6319 case Intrinsic::amdgcn_permlane_bcast:
6320 case Intrinsic::amdgcn_permlane_up:
6321 case Intrinsic::amdgcn_permlane_down:
6322 case Intrinsic::amdgcn_permlane_xor:
6323 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6324 case Intrinsic::amdgcn_permlane16:
6325 case Intrinsic::amdgcn_permlanex16: {
6327 int64_t Src4 =
MI.getOperand(6).getImm();
6328 int64_t Src5 =
MI.getOperand(7).getImm();
6329 return LaneOp.addUse(Src1)
6336 case Intrinsic::amdgcn_mov_dpp8:
6337 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6338 case Intrinsic::amdgcn_update_dpp:
6339 return LaneOp.addUse(Src1)
6340 .addImm(
MI.getOperand(4).getImm())
6341 .addImm(
MI.getOperand(5).getImm())
6342 .addImm(
MI.getOperand(6).getImm())
6343 .addImm(
MI.getOperand(7).getImm())
6353 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6354 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6355 IsPermlaneShuffle) {
6356 Src1 =
MI.getOperand(3).getReg();
6357 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6358 IsPermlaneShuffle) {
6359 Src2 =
MI.getOperand(4).getReg();
6364 unsigned Size = Ty.getSizeInBits();
6366 unsigned SplitSize = 32;
6367 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6368 ST.hasDPALU_DPP() &&
6372 if (
Size == SplitSize) {
6379 bool IsFloat = Ty.getScalarType().isFloat();
6383 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6385 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6387 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6391 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6393 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6394 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6396 if (IID == Intrinsic::amdgcn_writelane)
6397 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6399 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6401 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6403 B.buildTrunc(DstReg, LaneOpDst);
6404 MI.eraseFromParent();
6408 if (
Size % SplitSize != 0)
6412 bool NeedsBitcast =
false;
6413 if (IntTy.isVector()) {
6416 if (EltSize == SplitSize) {
6417 PartialResTy = EltTy;
6418 }
else if (EltSize == 16 || EltSize == 32) {
6419 unsigned NElem = SplitSize / EltSize;
6422 NeedsBitcast =
true;
6427 unsigned NumParts =
Size / SplitSize;
6431 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6432 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6434 if (IID == Intrinsic::amdgcn_writelane)
6435 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6437 for (
unsigned i = 0; i < NumParts; ++i) {
6438 Src0 = Src0Parts.
getReg(i);
6440 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6441 Src1 = Src1Parts.
getReg(i);
6443 if (IID == Intrinsic::amdgcn_writelane)
6444 Src2 = Src2Parts.
getReg(i);
6446 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6449 if (NeedsBitcast || IsFloat)
6452 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6454 B.buildMergeLikeInstr(DstReg, PartialRes);
6456 MI.eraseFromParent();
6464 ST.getTargetLowering()->getImplicitParameterOffset(
6474 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6475 B.buildConstant(IdxTy,
Offset).getReg(0));
6486 Register Pointer =
MI.getOperand(2).getReg();
6488 Register NumRecords =
MI.getOperand(4).getReg();
6494 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6496 auto ExtStride =
B.buildAnyExt(I32, Stride);
6498 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6499 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6501 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6503 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6507 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6508 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6509 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6510 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6514 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6515 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6516 auto ExtShiftedStride =
6517 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6518 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6519 auto ExtShiftedFlags =
6520 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6521 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6523 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6524 B.buildMergeValues(Result, {LowHalf, HighHalf});
6526 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6527 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6528 auto LowHalf = Unmerge.getReg(0);
6529 auto HighHalf = Unmerge.getReg(1);
6531 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6532 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6533 auto ShiftConst =
B.buildConstant(I32, 16);
6534 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6535 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6536 Register NewHighHalfReg = NewHighHalf.getReg(0);
6537 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6540 MI.eraseFromParent();
6557 MI.eraseFromParent();
6564 unsigned AddrSpace)
const {
6566 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6570 ST.hasGloballyAddressableScratch()) {
6572 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6573 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6575 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6577 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6579 B.buildConstant(I32, 1u << 26));
6584 MI.eraseFromParent();
6594std::pair<Register, unsigned>
6606 bool CheckNUW = ST.hasGFX1250Insts();
6608 MRI, OrigOffset,
nullptr, CheckNUW);
6612 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6622 unsigned Overflow = ImmOffset & ~MaxImm;
6623 ImmOffset -= Overflow;
6624 if ((int32_t)Overflow < 0) {
6625 Overflow += ImmOffset;
6629 if (Overflow != 0) {
6631 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6633 auto OverflowVal =
B.buildConstant(I32, Overflow);
6634 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6639 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6641 return std::pair(BaseReg, ImmOffset);
6648 bool ImageStore)
const {
6656 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6658 if (ST.hasUnpackedD16VMem()) {
6659 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6662 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6663 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6671 if (ImageStore && ST.hasImageStoreD16Bug()) {
6674 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6676 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6683 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6684 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6686 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6694 auto Unmerge =
B.buildUnmerge(I32, Reg);
6695 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6697 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6707 Reg =
B.buildPadVectorWithUndefElements(
6716 bool IsFormat)
const {
6726 VData =
B.buildBitcast(Ty, VData).getReg(0);
6728 if (Ty.isFloat(16)) {
6730 VData =
B.buildBitcast(Ty, VData).getReg(0);
6737 if (Ty.isVector()) {
6738 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6750 bool IsFormat)
const {
6757 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6764 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6765 const Function &Fn =
B.getMF().getFunction();
6767 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6768 MI.eraseFromParent();
6780 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6783 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6787 VIndex =
MI.getOperand(3).getReg();
6790 VIndex =
B.buildConstant(I32, 0).getReg(0);
6793 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6794 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6798 Format =
MI.getOperand(5 + OpOffset).getImm();
6802 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6808 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6809 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6810 }
else if (IsFormat) {
6811 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6812 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6816 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6819 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6822 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6827 auto MIB =
B.buildInstr(
Opc)
6838 MIB.addImm(AuxiliaryData)
6839 .addImm(HasVIndex ? -1 : 0)
6840 .addMemOperand(MMO);
6842 MI.eraseFromParent();
6848 unsigned ImmOffset,
unsigned Format,
6851 auto MIB =
B.buildInstr(
Opc)
6862 MIB.addImm(AuxiliaryData)
6863 .addImm(HasVIndex ? -1 : 0)
6864 .addMemOperand(MMO);
6870 Register SOffset,
unsigned ImmOffset,
6871 unsigned Format,
unsigned AuxiliaryData,
6875 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6877 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6880 B.buildUnmerge(Unmerge, LoadDstReg);
6886 bool IsTyped)
const {
6900 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6901 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6903 StatusDst =
MI.getOperand(1).getReg();
6908 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6911 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6914 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6917 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6920 VIndex =
B.buildConstant(I32, 0).getReg(0);
6923 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6924 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6928 Format =
MI.getOperand(5 + OpOffset).getImm();
6932 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6942 Dst =
MI.getOperand(0).getReg();
6943 B.setInsertPt(
B.getMBB(),
MI);
6950 Dst =
MI.getOperand(0).getReg();
6951 B.setInsertPt(
B.getMBB(),
MI);
6955 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6956 const bool Unpacked = ST.hasUnpackedD16VMem();
6958 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6959 const Function &Fn =
B.getMF().getFunction();
6961 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6964 B.buildUndef(StatusDst);
6965 MI.eraseFromParent();
6969 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6970 const Function &Fn =
B.getMF().getFunction();
6972 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6975 B.buildUndef(StatusDst);
6976 MI.eraseFromParent();
6988 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6989 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6990 }
else if (IsFormat) {
6992 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
6993 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6995 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6996 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
7001 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
7002 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7005 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7006 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7009 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7010 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7015 if (IsTFE && IsD16 && Ty.isVector()) {
7017 const unsigned NumElts = Ty.getNumElements();
7018 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7021 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7024 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7029 R =
B.buildTrunc(EltTy, R).getReg(0);
7030 B.buildMergeLikeInstr(Dst, ValueDWords);
7039 if (PackedTy == Ty) {
7040 B.buildBitcast(Dst, Merged);
7042 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7043 B.buildDeleteTrailingVectorElements(Dst, Packed);
7047 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7055 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7057 B.buildTrunc(DstInt, ExtDst);
7058 }
else if (NumValueDWords == 1) {
7060 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7064 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7067 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7068 IsTyped, HasVIndex,
B);
7069 B.buildMergeLikeInstr(DstInt, ValueDWords);
7072 B.buildBitcast(Dst, DstInt);
7074 (IsD16 && !Ty.isVector())) {
7075 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7077 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7078 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7079 B.buildTrunc(Dst, LoadDstReg);
7080 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7082 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7084 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7085 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7087 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7089 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7090 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7091 B.buildMergeLikeInstr(Dst, Repack);
7094 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7097 MI.eraseFromParent();
7103 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7104 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7105 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7106 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7107 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7108 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7109 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7110 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7111 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7112 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7113 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7114 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7115 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7116 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7117 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7118 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7119 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7120 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7121 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7122 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7123 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7124 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7125 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7126 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7127 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7128 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7129 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7130 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7131 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7132 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7133 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7135 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7136 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7137 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7138 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7139 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7140 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7141 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7142 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7143 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7144 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7145 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7146 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7147 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7148 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7150 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7151 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7152 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7153 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7154 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7155 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7156 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7157 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7158 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7159 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7160 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7162 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7163 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7164 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7165 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7166 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7167 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7168 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7169 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7170 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7172 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7173 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7174 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7175 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7176 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7177 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7178 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7179 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7180 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7181 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7182 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7183 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7185 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7186 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7187 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7188 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7189 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7190 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7191 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7192 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7201 const bool IsCmpSwap =
7202 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7203 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7204 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7205 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7216 CmpVal =
MI.getOperand(3).getReg();
7221 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7222 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7225 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7228 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7234 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7235 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7236 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7255 .addImm(AuxiliaryData)
7256 .addImm(HasVIndex ? -1 : 0)
7257 .addMemOperand(MMO);
7259 MI.eraseFromParent();
7269 bool IsA16,
bool IsG16) {
7283 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7288 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7292 "Bias needs to be converted to 16 bit in A16 mode");
7294 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7298 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7302 if (((
I + 1) >= EndIdx) ||
7309 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7311 B.buildBuildVector(V2EltTy,
7312 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7317 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7328 int DimIdx,
int NumVAddrs) {
7330 for (
int I = 0;
I != NumVAddrs; ++
I) {
7332 if (
SrcOp.isReg()) {
7335 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7336 if (
B.getMRI()->getType(
Reg) != I32)
7337 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7342 int NumAddrRegs = AddrRegs.
size();
7343 if (NumAddrRegs != 1) {
7344 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7347 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7350 for (
int I = 1;
I != NumVAddrs; ++
I) {
7353 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7375 const unsigned NumDefs =
MI.getNumExplicitDefs();
7376 const unsigned ArgOffset = NumDefs + 1;
7377 bool IsTFE = NumDefs == 2;
7395 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7399 const bool IsAtomicPacked16Bit =
7400 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7401 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7408 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7409 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7410 const bool DataTyIs16 =
7411 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7413 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7414 const bool IsA16 = AddrTyIs16;
7415 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7418 if (!BaseOpcode->
Atomic) {
7419 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7422 }
else if (DMask != 0) {
7424 }
else if (!IsTFE && !BaseOpcode->
Store) {
7426 B.buildUndef(
MI.getOperand(0));
7427 MI.eraseFromParent();
7435 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7436 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7437 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7438 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7439 unsigned NewOpcode = LoadOpcode;
7440 if (BaseOpcode->
Store)
7441 NewOpcode = StoreOpcode;
7443 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7446 MI.setDesc(
B.getTII().get(NewOpcode));
7450 if (IsTFE && DMask == 0) {
7453 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7456 if (BaseOpcode->
Atomic) {
7461 if (Ty.isVector() && !IsAtomicPacked16Bit)
7468 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7469 MI.getOperand(2).setReg(
Concat.getReg(0));
7470 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7474 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7477 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7483 if (IsA16 && !ST.hasA16()) {
7488 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7489 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7491 if (IsA16 || IsG16) {
7499 const bool UseNSA = ST.hasNSAEncoding() &&
7500 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7501 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7502 const bool UsePartialNSA =
7503 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7505 if (UsePartialNSA) {
7509 auto Concat =
B.buildConcatVectors(
7510 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7511 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7512 PackedRegs.
resize(NSAMaxSize);
7513 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7515 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7516 PackedRegs[0] =
Concat.getReg(0);
7520 const unsigned NumPacked = PackedRegs.
size();
7523 if (!
SrcOp.isReg()) {
7533 SrcOp.setReg(AMDGPU::NoRegister);
7550 const bool UseNSA = ST.hasNSAEncoding() &&
7551 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7552 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7553 const bool UsePartialNSA =
7554 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7556 if (UsePartialNSA) {
7558 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7560 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7575 if (!Ty.isVector() || !IsD16)
7579 if (RepackedReg != VData) {
7580 MI.getOperand(1).setReg(RepackedReg);
7588 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7591 if (NumElts < DMaskLanes)
7594 if (NumElts > 4 || DMaskLanes > 4)
7605 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7606 const LLT AdjustedTy =
7622 if (IsD16 && ST.hasUnpackedD16VMem()) {
7629 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7630 unsigned RoundedSize = 32 * RoundedElts;
7634 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7639 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7645 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7649 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7650 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7654 MI.getOperand(0).setReg(NewResultReg);
7662 Dst1Reg =
MI.getOperand(1).getReg();
7663 if (MRI->
getType(Dst1Reg) != I32)
7667 MI.removeOperand(1);
7670 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7671 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7672 B.buildBitcast(DstReg, Unmerge.getReg(0));
7673 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7682 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7684 if (ResultNumRegs == 1) {
7686 ResultRegs[0] = NewResultReg;
7689 for (
int I = 0;
I != NumDataRegs; ++
I)
7691 B.buildUnmerge(ResultRegs, NewResultReg);
7696 ResultRegs.
resize(NumDataRegs);
7701 if (IsD16 && !Ty.isVector()) {
7702 B.buildTrunc(DstReg, ResultRegs[0]);
7707 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7708 !ST.hasUnpackedD16VMem()) {
7709 B.buildBitcast(DstReg, ResultRegs[0]);
7721 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7723 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7724 }
else if (ST.hasUnpackedD16VMem()) {
7726 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7730 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7734 for (
int I = 0;
I != NumElts; ++
I)
7741 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7742 B.buildBuildVector(DstReg, ResultRegs);
7746 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7747 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7752 if (Ty == V3I16 || Ty == V3F16) {
7754 if (ResultRegs.
size() == 1) {
7755 NewResultReg = ResultRegs[0];
7756 }
else if (ResultRegs.
size() == 2) {
7758 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7773 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7775 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7777 if (ResizeDst != DstReg)
7778 B.buildBitcast(DstReg, ResizeDst);
7782 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7783 B.buildConcatVectors(DstReg, ResultRegs);
7792 Register OrigDst =
MI.getOperand(0).getReg();
7794 LLT Ty =
B.getMRI()->getType(OrigDst);
7795 unsigned Size = Ty.getSizeInBits();
7797 bool HasMMO = !
MI.memoperands_empty();
7802 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7803 if (
Size % 32 != 0 && !IsSubwordLoad) {
7806 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7807 B.buildUndef(OrigDst);
7808 MI.eraseFromParent();
7813 if (IsSubwordLoad) {
7815 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7816 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7819 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7821 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7830 B.setInsertPt(
B.getMBB(),
MI);
7835 B.setInsertPt(
B.getMBB(),
MI);
7838 MI.setDesc(
B.getTII().get(
Opc));
7839 MI.removeOperand(1);
7845 const unsigned MemSize = (
Size + 7) / 8;
7846 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7853 MI.addMemOperand(MF, MMO);
7855 if (Dst != OrigDst) {
7856 MI.getOperand(0).setReg(Dst);
7857 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7858 B.buildTrunc(OrigDst, Dst);
7880 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7881 MI.removeOperand(0);
7892 if (!ST.hasTrapHandler() ||
7896 return ST.supportsGetDoorbellID() ?
7911 MI.eraseFromParent();
7923 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7932 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7934 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7938 MI.eraseFromParent();
7947 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7954 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7974 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7977 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7978 B.buildCopy(SGPR01, Temp);
7979 B.buildInstr(AMDGPU::S_TRAP)
7982 MI.eraseFromParent();
7993 B.buildCopy(SGPR01, LiveIn);
7994 B.buildInstr(AMDGPU::S_TRAP)
7998 MI.eraseFromParent();
8007 if (ST.hasPrivEnabledTrap2NopBug()) {
8008 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
8010 MI.eraseFromParent();
8014 B.buildInstr(AMDGPU::S_TRAP)
8016 MI.eraseFromParent();
8025 if (!ST.hasTrapHandler() ||
8029 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8032 B.buildInstr(AMDGPU::S_TRAP)
8036 MI.eraseFromParent();
8050 Register NodePtr =
MI.getOperand(2).getReg();
8051 Register RayExtent =
MI.getOperand(3).getReg();
8052 Register RayOrigin =
MI.getOperand(4).getReg();
8054 Register RayInvDir =
MI.getOperand(6).getReg();
8057 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8064 const unsigned NumVDataDwords = 4;
8065 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8066 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8068 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8070 const unsigned BaseOpcodes[2][2] = {
8071 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8072 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8073 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8077 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8078 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8079 : AMDGPU::MIMGEncGfx10NSA,
8080 NumVDataDwords, NumVAddrDwords);
8084 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8085 : AMDGPU::MIMGEncGfx10Default,
8086 NumVDataDwords, NumVAddrDwords);
8091 if (UseNSA && IsGFX11Plus) {
8092 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8093 auto SrcInt =
B.buildBitcast(V3I32, Src);
8094 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8095 auto Merged =
B.buildMergeLikeInstr(
8096 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8097 Ops.push_back(Merged.getReg(0));
8100 Ops.push_back(NodePtr);
8101 Ops.push_back(RayExtent);
8102 packLanes(RayOrigin);
8105 auto UnmergeRayDir =
8106 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8107 auto UnmergeRayInvDir =
8108 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8109 auto MergedDir =
B.buildMergeLikeInstr(
8112 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8113 UnmergeRayDir.getReg(0)}))
8116 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8117 UnmergeRayDir.getReg(1)}))
8120 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8121 UnmergeRayDir.getReg(2)}))
8123 Ops.push_back(MergedDir.getReg(0));
8126 packLanes(RayInvDir);
8130 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8131 Ops.push_back(Unmerge.getReg(0));
8132 Ops.push_back(Unmerge.getReg(1));
8134 Ops.push_back(NodePtr);
8136 Ops.push_back(RayExtent);
8138 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8139 auto SrcInt =
B.buildBitcast(V3I32, Src);
8140 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8141 Ops.push_back(Unmerge.getReg(0));
8142 Ops.push_back(Unmerge.getReg(1));
8143 Ops.push_back(Unmerge.getReg(2));
8146 packLanes(RayOrigin);
8148 auto UnmergeRayDir =
8149 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8150 auto UnmergeRayInvDir =
8151 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8155 B.buildMergeLikeInstr(R1,
8156 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8157 B.buildMergeLikeInstr(
8158 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8159 B.buildMergeLikeInstr(
8160 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8166 packLanes(RayInvDir);
8175 Ops.push_back(MergedOps);
8178 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8187 .addImm(IsA16 ? 1 : 0)
8190 MI.eraseFromParent();
8200 Register DstOrigin =
MI.getOperand(1).getReg();
8202 Register NodePtr =
MI.getOperand(4).getReg();
8203 Register RayExtent =
MI.getOperand(5).getReg();
8204 Register InstanceMask =
MI.getOperand(6).getReg();
8205 Register RayOrigin =
MI.getOperand(7).getReg();
8207 Register Offsets =
MI.getOperand(9).getReg();
8208 Register TDescr =
MI.getOperand(10).getReg();
8211 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8212 const unsigned NumVDataDwords = 10;
8213 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8215 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8216 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8217 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8220 auto RayExtentInstanceMaskVec =
8221 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8222 B.buildAnyExt(I32, InstanceMask)});
8224 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8225 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8231 .addUse(RayExtentInstanceMaskVec.getReg(0))
8238 MI.eraseFromParent();
8247 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8248 MI.eraseFromParent();
8255 if (!ST.hasArchitectedSGPRs())
8259 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8260 auto LSB =
B.buildConstant(I32, 25);
8261 auto Width =
B.buildConstant(I32, 5);
8262 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8263 MI.eraseFromParent();
8271 unsigned Width)
const {
8275 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8276 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8279 B.buildCopy(DstReg, Result);
8280 MI.eraseFromParent();
8300 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8304 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8307 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8308 MI.eraseFromParent();
8321 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8325 .addReg(Unmerge.getReg(0));
8329 .addReg(Unmerge.getReg(1));
8330 MI.eraseFromParent();
8342 case Intrinsic::sponentry:
8348 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8351 B.buildIntToPtr(DstReg, TmpReg);
8352 MI.eraseFromParent();
8354 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8356 B.buildFrameIndex(
MI.getOperand(0), FI);
8357 MI.eraseFromParent();
8360 case Intrinsic::amdgcn_if:
8361 case Intrinsic::amdgcn_else: {
8364 bool Negated =
false;
8381 std::swap(CondBrTarget, UncondBrTarget);
8383 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8384 B.buildCopy(NewUse,
Use);
8385 if (IntrID == Intrinsic::amdgcn_if) {
8386 B.buildInstr(AMDGPU::SI_IF)
8389 .addMBB(UncondBrTarget)
8392 B.buildInstr(AMDGPU::SI_ELSE)
8395 .addMBB(UncondBrTarget)
8405 B.buildBr(*CondBrTarget);
8408 MI.eraseFromParent();
8409 BrCond->eraseFromParent();
8420 case Intrinsic::amdgcn_loop: {
8423 bool Negated =
false;
8432 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8435 std::swap(CondBrTarget, UncondBrTarget);
8437 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8438 B.buildCopy(NewReg, Reg);
8439 B.buildInstr(AMDGPU::SI_LOOP)
8441 .addMBB(UncondBrTarget)
8447 B.buildBr(*CondBrTarget);
8449 MI.eraseFromParent();
8450 BrCond->eraseFromParent();
8456 case Intrinsic::amdgcn_wave_reduce_min:
8457 case Intrinsic::amdgcn_wave_reduce_umin:
8458 case Intrinsic::amdgcn_wave_reduce_fmin:
8459 case Intrinsic::amdgcn_wave_reduce_max:
8460 case Intrinsic::amdgcn_wave_reduce_umax:
8461 case Intrinsic::amdgcn_wave_reduce_fmax:
8462 case Intrinsic::amdgcn_wave_reduce_add:
8463 case Intrinsic::amdgcn_wave_reduce_fadd:
8464 case Intrinsic::amdgcn_wave_reduce_sub:
8465 case Intrinsic::amdgcn_wave_reduce_fsub:
8466 case Intrinsic::amdgcn_wave_reduce_and:
8467 case Intrinsic::amdgcn_wave_reduce_or:
8468 case Intrinsic::amdgcn_wave_reduce_xor: {
8473 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8474 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8475 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8476 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8477 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8478 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8479 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8480 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8481 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8488 .addUse(Ext.getReg(0))
8489 .addImm(
MI.getOperand(3).getImm());
8491 B.buildFPTrunc(DstReg, NewDst);
8493 B.buildTrunc(DstReg, NewDst);
8494 MI.eraseFromParent();
8497 case Intrinsic::amdgcn_make_buffer_rsrc:
8499 case Intrinsic::amdgcn_kernarg_segment_ptr:
8502 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8503 MI.eraseFromParent();
8509 case Intrinsic::amdgcn_implicitarg_ptr:
8511 case Intrinsic::amdgcn_workitem_id_x:
8514 case Intrinsic::amdgcn_workitem_id_y:
8517 case Intrinsic::amdgcn_workitem_id_z:
8520 case Intrinsic::amdgcn_workgroup_id_x:
8525 case Intrinsic::amdgcn_workgroup_id_y:
8530 case Intrinsic::amdgcn_workgroup_id_z:
8535 case Intrinsic::amdgcn_cluster_id_x:
8536 return ST.hasClusters() &&
8539 case Intrinsic::amdgcn_cluster_id_y:
8540 return ST.hasClusters() &&
8543 case Intrinsic::amdgcn_cluster_id_z:
8544 return ST.hasClusters() &&
8547 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8548 return ST.hasClusters() &&
8551 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8552 return ST.hasClusters() &&
8555 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8556 return ST.hasClusters() &&
8559 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8560 return ST.hasClusters() &&
8562 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8563 return ST.hasClusters() &&
8566 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8567 return ST.hasClusters() &&
8570 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8571 return ST.hasClusters() &&
8574 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8575 return ST.hasClusters() &&
8579 case Intrinsic::amdgcn_wave_id:
8581 case Intrinsic::amdgcn_lds_kernel_id:
8584 case Intrinsic::amdgcn_dispatch_ptr:
8587 case Intrinsic::amdgcn_queue_ptr:
8590 case Intrinsic::amdgcn_implicit_buffer_ptr:
8593 case Intrinsic::amdgcn_dispatch_id:
8596 case Intrinsic::r600_read_ngroups_x:
8600 case Intrinsic::r600_read_ngroups_y:
8603 case Intrinsic::r600_read_ngroups_z:
8606 case Intrinsic::r600_read_local_size_x:
8609 case Intrinsic::r600_read_local_size_y:
8613 case Intrinsic::r600_read_local_size_z:
8616 case Intrinsic::amdgcn_fdiv_fast:
8618 case Intrinsic::amdgcn_is_shared:
8620 case Intrinsic::amdgcn_is_private:
8622 case Intrinsic::amdgcn_wavefrontsize: {
8623 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8624 MI.eraseFromParent();
8627 case Intrinsic::amdgcn_s_buffer_load:
8628 case Intrinsic::amdgcn_ptr_s_buffer_load:
8630 case Intrinsic::amdgcn_raw_buffer_store:
8631 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8632 case Intrinsic::amdgcn_struct_buffer_store:
8633 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8635 case Intrinsic::amdgcn_raw_buffer_store_format:
8636 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8637 case Intrinsic::amdgcn_struct_buffer_store_format:
8638 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8640 case Intrinsic::amdgcn_raw_tbuffer_store:
8641 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8642 case Intrinsic::amdgcn_struct_tbuffer_store:
8643 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8645 case Intrinsic::amdgcn_raw_buffer_load:
8646 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8647 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8648 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8649 case Intrinsic::amdgcn_struct_buffer_load:
8650 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8651 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8652 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8654 case Intrinsic::amdgcn_raw_buffer_load_format:
8655 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8656 case Intrinsic::amdgcn_struct_buffer_load_format:
8657 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8659 case Intrinsic::amdgcn_raw_tbuffer_load:
8660 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8661 case Intrinsic::amdgcn_struct_tbuffer_load:
8662 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8664 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8665 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8666 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8667 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8668 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8669 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8670 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8671 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8672 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8673 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8674 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8675 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8676 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8677 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8678 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8679 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8680 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8681 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8682 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8683 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8684 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8685 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8686 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8687 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8688 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8689 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8690 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8691 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8692 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8693 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8694 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8695 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8696 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8697 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8698 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8699 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8700 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8701 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8702 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8703 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8704 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8705 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8706 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8707 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8708 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8709 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8710 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8711 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8712 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8713 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8714 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8715 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8716 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8717 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8718 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8719 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8720 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8721 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8722 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8723 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8724 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8725 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8726 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8727 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8728 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8729 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8730 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8731 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8732 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8733 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8734 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8735 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8737 case Intrinsic::amdgcn_rsq_clamp:
8739 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8741 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8742 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8744 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8745 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8746 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8747 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8748 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8749 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8750 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8751 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8755 if (IndexArgTy != I64) {
8756 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8757 :
B.buildAnyExt(I64, Index);
8758 MI.getOperand(5).setReg(NewIndex.getReg(0));
8762 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8763 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8764 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8765 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8766 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8767 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8768 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8769 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8772 if (MRI.
getType(Index) != I32)
8773 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8776 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8777 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8778 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8779 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8780 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8781 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8782 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8783 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8784 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8786 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8790 if (IndexArgTy != IdxTy) {
8791 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8792 :
B.buildAnyExt(IdxTy, Index);
8793 MI.getOperand(7).setReg(NewIndex.getReg(0));
8798 case Intrinsic::amdgcn_fmed3: {
8804 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8805 MI.removeOperand(1);
8809 case Intrinsic::amdgcn_readlane:
8810 case Intrinsic::amdgcn_writelane:
8811 case Intrinsic::amdgcn_readfirstlane:
8812 case Intrinsic::amdgcn_permlane16:
8813 case Intrinsic::amdgcn_permlanex16:
8814 case Intrinsic::amdgcn_permlane64:
8815 case Intrinsic::amdgcn_set_inactive:
8816 case Intrinsic::amdgcn_set_inactive_chain_arg:
8817 case Intrinsic::amdgcn_mov_dpp8:
8818 case Intrinsic::amdgcn_update_dpp:
8819 case Intrinsic::amdgcn_permlane_bcast:
8820 case Intrinsic::amdgcn_permlane_up:
8821 case Intrinsic::amdgcn_permlane_down:
8822 case Intrinsic::amdgcn_permlane_xor:
8824 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8826 case Intrinsic::amdgcn_dead: {
8830 MI.eraseFromParent();
8833 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8834 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8835 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8836 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8837 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8838 MI.eraseFromParent();
8840 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8841 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8842 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8843 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8844 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8845 MI.eraseFromParent();
8847 case Intrinsic::amdgcn_av_load_b128:
8848 case Intrinsic::amdgcn_av_store_b128: {
8849 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8850 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8851 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8853 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8854 **
MI.memoperands_begin());
8855 MI.eraseFromParent();
8858 case Intrinsic::amdgcn_flat_load_monitor_b32:
8859 case Intrinsic::amdgcn_flat_load_monitor_b64:
8860 case Intrinsic::amdgcn_flat_load_monitor_b128:
8861 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8862 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8863 .add(
MI.getOperand(0))
8864 .add(
MI.getOperand(2))
8865 .addMemOperand(*
MI.memoperands_begin());
8866 MI.eraseFromParent();
8868 case Intrinsic::amdgcn_global_load_monitor_b32:
8869 case Intrinsic::amdgcn_global_load_monitor_b64:
8870 case Intrinsic::amdgcn_global_load_monitor_b128:
8871 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8872 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8873 .add(
MI.getOperand(0))
8874 .add(
MI.getOperand(2))
8875 .addMemOperand(*
MI.memoperands_begin());
8876 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static void buildTFEBufferLoad(unsigned Opc, ArrayRef< Register > ValueDsts, Register StatusDst, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define FP_DENORM_FLUSH_NONE
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarFor(std::initializer_list< LLT > Types, LegalizeMutation Mutation)
Widen the scalar, specified in mutation, when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a larger total bit size than second type index.
LLVM_ABI LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy)
True if the type index is a vector with element type EltTy.
LLVM_ABI LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the specified type indices are both the same bit size.
LLVM_ABI LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or vector with an element type that's narrower than the...
LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type)
True iff the given type index is not the specified type.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as TypeIdx, but take the number of elements from FromTypeIdx.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
Invariant opcodes: All instruction sets have these as their low opcodes.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
@ Load
The value being inserted comes from a load (InsertElement only).
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.