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});
1039 MinNumMaxNumIeee.
legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F32, F64});
1040 MinNumMaxNum.
legalFor(ST.hasIEEEMinimumMaximumInsts(), {F32, F64})
1043 if (ST.has16BitInsts()) {
1044 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {F16});
1045 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {F16})
1050 if (ST.hasVOP3PInsts()) {
1051 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1054 .clampMaxNumElements(0,
F16, 2);
1055 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F16})
1059 .clampMaxNumElements(0,
F16, 2);
1063 if (ST.hasAnyPackedFP64Ops()) {
1064 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2F64})
1068 .clampMaxNumElements(0,
F64, 2);
1072 if (ST.hasBF16PackedInsts()) {
1073 MinNumMaxNumIeee.legalFor(!ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1074 .clampMaxNumElementsStrict(0,
BF16, 2);
1076 MinNumMaxNum.legalFor(ST.hasIEEEMinimumMaximumInsts(), {V2BF16})
1079 .clampMaxNumElementsStrict(0,
BF16, 2);
1087 if (!ST.has16BitInsts()) {
1088 MinNumMaxNumIeee.minScalar(0,
F32);
1089 MinNumMaxNum.minScalar(0,
F32);
1092 if (ST.hasVOP3PInsts()) {
1093 FPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1094 FCanonicalizeActions.clampMaxNumElementsStrict(0,
F16, 2);
1095 StrictFPOpActions.clampMaxNumElementsStrict(0,
F16, 2);
1103 if (!ST.has16BitInsts()) {
1114 .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
1117 if (ST.hasAnyPackedFP32Ops())
1121 if (ST.has16BitInsts()) {
1124 .legalFor(ST.hasBF16TransInsts(), {BF16})
1134 .legalFor({{
F32, I32}, {
F64, I32}, {
F16, I16}})
1156 if (ST.hasFractBug()) {
1170 .legalFor({{
F32, I32}, {
F64, I32}})
1190 if (ST.hasCvtPkF16F32Inst()) {
1192 .clampMaxNumElements(0,
F16, 2);
1205 if (ST.has16BitInsts()) {
1219 if (ST.hasBF16PackedInsts()) {
1222 .clampMaxNumElementsStrict(0,
BF16, 2);
1227 if (ST.hasAnyPackedFP32Ops())
1235 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1236 FMad.customFor({
F32,
F16});
1237 else if (ST.hasMadMacF32Insts())
1238 FMad.customFor({
F32});
1239 else if (ST.hasMadF16())
1240 FMad.customFor({
F16});
1245 if (ST.has16BitInsts()) {
1248 FRem.minScalar(0,
F32).customFor({
F32,
F64});
1256 .clampMaxNumElements(0,
S16, 2)
1272 .legalFor({{
F32, I32}, {
F64, I32}})
1276 if (ST.has16BitInsts())
1284 .legalFor({{I32,
F32}, {I32,
F64}})
1285 .customFor({{I64,
F32}, {I64,
F64}})
1288 .widenScalarFor({{I16,
BF16}, {I32,
BF16}, {I64,
BF16}},
1290 if (ST.has16BitInsts())
1299 .legalFor({{I32,
F32}, {I32,
F64}, {I16,
F32}})
1300 .legalFor(ST.has16BitInsts(), {{I16, F16}})
1301 .legalFor(ST.hasVCvtPkIU16F32(), {{V2I16, V2F32}})
1305 if (
ST.has16BitInsts())
1308 if (
ST.hasVCvtPkIU16F32())
1318 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1319 .clampScalar(0, I16, I64)
1323 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1329 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1333 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1334 .clampScalar(0, I16, I64)
1338 auto &RoundingActions = getActionDefinitionsBuilder(
1339 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN});
1340 if (
ST.has16BitInsts())
1348 if (!
ST.has16BitInsts())
1351 getActionDefinitionsBuilder(G_PTR_ADD)
1357 getActionDefinitionsBuilder(G_PTRMASK)
1359 .scalarSameSizeAs(1, 0)
1363 getActionDefinitionsBuilder(G_ICMP)
1375 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1376 .legalForCartesianProduct(
1377 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1378 if (
ST.has16BitInsts()) {
1379 CmpBuilder.legalFor({{
S1,
S16}});
1388 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
1391 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct(
1392 {
I1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1394 if (
ST.hasSALUFloatInsts())
1395 FCmpBuilder.legalForCartesianProduct({
I32}, {
F16,
F32});
1398 .widenScalarToNextPow2(1)
1402 getActionDefinitionsBuilder(G_FPOW)
1404 .clampScalar(0,
F32,
F32)
1407 getActionDefinitionsBuilder(G_FPOWI).clampScalar(0,
F32,
F32).lower();
1409 getActionDefinitionsBuilder(G_FLOG2)
1410 .legalFor(
ST.has16BitInsts(), {F16})
1411 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1417 getActionDefinitionsBuilder(G_FEXP2)
1418 .legalFor(
ST.has16BitInsts(), {F16})
1419 .legalFor(
ST.hasBF16TransInsts(), {BF16})
1425 getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
1429 getActionDefinitionsBuilder({G_FEXP, G_FEXP10})
1434 getActionDefinitionsBuilder(G_CTPOP)
1436 .clampScalar(0,
S32,
S32)
1437 .widenScalarToNextPow2(1, 32)
1438 .clampScalar(1,
S32,
S64)
1440 .widenScalarToNextPow2(0, 32);
1443 if (
ST.has16BitInsts())
1444 getActionDefinitionsBuilder(G_IS_FPCLASS)
1445 .legalForCartesianProduct({
I1}, FPTypes16)
1446 .widenScalarToNextPow2(1)
1450 getActionDefinitionsBuilder(G_IS_FPCLASS)
1451 .legalForCartesianProduct({
I1}, FPTypesBase)
1452 .lowerFor({
I1,
F16})
1453 .widenScalarToNextPow2(1)
1460 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1462 .clampScalar(0,
S32,
S32)
1463 .clampScalar(1,
S32,
S64)
1464 .widenScalarToNextPow2(0, 32)
1465 .widenScalarToNextPow2(1, 32)
1469 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1472 .clampScalar(0,
S32,
S32)
1473 .clampScalar(1,
S32,
S64)
1475 .widenScalarToNextPow2(0, 32)
1476 .widenScalarToNextPow2(1, 32);
1478 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1480 .clampScalar(0,
S32,
S32)
1481 .clampScalar(1,
S32,
S64)
1483 .widenScalarToNextPow2(0, 32)
1484 .widenScalarToNextPow2(1, 32);
1486 getActionDefinitionsBuilder(G_CTLS)
1489 .clampScalar(0,
S32,
S32)
1490 .clampScalar(1,
S32,
S32);
1494 getActionDefinitionsBuilder(G_BITREVERSE)
1496 .clampScalar(0,
S32,
S64)
1498 .widenScalarToNextPow2(0);
1500 if (
ST.has16BitInsts()) {
1501 getActionDefinitionsBuilder(G_BSWAP)
1503 .clampMaxNumElementsStrict(0,
S16, 2)
1506 .widenScalarToNextPow2(0)
1507 .clampScalar(0,
S16,
S32)
1510 if (
ST.hasVOP3PInsts()) {
1511 getActionDefinitionsBuilder(G_ABS)
1513 .clampMaxNumElements(0,
S16, 2)
1515 .widenScalarToNextPow2(0)
1518 if (
ST.useMinMaxI64Insts()) {
1519 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1521 .clampMaxNumElements(0,
S16, 2)
1523 .widenScalarToNextPow2(0)
1527 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1529 .clampMaxNumElements(0,
S16, 2)
1531 .widenScalarToNextPow2(0)
1536 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1538 .widenScalarToNextPow2(0)
1545 getActionDefinitionsBuilder(G_BSWAP)
1550 .widenScalarToNextPow2(0)
1555 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1558 .widenScalarToNextPow2(0)
1563 getActionDefinitionsBuilder(G_INTTOPTR)
1565 .legalForCartesianProduct(AddrSpaces64, {
S64})
1566 .legalForCartesianProduct(AddrSpaces32, {
S32})
1579 getActionDefinitionsBuilder(G_PTRTOINT)
1581 .legalForCartesianProduct(AddrSpaces64, {
S64})
1582 .legalForCartesianProduct(AddrSpaces32, {
S32})
1595 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1599 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1600 bool IsLoad) ->
bool {
1604 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1617 !
ST.hasUsableDSOffset() && Query.
MMODescrs[0].AlignInBits == 32)
1622 unsigned NumRegs = (MemSize + 31) / 32;
1624 if (!
ST.hasDwordx3LoadStores())
1635 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1636 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1637 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1638 unsigned LocalAlign64 =
ST.hasUsableDSOffset() ? 32 : 64;
1644 for (
unsigned Op : {G_LOAD, G_STORE}) {
1645 const bool IsStore =
Op == G_STORE;
1647 auto &Actions = getActionDefinitionsBuilder(
Op);
1650 Actions.legalForTypesWithMemDesc(
1651 {{
S32, GlobalPtr,
S32, GlobalAlign32},
1654 {
S64, GlobalPtr,
S64, GlobalAlign32},
1657 {
S32, GlobalPtr,
S8, GlobalAlign8},
1658 {
S32, GlobalPtr,
S16, GlobalAlign16},
1660 {
S32, LocalPtr,
S32, 32},
1661 {
S64, LocalPtr,
S64, LocalAlign64},
1663 {
S32, LocalPtr,
S8, 8},
1664 {
S32, LocalPtr,
S16, 16},
1667 {
S32, PrivatePtr,
S32, 32},
1668 {
S32, PrivatePtr,
S8, 8},
1669 {
S32, PrivatePtr,
S16, 16},
1672 {
S32, ConstantPtr,
S32, GlobalAlign32},
1675 {
S64, ConstantPtr,
S64, GlobalAlign32}});
1677 if (IsStore ||
ST.d16PreservesUnusedBits()) {
1678 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1679 {{S16, GlobalPtr, S8, GlobalAlign8},
1680 {S16, GlobalPtr, S16, GlobalAlign16},
1681 {S16, LocalPtr, S8, 8},
1682 {S16, LocalPtr, S16, 16},
1683 {S16, PrivatePtr, S8, 8},
1684 {S16, PrivatePtr, S16, 16}});
1695 Actions.unsupportedIf(
1696 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1710 Actions.customIf(
typeIs(1, Constant32Ptr));
1736 return !Query.
Types[0].isVector() &&
1737 needToSplitMemOp(Query,
Op == G_LOAD);
1739 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1744 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1747 if (DstSize > MemSize)
1753 if (MemSize > MaxSize)
1761 return Query.
Types[0].isVector() &&
1762 needToSplitMemOp(Query,
Op == G_LOAD);
1764 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1778 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1779 if (MemSize > MaxSize) {
1783 if (MaxSize % EltSize == 0) {
1789 unsigned NumPieces = MemSize / MaxSize;
1793 if (NumPieces == 1 || NumPieces >= NumElts ||
1794 NumElts % NumPieces != 0)
1795 return std::pair(0, EltTy);
1803 return std::pair(0, EltTy);
1818 return std::pair(0, EltTy);
1823 .widenScalarToNextPow2(0)
1830 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1831 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1832 {
S32, GlobalPtr,
S16, 2 * 8},
1833 {
S32, LocalPtr,
S8, 8},
1834 {
S32, LocalPtr,
S16, 16},
1835 {
S32, PrivatePtr,
S8, 8},
1836 {
S32, PrivatePtr,
S16, 16},
1837 {
S32, ConstantPtr,
S8, 8},
1838 {
S32, ConstantPtr,
S16, 2 * 8}})
1839 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1840 {{S16, GlobalPtr, S8, GlobalAlign8},
1841 {S16, LocalPtr, S8, GlobalAlign8},
1842 {S16, PrivatePtr, S8, GlobalAlign8},
1843 {S16, ConstantPtr, S8, GlobalAlign8}})
1848 if (
ST.hasFlatAddressSpace()) {
1849 ExtLoads.legalForTypesWithMemDesc(
1850 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1852 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1853 {{S16, FlatPtr, S8, GlobalAlign8}});
1861 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1863 ExtLoads.narrowScalarIf(
1870 ExtLoads.clampScalar(0,
S32,
S32)
1871 .widenScalarToNextPow2(0)
1874 auto &Atomics = getActionDefinitionsBuilder(
1875 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1876 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1877 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1878 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1879 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1880 {
S64, GlobalPtr}, {
S64, LocalPtr},
1881 {
S32, RegionPtr}, {
S64, RegionPtr}});
1882 if (
ST.hasFlatAddressSpace()) {
1883 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1887 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1888 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1889 if (
ST.hasFlatAddressSpace()) {
1890 Atomics32.legalFor({{
S32, FlatPtr}});
1894 auto &
Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1895 if (
ST.hasLDSFPAtomicAddF32()) {
1897 if (
ST.hasLdsAtomicAddF64())
1899 if (
ST.hasAtomicDsPkAdd16Insts())
1902 if (
ST.hasAtomicFaddInsts())
1904 if (
ST.hasFlatAtomicFaddF32Inst())
1907 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1911 Atomic.legalFor({{
F32, GlobalPtr}, {
F64, GlobalPtr}, {
F64, FlatPtr}});
1914 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1915 ST.hasAtomicBufferGlobalPkAddF16Insts())
1917 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1919 if (
ST.hasAtomicFlatPkAdd16Insts())
1925 auto &AtomicFMinFMax =
1926 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1927 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1929 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1930 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1931 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1932 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1933 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1934 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1935 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1936 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1940 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1941 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1942 {
S32, FlatPtr}, {
S64, FlatPtr}})
1943 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1944 {
S32, RegionPtr}, {
S64, RegionPtr}});
1948 getActionDefinitionsBuilder(G_SELECT)
1950 LocalPtr, FlatPtr, PrivatePtr,
1954 .clampScalar(0,
S16,
S64)
1958 .clampMaxNumElements(0,
S32, 2)
1959 .clampMaxNumElements(0, LocalPtr, 2)
1960 .clampMaxNumElements(0, PrivatePtr, 2)
1962 .widenScalarToNextPow2(0)
1967 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1969 if (
ST.has16BitInsts()) {
1970 if (
ST.hasVOP3PInsts()) {
1972 .clampMaxNumElements(0,
S16, 2);
1974 Shifts.legalFor({{
S16,
S16}});
1977 Shifts.widenScalarIf(
1982 const LLT AmountTy = Query.
Types[1];
1988 Shifts.clampScalar(1,
S32,
S32);
1989 Shifts.widenScalarToNextPow2(0, 16);
1990 Shifts.clampScalar(0,
S16,
S64);
1992 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2000 Shifts.clampScalar(1,
S32,
S32);
2001 Shifts.widenScalarToNextPow2(0, 32);
2002 Shifts.clampScalar(0,
S32,
S64);
2004 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
2009 Shifts.scalarize(0);
2011 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
2012 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
2013 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
2014 unsigned IdxTypeIdx = 2;
2016 getActionDefinitionsBuilder(
Op)
2018 const LLT EltTy = Query.
Types[EltTypeIdx];
2019 const LLT VecTy = Query.
Types[VecTypeIdx];
2020 const LLT IdxTy = Query.
Types[IdxTypeIdx];
2022 const bool isLegalVecType =
2032 return (EltSize == 32 || EltSize == 64) &&
2048 const LLT EltTy = Query.
Types[EltTypeIdx];
2049 const LLT VecTy = Query.
Types[VecTypeIdx];
2053 const unsigned TargetEltSize =
2054 DstEltSize % 64 == 0 ? 64 : 32;
2055 return std::pair(VecTypeIdx,
2059 .clampScalar(EltTypeIdx,
S32,
S64)
2060 .clampScalar(VecTypeIdx,
S32,
S64)
2061 .clampScalar(IdxTypeIdx,
S32,
S32)
2062 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2071 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2073 const LLT &EltTy = Query.
Types[1].getElementType();
2074 return Query.
Types[0] != EltTy;
2077 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2078 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2079 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2080 getActionDefinitionsBuilder(
Op)
2083 const LLT BigTy = Query.
Types[BigTyIdx];
2089 const LLT LitTy = Query.
Types[LitTyIdx];
2094 .widenScalarToNextPow2(BigTyIdx, 32)
2102 const LLT BigTy = Query.
Types[BigTyIdx];
2103 const LLT LitTy = Query.
Types[LitTyIdx];
2111 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2121 if (
ST.hasScalarPackInsts()) {
2124 .minScalarOrElt(0,
S16)
2127 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2131 BuildVector.customFor({
V2S16,
S16});
2132 BuildVector.minScalarOrElt(0,
S32);
2134 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2142 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2144 .clampMaxNumElements(0,
S32, 32)
2145 .clampMaxNumElements(1,
S16, 2)
2146 .clampMaxNumElements(0,
S16, 64);
2148 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2151 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2152 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2153 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2155 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2156 const LLT Ty = Query.
Types[TypeIdx];
2168 getActionDefinitionsBuilder(
Op)
2172 const LLT BigTy = Query.
Types[BigTyIdx];
2178 .widenScalarToNextPow2(LitTyIdx, 16)
2187 .clampScalar(LitTyIdx,
S32,
S512)
2188 .widenScalarToNextPow2(LitTyIdx, 32)
2192 return notValidElt(Query, LitTyIdx);
2197 return notValidElt(Query, BigTyIdx);
2202 if (
Op == G_MERGE_VALUES) {
2203 Builder.widenScalarIf(
2206 const LLT Ty = Query.
Types[LitTyIdx];
2212 Builder.widenScalarIf(
2214 const LLT Ty = Query.
Types[BigTyIdx];
2220 const LLT &Ty = Query.
Types[BigTyIdx];
2222 if (NewSizeInBits >= 256) {
2224 if (RoundedTo < NewSizeInBits)
2225 NewSizeInBits = RoundedTo;
2227 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2236 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2237 .legalFor({{
S32}, {
S64}})
2238 .clampScalar(0,
S32,
S64);
2240 if (
ST.hasVOP3PInsts()) {
2241 SextInReg.lowerFor({{
V2S16}})
2245 .clampMaxNumElementsStrict(0,
S16, 2);
2246 }
else if (
ST.has16BitInsts()) {
2247 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2251 SextInReg.lowerFor({{
S32}, {
S64}});
2256 .clampScalar(0,
S32,
S64)
2259 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2263 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2264 FSHRActionDefs.legalFor({{
S32,
S32}})
2265 .clampMaxNumElementsStrict(0,
S16, 2);
2266 if (
ST.hasVOP3PInsts())
2268 FSHRActionDefs.scalarize(0).lower();
2270 if (
ST.hasVOP3PInsts()) {
2271 getActionDefinitionsBuilder(G_FSHL)
2273 .clampMaxNumElementsStrict(0,
S16, 2)
2277 getActionDefinitionsBuilder(G_FSHL)
2282 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2285 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2287 getActionDefinitionsBuilder(G_FENCE)
2290 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2295 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2297 .clampScalar(1,
S32,
S32)
2298 .clampScalar(0,
S32,
S64)
2299 .widenScalarToNextPow2(0)
2302 getActionDefinitionsBuilder(
2306 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2312 if (
ST.hasIEEEMinimumMaximumInsts()) {
2313 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2314 .legalFor(FPTypesPK16)
2315 .clampMaxNumElements(0,
F16, 2)
2317 }
else if (
ST.hasVOP3PInsts()) {
2318 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2320 .clampMaxNumElementsStrict(0,
F16, 2)
2324 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2326 .clampScalar(0,
F32,
F64)
2330 getActionDefinitionsBuilder(
2331 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2334 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2336 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2337 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2338 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2341 getActionDefinitionsBuilder(G_PREFETCH)
2342 .customFor({Constant32Ptr})
2345 getActionDefinitionsBuilder(
2346 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2347 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FADD, G_VECREDUCE_FMUL,
2348 G_VECREDUCE_FMIN, G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM,
2349 G_VECREDUCE_FMAXIMUM, G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2354 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2355 G_INTRINSIC_CONVERGENT,
2356 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2368 switch (
MI.getOpcode()) {
2369 case TargetOpcode::G_ADDRSPACE_CAST:
2371 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2373 case TargetOpcode::G_FCEIL:
2375 case TargetOpcode::G_FREM:
2377 case TargetOpcode::G_INTRINSIC_TRUNC:
2379 case TargetOpcode::G_SITOFP:
2381 case TargetOpcode::G_UITOFP:
2383 case TargetOpcode::G_FPTOSI:
2385 case TargetOpcode::G_FPTOUI:
2387 case TargetOpcode::G_FMINNUM:
2388 case TargetOpcode::G_FMAXNUM:
2389 case TargetOpcode::G_FMINIMUMNUM:
2390 case TargetOpcode::G_FMAXIMUMNUM:
2392 case TargetOpcode::G_EXTRACT:
2394 case TargetOpcode::G_INSERT:
2396 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2398 case TargetOpcode::G_INSERT_VECTOR_ELT:
2400 case TargetOpcode::G_FSIN:
2401 case TargetOpcode::G_FCOS:
2403 case TargetOpcode::G_GLOBAL_VALUE:
2405 case TargetOpcode::G_LOAD:
2406 case TargetOpcode::G_SEXTLOAD:
2407 case TargetOpcode::G_ZEXTLOAD:
2408 case TargetOpcode::G_PREFETCH:
2410 case TargetOpcode::G_STORE:
2412 case TargetOpcode::G_FMAD:
2414 case TargetOpcode::G_FDIV:
2416 case TargetOpcode::G_FFREXP:
2418 case TargetOpcode::G_FSQRT:
2420 case TargetOpcode::G_UDIV:
2421 case TargetOpcode::G_UREM:
2422 case TargetOpcode::G_UDIVREM:
2424 case TargetOpcode::G_SDIV:
2425 case TargetOpcode::G_SREM:
2426 case TargetOpcode::G_SDIVREM:
2428 case TargetOpcode::G_ATOMIC_CMPXCHG:
2430 case TargetOpcode::G_FLOG2:
2432 case TargetOpcode::G_FLOG:
2433 case TargetOpcode::G_FLOG10:
2435 case TargetOpcode::G_FEXP2:
2437 case TargetOpcode::G_FEXP:
2438 case TargetOpcode::G_FEXP10:
2440 case TargetOpcode::G_FPOW:
2442 case TargetOpcode::G_FFLOOR:
2444 case TargetOpcode::G_BUILD_VECTOR:
2445 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2447 case TargetOpcode::G_MUL:
2449 case TargetOpcode::G_CTLZ:
2450 case TargetOpcode::G_CTTZ:
2452 case TargetOpcode::G_CTLS:
2454 case TargetOpcode::G_CTLZ_ZERO_POISON:
2456 case TargetOpcode::G_STACKSAVE:
2458 case TargetOpcode::G_GET_FPENV:
2460 case TargetOpcode::G_SET_FPENV:
2462 case TargetOpcode::G_TRAP:
2464 case TargetOpcode::G_DEBUGTRAP:
2476 unsigned BaseAS = AS;
2481 Register Aperture = getBaseSegmentAperture(BaseAS, MRI,
B);
2485 auto Tag =
B.buildConstant(
S32, SANum);
2486 return B.buildOr(
S32, Aperture,
Tag).getReg(0);
2492Register AMDGPULegalizerInfo::getBaseSegmentAperture(
2502 if (ST.hasApertureRegs()) {
2506 const unsigned ApertureRegNo =
2507 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
2508 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2509 !ST.hasGloballyAddressableScratch()) &&
2510 "Cannot use src_private_base with globally addressable scratch!");
2513 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2514 return B.buildUnmerge(I32, Dst).getReg(1);
2529 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2545 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2548 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2562 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
2570 B.buildObjectPtrOffset(
2573 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2581 switch (Def->getOpcode()) {
2582 case AMDGPU::G_FRAME_INDEX:
2583 case AMDGPU::G_GLOBAL_VALUE:
2584 case AMDGPU::G_BLOCK_ADDR:
2586 case AMDGPU::G_CONSTANT: {
2587 const ConstantInt *CI = Def->getOperand(1).getCImm();
2602 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST);
2611 unsigned SrcAS = SrcTy.getAddressSpace();
2625 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2632 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2634 ST.hasGloballyAddressableScratch()) {
2637 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2639 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2640 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2642 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2643 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2644 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2647 return B.buildExtract(Dst, Src, 0).getReg(0);
2651 castFlatToLocalOrPrivate(Dst);
2652 MI.eraseFromParent();
2658 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2659 auto FlatNull =
B.buildConstant(SrcTy, 0);
2662 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2666 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2668 MI.eraseFromParent();
2675 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2678 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2681 ST.hasGloballyAddressableScratch()) {
2685 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2686 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2690 if (ST.isWave64()) {
2691 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2697 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2698 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2700 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2704 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2705 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2707 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2708 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2717 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2721 castLocalOrPrivateToFlat(Dst);
2722 MI.eraseFromParent();
2726 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2733 SegmentNull.getReg(0));
2735 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2737 MI.eraseFromParent();
2742 SrcTy.getSizeInBits() == 64) {
2744 B.buildExtract(Dst, Src, 0);
2745 MI.eraseFromParent();
2752 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2753 auto PtrLo =
B.buildPtrToInt(I32, Src);
2754 if (AddrHiVal == 0) {
2755 auto Zext =
B.buildZExt(I64, PtrLo);
2756 B.buildIntToPtr(Dst, Zext);
2758 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2759 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2762 MI.eraseFromParent();
2769 MI.eraseFromParent();
2778 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2783 auto C1 =
B.buildFConstant(Ty, C1Val);
2784 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2787 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2788 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2790 auto C2 =
B.buildFConstant(Ty, C2Val);
2791 auto Fabs =
B.buildFAbs(Ty, Src);
2794 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2795 MI.eraseFromParent();
2812 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2814 const auto Zero =
B.buildFConstant(
F64, 0.0);
2815 const auto One =
B.buildFConstant(
F64, 1.0);
2818 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2819 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2822 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2823 MI.eraseFromParent();
2831 Register Src0Reg =
MI.getOperand(1).getReg();
2832 Register Src1Reg =
MI.getOperand(2).getReg();
2833 auto Flags =
MI.getFlags();
2836 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2837 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2838 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2839 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2840 MI.eraseFromParent();
2846 const unsigned FractBits = 52;
2847 const unsigned ExpBits = 11;
2850 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2851 auto Const1 =
B.buildConstant(I32, ExpBits);
2853 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2855 .addUse(Const0.getReg(0))
2856 .addUse(Const1.getReg(0));
2858 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2871 auto SrcInt =
B.buildBitcast(I64, Src);
2874 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2881 const unsigned FractBits = 52;
2884 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2885 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2887 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2889 const auto Zero32 =
B.buildConstant(I32, 0);
2892 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2894 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2895 auto Not =
B.buildNot(I64, Shr);
2896 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2897 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2902 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2903 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2904 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2905 MI.eraseFromParent();
2921 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2922 auto ThirtyTwo =
B.buildConstant(I32, 32);
2925 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2926 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2928 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2929 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2932 B.buildFAdd(Dst, LdExp, CvtLo);
2933 MI.eraseFromParent();
2939 auto One =
B.buildConstant(I32, 1);
2943 auto ThirtyOne =
B.buildConstant(I32, 31);
2944 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2945 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2946 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2947 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2948 .addUse(Unmerge.getReg(1));
2949 auto LS2 =
B.buildSub(I32, LS, One);
2950 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2952 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2953 auto Norm =
B.buildShl(I64, Src, ShAmt);
2954 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2955 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2956 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2957 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2958 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2959 B.buildFLdexp(Dst, FVal, Scale);
2960 MI.eraseFromParent();
2980 unsigned Flags =
MI.getFlags();
2991 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2999 auto SrcInt =
B.buildBitcast(I32, Src);
3000 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
3001 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
3005 K0 =
B.buildFConstant(
3007 K1 =
B.buildFConstant(
3010 K0 =
B.buildFConstant(
3012 K1 =
B.buildFConstant(
3016 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
3017 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
3018 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
3020 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
3021 :
B.buildFPTOUI(I32, FloorMul);
3022 auto Lo =
B.buildFPTOUI(I32, Fma);
3026 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
3028 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
3031 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
3032 MI.eraseFromParent();
3055 uint64_t
Offset =
MI.getOperand(2).getImm();
3064 unsigned StartIdx =
Offset / 32;
3068 if (DstCount == 1) {
3070 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3078 for (
unsigned I = 0;
I < DstCount; ++
I)
3079 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3080 B.buildMergeLikeInstr(DstReg, MergeVec);
3083 MI.eraseFromParent();
3093 Register InsertSrc =
MI.getOperand(2).getReg();
3094 uint64_t
Offset =
MI.getOperand(3).getImm();
3102 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3106 unsigned DstCount = DstSize / 32;
3107 unsigned InsertCount = InsertSize / 32;
3108 unsigned StartIdx =
Offset / 32;
3110 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3113 for (
unsigned I = 0;
I < StartIdx; ++
I)
3116 if (InsertCount == 1) {
3120 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3123 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3124 for (
unsigned I = 0;
I < InsertCount; ++
I)
3128 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3131 B.buildMergeLikeInstr(DstReg, MergeVec);
3133 MI.eraseFromParent();
3160 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3161 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3162 B.buildIntToPtr(Dst, IntElt);
3164 MI.eraseFromParent();
3171 std::optional<ValueAndVReg> MaybeIdxVal =
3175 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3178 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3179 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3184 MI.eraseFromParent();
3213 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3214 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3215 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3217 B.buildIntToPtr(Dst, IntVecDest);
3218 MI.eraseFromParent();
3225 std::optional<ValueAndVReg> MaybeIdxVal =
3230 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3233 if (IdxVal < NumElts) {
3235 for (
unsigned i = 0; i < NumElts; ++i)
3237 B.buildUnmerge(SrcRegs, Vec);
3239 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3240 B.buildMergeLikeInstr(Dst, SrcRegs);
3245 MI.eraseFromParent();
3256 unsigned Flags =
MI.getFlags();
3260 if (ST.hasTrigReducedRange()) {
3261 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3262 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3263 .addUse(MulVal.getReg(0))
3267 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3270 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3274 MI.eraseFromParent();
3282 unsigned GAFlags)
const {
3315 if (ST.has64BitLiterals()) {
3319 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3323 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3334 B.buildExtract(DstReg, PCReg, 0);
3336 B.buildCopy(DstReg, PCReg);
3346 if (RequiresHighHalf && ST.has64BitLiterals()) {
3349 B.buildInstr(AMDGPU::S_MOV_B64)
3352 B.buildCopy(DstReg, Addr);
3360 B.buildInstr(AMDGPU::S_MOV_B32)
3365 if (RequiresHighHalf) {
3367 "Must provide a 64-bit pointer type!");
3372 B.buildInstr(AMDGPU::S_MOV_B32)
3379 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3380 B.buildCast(DstReg, AddrDst);
3382 B.buildCast(DstReg, AddrLo);
3391 unsigned AS = Ty.getAddressSpace();
3402 Fn,
"unsupported use of BARRIER address space",
MI.getDebugLoc(),
3404 B.buildUndef(DstReg);
3405 MI.eraseFromParent();
3409 B.buildConstant(DstReg,
3411 MI.eraseFromParent();
3417 GV->
getName() !=
"llvm.amdgcn.module.lds") {
3420 Fn,
"local memory global used by non-kernel function",
3429 B.buildUndef(DstReg);
3430 MI.eraseFromParent();
3454 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3455 B.buildIntToPtr(DstReg, Sz);
3456 MI.eraseFromParent();
3462 MI.eraseFromParent();
3466 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3468 MI.eraseFromParent();
3476 MI.eraseFromParent();
3482 MI.eraseFromParent();
3498 if (Ty.getSizeInBits() == 32) {
3500 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3501 B.buildExtract(DstReg,
Load, 0);
3503 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3505 MI.eraseFromParent();
3522 unsigned PtrIdx =
MI.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3523 Register PtrReg =
MI.getOperand(PtrIdx).getReg();
3529 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3531 MI.getOperand(PtrIdx).setReg(Cast.getReg(0));
3536 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3554 const uint64_t AlignInBits = 8 * MemAlign.
value();
3562 if (WideMemSize == ValSize) {
3568 MI.setMemRefs(MF, {WideMMO});
3574 if (ValSize > WideMemSize)
3581 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3582 B.buildTrunc(ValReg, WideLoad).getReg(0);
3589 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3590 B.buildExtract(ValReg, WideLoad, 0);
3594 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3595 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3599 MI.eraseFromParent();
3612 Register DataReg =
MI.getOperand(0).getReg();
3657 "this should not have been custom lowered");
3662 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3664 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3668 .setMemRefs(
MI.memoperands());
3670 MI.eraseFromParent();
3678 switch (
DefMI->getOpcode()) {
3679 case TargetOpcode::G_INTRINSIC: {
3681 case Intrinsic::amdgcn_frexp_mant:
3682 case Intrinsic::amdgcn_log:
3683 case Intrinsic::amdgcn_log_clamp:
3684 case Intrinsic::amdgcn_exp2:
3685 case Intrinsic::amdgcn_sqrt:
3693 case TargetOpcode::G_FSQRT:
3695 case TargetOpcode::G_FFREXP: {
3696 if (
DefMI->getOperand(0).getReg() == Src)
3700 case TargetOpcode::G_FPEXT: {
3721std::pair<Register, Register>
3723 unsigned Flags)
const {
3727 auto SmallestNormal =
B.buildFConstant(
3729 auto IsLtSmallestNormal =
3732 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3733 auto One =
B.buildFConstant(
F32, 1.0);
3735 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3736 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3738 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3751 LLT Ty =
B.getMRI()->getType(Dst);
3752 unsigned Flags =
MI.getFlags();
3756 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3757 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3758 .addUse(Ext.getReg(0))
3760 B.buildFPTrunc(Dst,
Log2, Flags);
3761 MI.eraseFromParent();
3769 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3772 MI.eraseFromParent();
3776 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3777 .addUse(ScaledInput)
3780 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3781 auto Zero =
B.buildFConstant(Ty, 0.0);
3783 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3784 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3786 MI.eraseFromParent();
3792 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3793 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3798 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3799 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3804 unsigned Flags =
MI.getFlags();
3814 auto PromoteSrc =
B.buildFPExt(
F32,
X, Flags);
3816 B.buildFPTrunc(Dst, LogVal, Flags);
3821 MI.eraseFromParent();
3830 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3833 if (ST.hasFastFMAF32()) {
3835 const float c_log10 = 0x1.344134p-2f;
3836 const float cc_log10 = 0x1.09f79ep-26f;
3839 const float c_log = 0x1.62e42ep-1f;
3840 const float cc_log = 0x1.efa39ep-25f;
3842 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3843 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3847 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3848 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3849 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3850 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3851 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3854 const float ch_log10 = 0x1.344000p-2f;
3855 const float ct_log10 = 0x1.3509f6p-18f;
3858 const float ch_log = 0x1.62e000p-1f;
3859 const float ct_log = 0x1.0bfbe8p-15f;
3861 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3862 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3865 auto YInt =
B.buildBitcast(I32,
Y);
3866 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
3867 auto YH =
B.buildBitcast(Ty,
B.buildAnd(I32, YInt, MaskConst));
3868 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3872 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3875 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3877 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3880 const bool IsFiniteOnly =
3883 if (!IsFiniteOnly) {
3886 auto Fabs =
B.buildFAbs(Ty,
Y);
3889 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3893 auto Zero =
B.buildFConstant(Ty, 0.0);
3895 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3896 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3897 B.buildFSub(Dst, R, Shift, Flags);
3899 B.buildCopy(Dst, R);
3902 MI.eraseFromParent();
3908 unsigned Flags)
const {
3909 const double Log2BaseInverted =
3912 LLT Ty =
B.getMRI()->getType(Dst);
3917 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3918 .addUse(ScaledInput)
3920 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3921 auto Zero =
B.buildFConstant(Ty, 0.0);
3923 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3924 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3926 if (ST.hasFastFMAF32())
3927 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3929 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3930 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3937 auto Log2Operand = Ty ==
F16 ?
B.buildFLog2(Ty, Src, Flags)
3938 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3941 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3942 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3953 unsigned Flags =
MI.getFlags();
3954 LLT Ty =
B.getMRI()->getType(Dst);
3961 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3962 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3963 .addUse(Ext.getReg(0))
3965 B.buildFPTrunc(Dst,
Log2, Flags);
3966 MI.eraseFromParent();
3976 MI.eraseFromParent();
3984 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3986 RangeCheckConst, Flags);
3988 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3989 auto Zero =
B.buildFConstant(Ty, 0.0);
3990 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3991 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3993 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3994 .addUse(AddInput.getReg(0))
3997 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3998 auto One =
B.buildFConstant(Ty, 1.0);
3999 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
4000 B.buildFMul(Dst, Exp2, ResultScale, Flags);
4001 MI.eraseFromParent();
4006 const SrcOp &Src,
unsigned Flags) {
4007 LLT Ty = Dst.getLLTTy(*
B.getMRI());
4010 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
4011 .addUse(Src.getReg())
4014 return B.buildFExp2(Dst, Src, Flags);
4020 bool IsExp10)
const {
4021 LLT Ty =
B.getMRI()->getType(
X);
4025 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
4026 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
4033 LLT Ty =
B.getMRI()->getType(Dst);
4039 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
4042 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
4043 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4044 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
4047 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
4049 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4050 .addUse(ExpInput.getReg(0))
4053 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
4054 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
4055 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4061 unsigned Flags)
const {
4062 LLT Ty =
B.getMRI()->getType(Dst);
4066 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4067 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4069 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4070 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4071 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4072 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4073 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4083 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4087 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4088 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4089 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4091 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4092 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4094 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4095 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4096 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4097 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4099 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4100 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4101 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4103 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4121 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4123 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4125 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4127 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4128 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4129 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4130 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4132 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4133 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4134 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4135 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4137 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4138 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4139 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4140 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4141 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4143 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4144 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4145 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4146 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4149 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4150 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4151 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4153 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4154 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4155 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4156 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4157 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4161 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4162 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4164 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4166 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4168 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4170 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4172 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4173 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4174 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4175 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4177 auto One =
B.buildFConstant(
F64, 1.0);
4178 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4179 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4182 auto DnInt =
B.buildFPTOSI(I32, Dn);
4183 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4190 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4197 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4199 MI.eraseFromParent();
4207 const unsigned Flags =
MI.getFlags();
4215 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4223 MI.eraseFromParent();
4234 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4237 B.buildFPTrunc(Dst, Lowered, Flags);
4238 MI.eraseFromParent();
4249 MI.eraseFromParent();
4277 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4280 if (ST.hasFastFMAF32()) {
4282 const float cc_exp = 0x1.4ae0bep-26f;
4283 const float c_exp10 = 0x1.a934f0p+1f;
4284 const float cc_exp10 = 0x1.2f346ep-24f;
4286 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4287 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4288 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4289 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4291 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4292 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4294 const float ch_exp = 0x1.714000p+0f;
4295 const float cl_exp = 0x1.47652ap-12f;
4297 const float ch_exp10 = 0x1.a92000p+1f;
4298 const float cl_exp10 = 0x1.4f0978p-11f;
4301 auto XInt =
B.buildBitcast(I32,
X);
4302 auto MaskConst =
B.buildConstant(I32, 0xfffff000);
4303 auto XH =
B.buildBitcast(Ty,
B.buildAnd(I32, XInt, MaskConst));
4304 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4306 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4307 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4309 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4310 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4313 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4314 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4317 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4320 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4321 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4323 auto IntE =
B.buildFPTOSI(I32, E);
4325 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4326 .addUse(
A.getReg(0))
4328 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4330 auto UnderflowCheckConst =
4331 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4332 auto Zero =
B.buildFConstant(Ty, 0.0);
4336 R =
B.buildSelect(Ty, Underflow, Zero, R);
4339 auto OverflowCheckConst =
4340 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4345 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4348 B.buildCopy(Dst, R);
4349 MI.eraseFromParent();
4360 unsigned Flags =
MI.getFlags();
4369 auto Log =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
4371 .setMIFlags(CoreFlags);
4372 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4374 .addUse(Log.getReg(0))
4375 .setMIFlags(CoreFlags);
4377 MI.eraseFromParent();
4381 auto Abs =
B.buildFAbs(
F32,
X, Flags);
4382 auto Log =
B.buildFLog2(
F32, Abs, CoreFlags);
4383 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4385 .addUse(Log.getReg(0))
4386 .setMIFlags(CoreFlags);
4391 .signBitIsZeroOrNaN()) {
4392 B.buildFExp2(Dst,
Mul, CoreFlags);
4393 MI.eraseFromParent();
4399 auto YTrunc =
B.buildIntrinsicTrunc(
F32,
Y);
4401 auto YHalf =
B.buildFMul(
F32,
Y,
B.buildFConstant(
F32, 0.5));
4402 auto YHalfTrunc =
B.buildIntrinsicTrunc(
F32, YHalf);
4403 auto YIsOdd =
B.buildAnd(
4407 auto Neg =
B.buildFCopysign(
F32, R,
X);
4409 B.buildSelect(Dst, YIsOdd, Neg, R);
4410 MI.eraseFromParent();
4413 R =
B.buildSelect(
F32, YIsOdd, Neg, R).getReg(0);
4420 auto XNegFinite =
B.buildIsFPClass(
S1,
X, NegFiniteMask);
4422 auto NegNonInt =
B.buildAnd(
S1, XNegFinite,
B.buildNot(
S1, YIsInt));
4424 B.buildSelect(Dst, NegNonInt, NaN, R);
4426 MI.eraseFromParent();
4434 ModSrc = SrcFNeg->getOperand(1).getReg();
4436 ModSrc = SrcFAbs->getOperand(1).getReg();
4438 ModSrc = SrcFAbs->getOperand(1).getReg();
4448 Register OrigSrc =
MI.getOperand(1).getReg();
4449 unsigned Flags =
MI.getFlags();
4451 "this should not have been custom lowered");
4461 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4480 if (MFI->
getMode().
IEEE && !ST.hasIEEEMinimumMaximumInsts())
4481 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4483 B.buildFMinNum(Min, Fract, Const, Flags);
4488 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4491 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4492 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4494 MI.eraseFromParent();
4512 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4514 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4515 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4518 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4519 B.buildBitcast(Dst,
Merge);
4521 MI.eraseFromParent();
4538 bool UsePartialMad64_32,
4539 bool SeparateOddAlignedProducts)
const {
4554 auto getZero32 = [&]() ->
Register {
4556 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4559 auto getZero64 = [&]() ->
Register {
4561 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4566 for (
unsigned i = 0; i < Src0.size(); ++i) {
4577 if (CarryIn.empty())
4580 bool HaveCarryOut =
true;
4582 if (CarryIn.size() == 1) {
4584 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4588 CarryAccum = getZero32();
4590 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4591 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4593 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4598 LocalAccum = getZero32();
4599 HaveCarryOut =
false;
4604 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4605 LocalAccum =
Add.getReg(0);
4619 auto buildMadChain =
4622 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4623 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4630 if (LocalAccum.size() == 1 &&
4631 (!UsePartialMad64_32 || !CarryIn.empty())) {
4634 unsigned j1 = DstIndex - j0;
4635 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4639 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4641 LocalAccum[0] =
Mul.getReg(0);
4643 if (CarryIn.empty()) {
4644 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4647 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4653 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4657 if (j0 <= DstIndex) {
4658 bool HaveSmallAccum =
false;
4661 if (LocalAccum[0]) {
4662 if (LocalAccum.size() == 1) {
4663 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4664 HaveSmallAccum =
true;
4665 }
else if (LocalAccum[1]) {
4666 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4667 HaveSmallAccum =
false;
4669 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4670 HaveSmallAccum =
true;
4673 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4675 HaveSmallAccum =
true;
4679 unsigned j1 = DstIndex - j0;
4680 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4684 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4685 {Src0[j0], Src1[j1], Tmp});
4686 Tmp = Mad.getReg(0);
4687 if (!HaveSmallAccum)
4688 CarryOut.push_back(Mad.getReg(1));
4689 HaveSmallAccum =
false;
4692 }
while (j0 <= DstIndex);
4694 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4695 LocalAccum[0] = Unmerge.getReg(0);
4696 if (LocalAccum.size() > 1)
4697 LocalAccum[1] = Unmerge.getReg(1);
4704 LocalAccum[0] = getZero32();
4708 assert((LocalAccum.size() == 1 || LocalAccum[1]) &&
4709 "Uninitialized accumulator part");
4735 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4736 Carry OddCarryIn = std::move(OddCarry);
4737 Carry EvenCarryIn = std::move(EvenCarry);
4742 if (2 * i < Accum.
size()) {
4743 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4744 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4749 if (!SeparateOddAlignedProducts) {
4750 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4751 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4753 bool IsHighest = 2 * i >= Accum.
size();
4756 .take_front(IsHighest ? 1 : 2);
4757 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4763 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4765 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4767 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4770 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4773 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4774 Lo->getOperand(1).getReg());
4775 Accum[2 * i] =
Hi.getReg(0);
4776 SeparateOddCarry =
Hi.getReg(1);
4783 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4784 EvenCarryIn.push_back(CarryOut);
4786 if (2 * i < Accum.
size()) {
4787 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4788 OddCarry.push_back(CarryOut);
4800 assert(ST.hasMad64_32());
4801 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4813 unsigned Size = Ty.getSizeInBits();
4814 if (ST.useVMulU64Inst() &&
Size == 64)
4817 unsigned NumParts =
Size / 32;
4829 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4833 for (
unsigned i = 0; i < NumParts; ++i) {
4837 B.buildUnmerge(Src0Parts, Src0);
4838 B.buildUnmerge(Src1Parts, Src1);
4841 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4842 SeparateOddAlignedProducts);
4844 B.buildMergeLikeInstr(DstReg, AccumRegs);
4845 MI.eraseFromParent();
4860 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4861 ? AMDGPU::G_AMDGPU_FFBH_U32
4862 : AMDGPU::G_AMDGPU_FFBL_B32;
4863 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4866 MI.eraseFromParent();
4876 TypeSize NumBits = SrcTy.getSizeInBits();
4881 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4882 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4883 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4884 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4885 B.buildTrunc(Dst, Ctlz);
4886 MI.eraseFromParent();
4897 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4898 unsigned BitWidth = SrcTy.getSizeInBits();
4900 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4901 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4902 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4903 MI.eraseFromParent();
4909 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4912 return ConstVal == -1;
4919 Register CondDef =
MI.getOperand(0).getReg();
4938 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4947 UncondBrTarget = &*NextMBB;
4949 if (
Next->getOpcode() != AMDGPU::G_BR)
4968 *ArgRC,
B.getDebugLoc(), ArgTy);
4972 const unsigned Mask = Arg->
getMask();
4980 auto ShiftAmt =
B.buildConstant(I32, Shift);
4981 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4984 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4986 B.buildCopy(DstReg, LiveIn);
4996 if (!ST.hasClusters()) {
4999 MI.eraseFromParent();
5019 auto One =
B.buildConstant(I32, 1);
5020 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
5021 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
5022 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
5029 B.buildCopy(DstReg, GlobalIdXYZ);
5030 MI.eraseFromParent();
5034 B.buildCopy(DstReg, ClusterIdXYZ);
5035 MI.eraseFromParent();
5040 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
5042 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
5043 B.buildInstr(AMDGPU::S_GETREG_B32_const)
5045 .addImm(ClusterIdField);
5046 auto Zero =
B.buildConstant(I32, 0);
5049 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
5050 MI.eraseFromParent();
5092 auto LoadConstant = [&](
unsigned N) {
5093 B.buildConstant(DstReg,
N);
5097 if (ST.hasArchitectedSGPRs() &&
5104 Arg = &WorkGroupIDX;
5105 ArgRC = &AMDGPU::SReg_32RegClass;
5109 Arg = &WorkGroupIDY;
5110 ArgRC = &AMDGPU::SReg_32RegClass;
5114 Arg = &WorkGroupIDZ;
5115 ArgRC = &AMDGPU::SReg_32RegClass;
5119 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5120 return LoadConstant(0);
5121 Arg = &ClusterWorkGroupIDX;
5122 ArgRC = &AMDGPU::SReg_32RegClass;
5126 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5127 return LoadConstant(0);
5128 Arg = &ClusterWorkGroupIDY;
5129 ArgRC = &AMDGPU::SReg_32RegClass;
5133 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5134 return LoadConstant(0);
5135 Arg = &ClusterWorkGroupIDZ;
5136 ArgRC = &AMDGPU::SReg_32RegClass;
5141 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5142 Arg = &ClusterWorkGroupMaxIDX;
5143 ArgRC = &AMDGPU::SReg_32RegClass;
5148 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5149 Arg = &ClusterWorkGroupMaxIDY;
5150 ArgRC = &AMDGPU::SReg_32RegClass;
5155 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5156 Arg = &ClusterWorkGroupMaxIDZ;
5157 ArgRC = &AMDGPU::SReg_32RegClass;
5161 Arg = &ClusterWorkGroupMaxFlatID;
5162 ArgRC = &AMDGPU::SReg_32RegClass;
5177 return LoadConstant(0);
5182 B.buildUndef(DstReg);
5186 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5198 MI.eraseFromParent();
5204 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5205 MI.eraseFromParent();
5212 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5226 B.buildUndef(DstReg);
5227 MI.eraseFromParent();
5231 if (Arg->isMasked()) {
5245 MI.eraseFromParent();
5260 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5269 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5277 Align Alignment)
const {
5281 "unexpected kernarg parameter type");
5288 MI.eraseFromParent();
5320 auto FloatY =
B.buildUITOFP(
F32,
Y);
5321 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5323 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5324 auto Z =
B.buildFPTOUI(I32, ScaledY);
5327 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5328 auto NegYZ =
B.buildMul(I32, NegY, Z);
5329 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5332 auto Q =
B.buildUMulH(I32,
X, Z);
5333 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5336 auto One =
B.buildConstant(I32, 1);
5339 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5340 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5345 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5348 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5367 auto Unmerge =
B.buildUnmerge(I32, Val);
5369 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5370 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5372 auto Mad =
B.buildFMAD(
5376 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5377 auto Mul1 =
B.buildFMul(
5381 auto Mul2 =
B.buildFMul(
5383 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5386 auto Mad2 =
B.buildFMAD(
5390 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5391 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5393 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5408 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5410 auto Zero64 =
B.buildConstant(I64, 0);
5411 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5413 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5414 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5416 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5417 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5418 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5420 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5421 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5422 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5424 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5425 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5426 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5427 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5428 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5430 auto Zero32 =
B.buildConstant(I32, 0);
5431 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5432 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5433 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5435 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5436 Register NumerLo = UnmergeNumer.getReg(0);
5437 Register NumerHi = UnmergeNumer.getReg(1);
5439 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5440 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5441 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5442 Register Mul3_Lo = UnmergeMul3.getReg(0);
5443 Register Mul3_Hi = UnmergeMul3.getReg(1);
5444 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5445 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5446 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5447 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5449 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5450 Register DenomLo = UnmergeDenom.getReg(0);
5451 Register DenomHi = UnmergeDenom.getReg(1);
5454 auto C1 =
B.buildSExt(I32, CmpHi);
5457 auto C2 =
B.buildSExt(I32, CmpLo);
5460 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5467 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5468 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5469 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5470 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5472 auto One64 =
B.buildConstant(I64, 1);
5473 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5479 auto C6 =
B.buildSelect(
5483 auto Add4 =
B.buildAdd(I64, Add3, One64);
5484 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5486 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5487 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5488 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5494 auto Sel1 =
B.buildSelect(
5501 auto Sel2 =
B.buildSelect(
5512 switch (
MI.getOpcode()) {
5515 case AMDGPU::G_UDIV: {
5516 DstDivReg =
MI.getOperand(0).getReg();
5519 case AMDGPU::G_UREM: {
5520 DstRemReg =
MI.getOperand(0).getReg();
5523 case AMDGPU::G_UDIVREM: {
5524 DstDivReg =
MI.getOperand(0).getReg();
5525 DstRemReg =
MI.getOperand(1).getReg();
5532 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5533 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5534 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5544 MI.eraseFromParent();
5555 if (Ty != I32 && Ty != I64)
5558 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5559 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5560 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5562 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5563 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5564 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5566 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5567 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5569 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5570 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5572 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5573 switch (
MI.getOpcode()) {
5576 case AMDGPU::G_SDIV: {
5577 DstDivReg =
MI.getOperand(0).getReg();
5581 case AMDGPU::G_SREM: {
5582 DstRemReg =
MI.getOperand(0).getReg();
5586 case AMDGPU::G_SDIVREM: {
5587 DstDivReg =
MI.getOperand(0).getReg();
5588 DstRemReg =
MI.getOperand(1).getReg();
5601 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5602 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5603 B.buildSub(DstDivReg, SignXor, Sign);
5607 auto Sign = LHSign.getReg(0);
5608 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5609 B.buildSub(DstRemReg, SignXor, Sign);
5612 MI.eraseFromParent();
5622 uint16_t Flags =
MI.getFlags();
5628 if (!AllowInaccurateRcp && ResTy !=
F16)
5639 if (CLHS->isOne()) {
5640 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5644 MI.eraseFromParent();
5649 if (CLHS->isMinusOne()) {
5650 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5651 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5652 .addUse(FNeg.getReg(0))
5655 MI.eraseFromParent();
5662 if (!AllowInaccurateRcp &&
5667 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5670 B.buildFMul(Res, LHS, RCP, Flags);
5672 MI.eraseFromParent();
5682 uint16_t Flags =
MI.getFlags();
5687 if (!AllowInaccurateRcp)
5695 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5697 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5698 auto One =
B.buildFConstant(ResTy, 1.0);
5700 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5704 R =
B.buildFNeg(ResTy, R);
5706 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5707 R =
B.buildFMA(ResTy, Tmp0, R, R);
5709 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5710 R =
B.buildFMA(ResTy, Tmp1, R, R);
5713 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5714 B.buildCopy(Res, R);
5715 MI.eraseFromParent();
5719 auto Ret =
B.buildFMul(ResTy,
X, R);
5720 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5722 B.buildFMA(Res, Tmp2, R, Ret);
5723 MI.eraseFromParent();
5737 uint16_t Flags =
MI.getFlags();
5754 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5755 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5756 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5757 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5758 .addUse(RHSExt.getReg(0))
5760 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5762 if (ST.hasMadMacF32Insts()) {
5763 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5764 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5765 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5767 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5768 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5769 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5771 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5772 auto TmpInt =
B.buildBitcast(I32, Tmp);
5773 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5774 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5775 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5776 auto RDst =
B.buildFPTrunc(
F16, Quot, Flags);
5777 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5778 .addUse(RDst.getReg(0))
5783 MI.eraseFromParent();
5796 unsigned SPDenormMode =
5799 if (ST.hasDenormModeInst()) {
5801 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5803 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5804 B.buildInstr(AMDGPU::S_DENORM_MODE)
5805 .addImm(NewDenormModeValue);
5808 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5809 .addImm(SPDenormMode)
5826 uint16_t Flags =
MI.getFlags();
5830 auto One =
B.buildFConstant(
F32, 1.0f);
5832 auto DenominatorScaled =
5833 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5838 auto NumeratorScaled =
5839 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5845 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5846 .addUse(DenominatorScaled.getReg(0))
5848 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5851 const bool HasDynamicDenormals =
5856 if (!PreservesDenormals) {
5857 if (HasDynamicDenormals) {
5859 B.buildInstr(AMDGPU::S_GETREG_B32)
5860 .addDef(SavedSPDenormMode)
5866 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5867 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5868 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5869 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5870 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5871 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5873 if (!PreservesDenormals) {
5874 if (HasDynamicDenormals) {
5875 assert(SavedSPDenormMode);
5876 B.buildInstr(AMDGPU::S_SETREG_B32)
5877 .addReg(SavedSPDenormMode)
5883 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5884 .addUse(Fma4.getReg(0))
5885 .addUse(Fma1.getReg(0))
5886 .addUse(Fma3.getReg(0))
5887 .addUse(NumeratorScaled.getReg(1))
5890 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5891 .addUse(Fmas.getReg(0))
5896 MI.eraseFromParent();
5910 uint16_t Flags =
MI.getFlags();
5914 auto One =
B.buildFConstant(
F64, 1.0);
5916 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5922 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5924 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5925 .addUse(DivScale0.getReg(0))
5928 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5929 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5930 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5932 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5938 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5939 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5940 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5943 if (!ST.hasUsableDivScaleConditionOutput()) {
5950 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5951 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5952 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5953 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5956 Scale1Unmerge.getReg(1));
5958 Scale0Unmerge.getReg(1));
5959 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5961 Scale = DivScale1.getReg(1);
5964 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5965 .addUse(Fma4.getReg(0))
5966 .addUse(Fma3.getReg(0))
5967 .addUse(
Mul.getReg(0))
5971 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5972 .addUse(Fmas.getReg(0))
5977 MI.eraseFromParent();
5987 uint16_t Flags =
MI.getFlags();
5992 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5995 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5999 if (ST.hasFractBug()) {
6000 auto Fabs =
B.buildFAbs(Ty, Val);
6004 auto Zero =
B.buildConstant(InstrExpTy, 0);
6005 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
6006 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
6009 B.buildCopy(Res0, Mant);
6010 B.buildSExtOrTrunc(Res1, Exp);
6012 MI.eraseFromParent();
6022 uint16_t Flags =
MI.getFlags();
6026 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
6029 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
6030 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
6031 auto C2 =
B.buildFConstant(
F32, 1.0f);
6034 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
6036 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
6038 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
6039 .addUse(Mul0.getReg(0))
6042 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
6044 B.buildFMul(Res, Sel, Mul1, Flags);
6046 MI.eraseFromParent();
6055 unsigned Flags =
MI.getFlags();
6056 assert(!ST.has16BitInsts());
6057 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
6058 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
6059 .addUse(Ext.getReg(0))
6061 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
6062 MI.eraseFromParent();
6072 const unsigned Flags =
MI.getFlags();
6080 MI.eraseFromParent();
6084 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
6086 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
6087 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
6088 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
6093 .addUse(SqrtX.getReg(0))
6096 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6097 auto NegOne =
B.buildConstant(I32, -1);
6098 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6100 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6101 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6103 auto PosOne =
B.buildConstant(I32, 1);
6104 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6106 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6107 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6109 auto Zero =
B.buildFConstant(
F32, 0.0f);
6113 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6117 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6120 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6121 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6123 auto Half =
B.buildFConstant(
F32, 0.5f);
6124 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6125 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6126 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6127 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6128 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6129 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6130 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6131 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6134 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6136 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6138 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6141 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6143 MI.eraseFromParent();
6177 unsigned Flags =
MI.getFlags();
6182 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6184 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6188 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6189 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6190 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6193 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6195 auto Half =
B.buildFConstant(
F64, 0.5);
6196 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6197 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6199 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6200 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6202 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6203 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6205 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6206 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6208 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6210 Register SqrtRet = SqrtS2.getReg(0);
6212 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6213 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6214 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6217 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6218 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6219 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6224 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6227 IsZeroOrInf =
B.buildIsFPClass(I1, SqrtX,
fcZero |
fcPosInf).getReg(0);
6233 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6235 MI.eraseFromParent();
6266 auto Flags =
MI.getFlags();
6278 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6288 auto ClampMax = UseIEEE && !ST.hasIEEEMinimumMaximumInsts()
6289 ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags)
6290 :
B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6294 if (UseIEEE && !ST.hasIEEEMinimumMaximumInsts())
6295 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6297 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6298 MI.eraseFromParent();
6310 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6311 IID == Intrinsic::amdgcn_permlanex16;
6312 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6313 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6314 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6315 IID == Intrinsic::amdgcn_permlane_up ||
6316 IID == Intrinsic::amdgcn_permlane_down ||
6317 IID == Intrinsic::amdgcn_permlane_xor;
6321 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6323 case Intrinsic::amdgcn_readfirstlane:
6324 case Intrinsic::amdgcn_permlane64:
6325 return LaneOp.getReg(0);
6326 case Intrinsic::amdgcn_readlane:
6327 case Intrinsic::amdgcn_set_inactive:
6328 case Intrinsic::amdgcn_set_inactive_chain_arg:
6329 return LaneOp.addUse(Src1).getReg(0);
6330 case Intrinsic::amdgcn_writelane:
6331 case Intrinsic::amdgcn_permlane_bcast:
6332 case Intrinsic::amdgcn_permlane_up:
6333 case Intrinsic::amdgcn_permlane_down:
6334 case Intrinsic::amdgcn_permlane_xor:
6335 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6336 case Intrinsic::amdgcn_permlane16:
6337 case Intrinsic::amdgcn_permlanex16: {
6339 int64_t Src4 =
MI.getOperand(6).getImm();
6340 int64_t Src5 =
MI.getOperand(7).getImm();
6341 return LaneOp.addUse(Src1)
6348 case Intrinsic::amdgcn_mov_dpp8:
6349 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6350 case Intrinsic::amdgcn_update_dpp:
6351 return LaneOp.addUse(Src1)
6352 .addImm(
MI.getOperand(4).getImm())
6353 .addImm(
MI.getOperand(5).getImm())
6354 .addImm(
MI.getOperand(6).getImm())
6355 .addImm(
MI.getOperand(7).getImm())
6365 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6366 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6367 IsPermlaneShuffle) {
6368 Src1 =
MI.getOperand(3).getReg();
6369 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6370 IsPermlaneShuffle) {
6371 Src2 =
MI.getOperand(4).getReg();
6376 unsigned Size = Ty.getSizeInBits();
6378 unsigned SplitSize = 32;
6379 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6380 ST.hasDPALU_DPP() &&
6384 if (
Size == SplitSize) {
6391 bool IsFloat = Ty.getScalarType().isFloat();
6395 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6397 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6399 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6403 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6405 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6406 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6408 if (IID == Intrinsic::amdgcn_writelane)
6409 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6411 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6413 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6415 B.buildTrunc(DstReg, LaneOpDst);
6416 MI.eraseFromParent();
6420 if (
Size % SplitSize != 0)
6424 bool NeedsBitcast =
false;
6425 if (IntTy.isVector()) {
6428 if (EltSize == SplitSize) {
6429 PartialResTy = EltTy;
6430 }
else if (EltSize == 16 || EltSize == 32) {
6431 unsigned NElem = SplitSize / EltSize;
6434 NeedsBitcast =
true;
6439 unsigned NumParts =
Size / SplitSize;
6443 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6444 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6446 if (IID == Intrinsic::amdgcn_writelane)
6447 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6449 for (
unsigned i = 0; i < NumParts; ++i) {
6450 Src0 = Src0Parts.
getReg(i);
6452 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6453 Src1 = Src1Parts.
getReg(i);
6455 if (IID == Intrinsic::amdgcn_writelane)
6456 Src2 = Src2Parts.
getReg(i);
6458 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6461 if (NeedsBitcast || IsFloat)
6464 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6466 B.buildMergeLikeInstr(DstReg, PartialRes);
6468 MI.eraseFromParent();
6476 ST.getTargetLowering()->getImplicitParameterOffset(
6486 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6487 B.buildConstant(IdxTy,
Offset).getReg(0));
6498 Register Pointer =
MI.getOperand(2).getReg();
6500 Register NumRecords =
MI.getOperand(4).getReg();
6506 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6508 auto ExtStride =
B.buildAnyExt(I32, Stride);
6510 if (ST.getBufferResourceNumRecordsWidth() == 45) {
6511 NumRecords =
B.buildZExtOrTrunc(I64, NumRecords).getReg(0);
6513 B.buildAnd(I64, NumRecords,
B.buildConstant(I64, (1ULL << 45) - 1))
6515 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6519 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6520 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6521 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6522 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6526 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6527 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6528 auto ExtShiftedStride =
6529 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6530 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6531 auto ExtShiftedFlags =
6532 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6533 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6535 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6536 B.buildMergeValues(Result, {LowHalf, HighHalf});
6538 NumRecords =
B.buildZExtOrTrunc(I32, NumRecords).getReg(0);
6539 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6540 auto LowHalf = Unmerge.getReg(0);
6541 auto HighHalf = Unmerge.getReg(1);
6543 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6544 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6545 auto ShiftConst =
B.buildConstant(I32, 16);
6546 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6547 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6548 Register NewHighHalfReg = NewHighHalf.getReg(0);
6549 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6552 MI.eraseFromParent();
6569 MI.eraseFromParent();
6576 unsigned AddrSpace)
const {
6578 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6582 ST.hasGloballyAddressableScratch()) {
6584 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6585 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6587 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6589 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6591 B.buildConstant(I32, 1u << 26));
6596 MI.eraseFromParent();
6606std::pair<Register, unsigned>
6618 bool CheckNUW = ST.hasGFX1250Insts();
6620 MRI, OrigOffset,
nullptr, CheckNUW);
6624 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6634 unsigned Overflow = ImmOffset & ~MaxImm;
6635 ImmOffset -= Overflow;
6636 if ((int32_t)Overflow < 0) {
6637 Overflow += ImmOffset;
6641 if (Overflow != 0) {
6643 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6645 auto OverflowVal =
B.buildConstant(I32, Overflow);
6646 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6651 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6653 return std::pair(BaseReg, ImmOffset);
6660 bool ImageStore)
const {
6668 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6670 if (ST.hasUnpackedD16VMem()) {
6671 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6674 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6675 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6683 if (ImageStore && ST.hasImageStoreD16Bug()) {
6686 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6688 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6695 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6696 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6698 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6706 auto Unmerge =
B.buildUnmerge(I32, Reg);
6707 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6709 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6719 Reg =
B.buildPadVectorWithUndefElements(
6728 bool IsFormat)
const {
6738 VData =
B.buildBitcast(Ty, VData).getReg(0);
6740 if (Ty.isFloat(16)) {
6742 VData =
B.buildBitcast(Ty, VData).getReg(0);
6749 if (Ty.isVector()) {
6750 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6762 bool IsFormat)
const {
6769 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6776 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6777 const Function &Fn =
B.getMF().getFunction();
6779 Fn,
"unsupported sub-dword format buffer store",
MI.getDebugLoc()));
6780 MI.eraseFromParent();
6792 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6795 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6799 VIndex =
MI.getOperand(3).getReg();
6802 VIndex =
B.buildConstant(I32, 0).getReg(0);
6805 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6806 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6810 Format =
MI.getOperand(5 + OpOffset).getImm();
6814 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6820 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6821 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6822 }
else if (IsFormat) {
6823 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6824 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6828 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6831 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6834 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6839 auto MIB =
B.buildInstr(
Opc)
6850 MIB.addImm(AuxiliaryData)
6851 .addImm(HasVIndex ? -1 : 0)
6852 .addMemOperand(MMO);
6854 MI.eraseFromParent();
6860 unsigned ImmOffset,
unsigned Format,
6863 auto MIB =
B.buildInstr(
Opc)
6874 MIB.addImm(AuxiliaryData)
6875 .addImm(HasVIndex ? -1 : 0)
6876 .addMemOperand(MMO);
6882 Register SOffset,
unsigned ImmOffset,
6883 unsigned Format,
unsigned AuxiliaryData,
6887 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6889 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6892 B.buildUnmerge(Unmerge, LoadDstReg);
6898 bool IsTyped)
const {
6912 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6913 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6915 StatusDst =
MI.getOperand(1).getReg();
6920 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6923 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6926 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6929 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6932 VIndex =
B.buildConstant(I32, 0).getReg(0);
6935 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6936 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6940 Format =
MI.getOperand(5 + OpOffset).getImm();
6944 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6954 Dst =
MI.getOperand(0).getReg();
6955 B.setInsertPt(
B.getMBB(),
MI);
6962 Dst =
MI.getOperand(0).getReg();
6963 B.setInsertPt(
B.getMBB(),
MI);
6967 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6968 const bool Unpacked = ST.hasUnpackedD16VMem();
6970 if (IsFormat && !IsTyped && !IsD16 && MemTy.
getSizeInBits() < 32) {
6971 const Function &Fn =
B.getMF().getFunction();
6973 Fn,
"unsupported sub-dword format buffer load",
MI.getDebugLoc()));
6976 B.buildUndef(StatusDst);
6977 MI.eraseFromParent();
6981 if (!IsTyped && IsD16 && IsTFE && !ST.hasBufferTFEFormatD16()) {
6982 const Function &Fn =
B.getMF().getFunction();
6984 Fn,
"TFE D16 format buffer load is not supported on this GPU",
6987 B.buildUndef(StatusDst);
6988 MI.eraseFromParent();
7000 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
7001 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
7002 }
else if (IsFormat) {
7004 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE
7005 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
7007 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
7008 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
7013 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
7014 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
7017 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
7018 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
7021 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
7022 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
7027 if (IsTFE && IsD16 && Ty.isVector()) {
7029 const unsigned NumElts = Ty.getNumElements();
7030 const unsigned NumValueDWords = Unpacked ? NumElts :
divideCeil(NumElts, 2);
7033 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7036 SOffset, ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7041 R =
B.buildTrunc(EltTy, R).getReg(0);
7042 B.buildMergeLikeInstr(Dst, ValueDWords);
7051 if (PackedTy == Ty) {
7052 B.buildBitcast(Dst, Merged);
7054 Register Packed =
B.buildBitcast(PackedTy, Merged).getReg(0);
7055 B.buildDeleteTrailingVectorElements(Dst, Packed);
7059 const unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
7067 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7069 B.buildTrunc(DstInt, ExtDst);
7070 }
else if (NumValueDWords == 1) {
7072 ImmOffset,
Format, AuxiliaryData, MMO, IsTyped,
7076 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
7079 SOffset, ImmOffset,
Format, AuxiliaryData, MMO,
7080 IsTyped, HasVIndex,
B);
7081 B.buildMergeLikeInstr(DstInt, ValueDWords);
7084 B.buildBitcast(Dst, DstInt);
7086 (IsD16 && !Ty.isVector())) {
7087 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
7089 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7090 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7091 B.buildTrunc(Dst, LoadDstReg);
7092 }
else if (Unpacked && IsD16 && Ty.isVector()) {
7094 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
7096 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7097 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7099 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
7101 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
7102 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
7103 B.buildMergeLikeInstr(Dst, Repack);
7106 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
7109 MI.eraseFromParent();
7115 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
7116 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
7117 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
7118 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
7119 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
7120 case Intrinsic::amdgcn_raw_buffer_atomic_add:
7121 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
7122 case Intrinsic::amdgcn_struct_buffer_atomic_add:
7123 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
7124 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
7125 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
7126 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
7127 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
7128 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
7129 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
7130 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
7131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
7132 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
7133 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
7134 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
7135 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
7136 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
7137 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
7138 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
7139 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
7140 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
7141 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
7142 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
7143 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
7144 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7145 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7147 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7148 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7149 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7150 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7151 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7152 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7153 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7154 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7155 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7156 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7157 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7158 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7159 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7160 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7161 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7162 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7163 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7164 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7165 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7166 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7167 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7168 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7169 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7170 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7171 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7172 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7173 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7174 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7175 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7176 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7177 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7178 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7179 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7180 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7182 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7183 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7184 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7185 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7186 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7187 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7188 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7189 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7190 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7191 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7192 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7194 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7195 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7197 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7198 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7199 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7200 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7201 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7202 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7203 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7204 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7213 const bool IsCmpSwap =
7214 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7215 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7216 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7217 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7228 CmpVal =
MI.getOperand(3).getReg();
7233 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7234 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7237 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7240 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7246 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7247 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7248 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7267 .addImm(AuxiliaryData)
7268 .addImm(HasVIndex ? -1 : 0)
7269 .addMemOperand(MMO);
7271 MI.eraseFromParent();
7281 bool IsA16,
bool IsG16) {
7295 (
B.getMRI()->getType(AddrReg) ==
F16)) {
7300 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7304 "Bias needs to be converted to 16 bit in A16 mode");
7306 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7310 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7314 if (((
I + 1) >= EndIdx) ||
7321 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7323 B.buildBuildVector(V2EltTy,
7324 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7329 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7340 int DimIdx,
int NumVAddrs) {
7342 for (
int I = 0;
I != NumVAddrs; ++
I) {
7344 if (
SrcOp.isReg()) {
7347 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7348 if (
B.getMRI()->getType(
Reg) != I32)
7349 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7354 int NumAddrRegs = AddrRegs.
size();
7355 if (NumAddrRegs != 1) {
7356 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7359 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7362 for (
int I = 1;
I != NumVAddrs; ++
I) {
7365 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7387 const unsigned NumDefs =
MI.getNumExplicitDefs();
7388 const unsigned ArgOffset = NumDefs + 1;
7389 bool IsTFE = NumDefs == 2;
7407 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7411 const bool IsAtomicPacked16Bit =
7412 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7413 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7420 const bool GradTyIs16 = GradTy == I16 || GradTy ==
F16;
7421 const bool AddrTyIs16 = AddrTy == I16 || AddrTy ==
F16;
7422 const bool DataTyIs16 =
7423 Ty.getScalarType() == I16 || Ty.getScalarType() ==
F16;
7425 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7426 const bool IsA16 = AddrTyIs16;
7427 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7430 if (!BaseOpcode->
Atomic) {
7431 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7434 }
else if (DMask != 0) {
7436 }
else if (!IsTFE && !BaseOpcode->
Store) {
7438 B.buildUndef(
MI.getOperand(0));
7439 MI.eraseFromParent();
7447 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7448 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7449 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7450 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7451 unsigned NewOpcode = LoadOpcode;
7452 if (BaseOpcode->
Store)
7453 NewOpcode = StoreOpcode;
7455 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7458 MI.setDesc(
B.getTII().get(NewOpcode));
7462 if (IsTFE && DMask == 0) {
7465 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7468 if (BaseOpcode->
Atomic) {
7473 if (Ty.isVector() && !IsAtomicPacked16Bit)
7480 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7481 MI.getOperand(2).setReg(
Concat.getReg(0));
7482 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7486 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7489 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7495 if (IsA16 && !ST.hasA16()) {
7500 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7501 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7503 if (IsA16 || IsG16) {
7511 const bool UseNSA = ST.hasNSAEncoding() &&
7512 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7513 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7514 const bool UsePartialNSA =
7515 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7517 if (UsePartialNSA) {
7521 auto Concat =
B.buildConcatVectors(
7522 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7523 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7524 PackedRegs.
resize(NSAMaxSize);
7525 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7527 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7528 PackedRegs[0] =
Concat.getReg(0);
7532 const unsigned NumPacked = PackedRegs.
size();
7535 if (!
SrcOp.isReg()) {
7545 SrcOp.setReg(AMDGPU::NoRegister);
7562 const bool UseNSA = ST.hasNSAEncoding() &&
7563 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7564 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7565 const bool UsePartialNSA =
7566 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7568 if (UsePartialNSA) {
7570 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7572 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7587 if (!Ty.isVector() || !IsD16)
7591 if (RepackedReg != VData) {
7592 MI.getOperand(1).setReg(RepackedReg);
7600 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7603 if (NumElts < DMaskLanes)
7606 if (NumElts > 4 || DMaskLanes > 4)
7617 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7618 const LLT AdjustedTy =
7634 if (IsD16 && ST.hasUnpackedD16VMem()) {
7641 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7642 unsigned RoundedSize = 32 * RoundedElts;
7646 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7651 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7657 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7661 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7662 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7666 MI.getOperand(0).setReg(NewResultReg);
7674 Dst1Reg =
MI.getOperand(1).getReg();
7675 if (MRI->
getType(Dst1Reg) != I32)
7679 MI.removeOperand(1);
7682 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7683 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7684 B.buildBitcast(DstReg, Unmerge.getReg(0));
7685 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7694 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7696 if (ResultNumRegs == 1) {
7698 ResultRegs[0] = NewResultReg;
7701 for (
int I = 0;
I != NumDataRegs; ++
I)
7703 B.buildUnmerge(ResultRegs, NewResultReg);
7708 ResultRegs.
resize(NumDataRegs);
7713 if (IsD16 && !Ty.isVector()) {
7714 B.buildTrunc(DstReg, ResultRegs[0]);
7719 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7720 !ST.hasUnpackedD16VMem()) {
7721 B.buildBitcast(DstReg, ResultRegs[0]);
7733 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7735 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7736 }
else if (ST.hasUnpackedD16VMem()) {
7738 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7742 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7746 for (
int I = 0;
I != NumElts; ++
I)
7753 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7754 B.buildBuildVector(DstReg, ResultRegs);
7758 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7759 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7764 if (Ty == V3I16 || Ty == V3F16) {
7766 if (ResultRegs.
size() == 1) {
7767 NewResultReg = ResultRegs[0];
7768 }
else if (ResultRegs.
size() == 2) {
7770 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7785 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7787 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7789 if (ResizeDst != DstReg)
7790 B.buildBitcast(DstReg, ResizeDst);
7794 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7795 B.buildConcatVectors(DstReg, ResultRegs);
7804 Register OrigDst =
MI.getOperand(0).getReg();
7806 LLT Ty =
B.getMRI()->getType(OrigDst);
7807 unsigned Size = Ty.getSizeInBits();
7809 bool HasMMO = !
MI.memoperands_empty();
7814 bool IsSubwordLoad = Ty.isScalar() &&
Size < 32 && ST.hasScalarSubwordLoads();
7815 if (
Size % 32 != 0 && !IsSubwordLoad) {
7818 Fn,
"unsupported s_buffer_load result type",
MI.getDebugLoc()));
7819 B.buildUndef(OrigDst);
7820 MI.eraseFromParent();
7825 if (IsSubwordLoad) {
7827 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7828 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7831 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7833 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7842 B.setInsertPt(
B.getMBB(),
MI);
7847 B.setInsertPt(
B.getMBB(),
MI);
7850 MI.setDesc(
B.getTII().get(
Opc));
7851 MI.removeOperand(1);
7857 const unsigned MemSize = (
Size + 7) / 8;
7858 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7865 MI.addMemOperand(MF, MMO);
7867 if (Dst != OrigDst) {
7868 MI.getOperand(0).setReg(Dst);
7869 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7870 B.buildTrunc(OrigDst, Dst);
7892 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7893 MI.removeOperand(0);
7904 if (!ST.hasTrapHandler() ||
7923 MI.eraseFromParent();
7935 for (
auto I = SplitPoint, E = BB.
end();
I != E; ++
I) {
7944 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7946 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7950 MI.eraseFromParent();
7959 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7966 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7986 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7989 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7990 B.buildCopy(SGPR01, Temp);
7991 B.buildInstr(AMDGPU::S_TRAP)
7994 MI.eraseFromParent();
8005 B.buildCopy(SGPR01, LiveIn);
8006 B.buildInstr(AMDGPU::S_TRAP)
8010 MI.eraseFromParent();
8021 if (ST.hasPrivEnabledTrap2NopBug()) {
8033 ST.getInstrInfo()->insertSimulatedTrap(MRI,
MBB,
MI,
MI.getDebugLoc());
8036 MI.eraseFromParent();
8040 B.buildInstr(AMDGPU::S_TRAP)
8042 MI.eraseFromParent();
8051 if (!ST.hasTrapHandler() ||
8055 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
8058 B.buildInstr(AMDGPU::S_TRAP)
8062 MI.eraseFromParent();
8076 Register NodePtr =
MI.getOperand(2).getReg();
8077 Register RayExtent =
MI.getOperand(3).getReg();
8078 Register RayOrigin =
MI.getOperand(4).getReg();
8080 Register RayInvDir =
MI.getOperand(6).getReg();
8083 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
8090 const unsigned NumVDataDwords = 4;
8091 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
8092 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
8094 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
8096 const unsigned BaseOpcodes[2][2] = {
8097 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
8098 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
8099 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
8103 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
8104 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
8105 : AMDGPU::MIMGEncGfx10NSA,
8106 NumVDataDwords, NumVAddrDwords);
8110 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
8111 : AMDGPU::MIMGEncGfx10Default,
8112 NumVDataDwords, NumVAddrDwords);
8117 if (UseNSA && IsGFX11Plus) {
8118 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8119 auto SrcInt =
B.buildBitcast(V3I32, Src);
8120 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8121 auto Merged =
B.buildMergeLikeInstr(
8122 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
8123 Ops.push_back(Merged.getReg(0));
8126 Ops.push_back(NodePtr);
8127 Ops.push_back(RayExtent);
8128 packLanes(RayOrigin);
8131 auto UnmergeRayDir =
8132 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8133 auto UnmergeRayInvDir =
8134 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8135 auto MergedDir =
B.buildMergeLikeInstr(
8138 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
8139 UnmergeRayDir.getReg(0)}))
8142 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
8143 UnmergeRayDir.getReg(1)}))
8146 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
8147 UnmergeRayDir.getReg(2)}))
8149 Ops.push_back(MergedDir.getReg(0));
8152 packLanes(RayInvDir);
8156 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
8157 Ops.push_back(Unmerge.getReg(0));
8158 Ops.push_back(Unmerge.getReg(1));
8160 Ops.push_back(NodePtr);
8162 Ops.push_back(RayExtent);
8164 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
8165 auto SrcInt =
B.buildBitcast(V3I32, Src);
8166 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
8167 Ops.push_back(Unmerge.getReg(0));
8168 Ops.push_back(Unmerge.getReg(1));
8169 Ops.push_back(Unmerge.getReg(2));
8172 packLanes(RayOrigin);
8174 auto UnmergeRayDir =
8175 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
8176 auto UnmergeRayInvDir =
8177 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8181 B.buildMergeLikeInstr(R1,
8182 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8183 B.buildMergeLikeInstr(
8184 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8185 B.buildMergeLikeInstr(
8186 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8192 packLanes(RayInvDir);
8201 Ops.push_back(MergedOps);
8204 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8213 .addImm(IsA16 ? 1 : 0)
8216 MI.eraseFromParent();
8226 Register DstOrigin =
MI.getOperand(1).getReg();
8228 Register NodePtr =
MI.getOperand(4).getReg();
8229 Register RayExtent =
MI.getOperand(5).getReg();
8230 Register InstanceMask =
MI.getOperand(6).getReg();
8231 Register RayOrigin =
MI.getOperand(7).getReg();
8233 Register Offsets =
MI.getOperand(9).getReg();
8234 Register TDescr =
MI.getOperand(10).getReg();
8237 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8238 const unsigned NumVDataDwords = 10;
8239 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8241 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8242 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8243 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8246 auto RayExtentInstanceMaskVec =
8247 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8248 B.buildAnyExt(I32, InstanceMask)});
8250 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8251 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8257 .addUse(RayExtentInstanceMaskVec.getReg(0))
8264 MI.eraseFromParent();
8273 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8274 MI.eraseFromParent();
8281 if (!ST.hasArchitectedSGPRs())
8285 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8286 auto LSB =
B.buildConstant(I32, 25);
8287 auto Width =
B.buildConstant(I32, 5);
8288 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8289 MI.eraseFromParent();
8297 unsigned Width)
const {
8301 {&AMDGPU::SReg_32RegClass, MRI.
getType(DstReg)});
8302 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8305 B.buildCopy(DstReg, Result);
8306 MI.eraseFromParent();
8326 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8330 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8333 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8334 MI.eraseFromParent();
8347 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8351 .addReg(Unmerge.getReg(0));
8355 .addReg(Unmerge.getReg(1));
8356 MI.eraseFromParent();
8368 case Intrinsic::sponentry:
8374 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8377 B.buildIntToPtr(DstReg, TmpReg);
8378 MI.eraseFromParent();
8380 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8382 B.buildFrameIndex(
MI.getOperand(0), FI);
8383 MI.eraseFromParent();
8386 case Intrinsic::amdgcn_if:
8387 case Intrinsic::amdgcn_else: {
8390 bool Negated =
false;
8407 std::swap(CondBrTarget, UncondBrTarget);
8409 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8410 B.buildCopy(NewUse,
Use);
8411 if (IntrID == Intrinsic::amdgcn_if) {
8412 B.buildInstr(AMDGPU::SI_IF)
8415 .addMBB(UncondBrTarget)
8418 B.buildInstr(AMDGPU::SI_ELSE)
8421 .addMBB(UncondBrTarget)
8431 B.buildBr(*CondBrTarget);
8434 MI.eraseFromParent();
8435 BrCond->eraseFromParent();
8446 case Intrinsic::amdgcn_loop: {
8449 bool Negated =
false;
8458 {
TRI->getWaveMaskRegClass(), MRI.
getType(Reg)});
8461 std::swap(CondBrTarget, UncondBrTarget);
8463 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8464 B.buildCopy(NewReg, Reg);
8465 B.buildInstr(AMDGPU::SI_LOOP)
8467 .addMBB(UncondBrTarget)
8473 B.buildBr(*CondBrTarget);
8475 MI.eraseFromParent();
8476 BrCond->eraseFromParent();
8482 case Intrinsic::amdgcn_wave_reduce_min:
8483 case Intrinsic::amdgcn_wave_reduce_umin:
8484 case Intrinsic::amdgcn_wave_reduce_fmin:
8485 case Intrinsic::amdgcn_wave_reduce_max:
8486 case Intrinsic::amdgcn_wave_reduce_umax:
8487 case Intrinsic::amdgcn_wave_reduce_fmax:
8488 case Intrinsic::amdgcn_wave_reduce_add:
8489 case Intrinsic::amdgcn_wave_reduce_fadd:
8490 case Intrinsic::amdgcn_wave_reduce_sub:
8491 case Intrinsic::amdgcn_wave_reduce_fsub:
8492 case Intrinsic::amdgcn_wave_reduce_and:
8493 case Intrinsic::amdgcn_wave_reduce_or:
8494 case Intrinsic::amdgcn_wave_reduce_xor: {
8499 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8500 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8501 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8502 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8503 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8504 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8505 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8506 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8507 auto Ext = IsFPOp ?
B.buildFPExt(
F32, SrcReg)
8514 .addUse(Ext.getReg(0))
8515 .addImm(
MI.getOperand(3).getImm());
8517 B.buildFPTrunc(DstReg, NewDst);
8519 B.buildTrunc(DstReg, NewDst);
8520 MI.eraseFromParent();
8523 case Intrinsic::amdgcn_make_buffer_rsrc:
8525 case Intrinsic::amdgcn_kernarg_segment_ptr:
8528 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8529 MI.eraseFromParent();
8535 case Intrinsic::amdgcn_implicitarg_ptr:
8537 case Intrinsic::amdgcn_workitem_id_x:
8540 case Intrinsic::amdgcn_workitem_id_y:
8543 case Intrinsic::amdgcn_workitem_id_z:
8546 case Intrinsic::amdgcn_workgroup_id_x:
8551 case Intrinsic::amdgcn_workgroup_id_y:
8556 case Intrinsic::amdgcn_workgroup_id_z:
8561 case Intrinsic::amdgcn_cluster_id_x:
8562 return ST.hasClusters() &&
8565 case Intrinsic::amdgcn_cluster_id_y:
8566 return ST.hasClusters() &&
8569 case Intrinsic::amdgcn_cluster_id_z:
8570 return ST.hasClusters() &&
8573 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8574 return ST.hasClusters() &&
8577 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8578 return ST.hasClusters() &&
8581 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8582 return ST.hasClusters() &&
8585 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8586 return ST.hasClusters() &&
8588 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8589 return ST.hasClusters() &&
8592 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8593 return ST.hasClusters() &&
8596 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8597 return ST.hasClusters() &&
8600 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8601 return ST.hasClusters() &&
8605 case Intrinsic::amdgcn_wave_id:
8607 case Intrinsic::amdgcn_lds_kernel_id:
8610 case Intrinsic::amdgcn_dispatch_ptr:
8613 case Intrinsic::amdgcn_queue_ptr:
8616 case Intrinsic::amdgcn_implicit_buffer_ptr:
8619 case Intrinsic::amdgcn_dispatch_id:
8622 case Intrinsic::r600_read_ngroups_x:
8626 case Intrinsic::r600_read_ngroups_y:
8629 case Intrinsic::r600_read_ngroups_z:
8632 case Intrinsic::r600_read_local_size_x:
8635 case Intrinsic::r600_read_local_size_y:
8639 case Intrinsic::r600_read_local_size_z:
8642 case Intrinsic::amdgcn_fdiv_fast:
8644 case Intrinsic::amdgcn_is_shared:
8646 case Intrinsic::amdgcn_is_private:
8648 case Intrinsic::amdgcn_wavefrontsize: {
8649 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8650 MI.eraseFromParent();
8653 case Intrinsic::amdgcn_s_buffer_load:
8654 case Intrinsic::amdgcn_ptr_s_buffer_load:
8656 case Intrinsic::amdgcn_raw_buffer_store:
8657 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8658 case Intrinsic::amdgcn_struct_buffer_store:
8659 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8661 case Intrinsic::amdgcn_raw_buffer_store_format:
8662 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8663 case Intrinsic::amdgcn_struct_buffer_store_format:
8664 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8666 case Intrinsic::amdgcn_raw_tbuffer_store:
8667 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8668 case Intrinsic::amdgcn_struct_tbuffer_store:
8669 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8671 case Intrinsic::amdgcn_raw_buffer_load:
8672 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8673 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8674 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8675 case Intrinsic::amdgcn_struct_buffer_load:
8676 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8677 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8678 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8680 case Intrinsic::amdgcn_raw_buffer_load_format:
8681 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8682 case Intrinsic::amdgcn_struct_buffer_load_format:
8683 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8685 case Intrinsic::amdgcn_raw_tbuffer_load:
8686 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8687 case Intrinsic::amdgcn_struct_tbuffer_load:
8688 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8690 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8691 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8692 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8693 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8694 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8695 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8696 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8697 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8698 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8699 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8700 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8701 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8702 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8703 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8704 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8705 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8706 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8707 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8708 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8709 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8710 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8711 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8712 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8713 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8714 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8715 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8716 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8717 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8718 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8719 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8720 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8721 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8722 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8723 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8724 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8725 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8726 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8727 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8728 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8729 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8730 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8731 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8732 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8733 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8734 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8735 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8736 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8737 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8738 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8739 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8740 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8741 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8742 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8743 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8744 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8745 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8746 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8747 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8748 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8749 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8750 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8751 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8752 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8753 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8754 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8755 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8756 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8757 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8758 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8759 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8760 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8761 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8763 case Intrinsic::amdgcn_rsq_clamp:
8765 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8767 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8768 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8770 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8771 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8772 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8773 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8774 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8775 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8776 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8777 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8781 if (IndexArgTy != I64) {
8782 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8783 :
B.buildAnyExt(I64, Index);
8784 MI.getOperand(5).setReg(NewIndex.getReg(0));
8788 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8789 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8790 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8791 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8792 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8793 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8794 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8795 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8798 if (MRI.
getType(Index) != I32)
8799 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8802 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8803 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8804 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8805 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8806 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8807 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8808 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8809 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8810 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8812 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8816 if (IndexArgTy != IdxTy) {
8817 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8818 :
B.buildAnyExt(IdxTy, Index);
8819 MI.getOperand(7).setReg(NewIndex.getReg(0));
8824 case Intrinsic::amdgcn_fmed3: {
8830 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8831 MI.removeOperand(1);
8835 case Intrinsic::amdgcn_readlane:
8836 case Intrinsic::amdgcn_writelane:
8837 case Intrinsic::amdgcn_readfirstlane:
8838 case Intrinsic::amdgcn_permlane16:
8839 case Intrinsic::amdgcn_permlanex16:
8840 case Intrinsic::amdgcn_permlane64:
8841 case Intrinsic::amdgcn_set_inactive:
8842 case Intrinsic::amdgcn_set_inactive_chain_arg:
8843 case Intrinsic::amdgcn_mov_dpp8:
8844 case Intrinsic::amdgcn_update_dpp:
8845 case Intrinsic::amdgcn_permlane_bcast:
8846 case Intrinsic::amdgcn_permlane_up:
8847 case Intrinsic::amdgcn_permlane_down:
8848 case Intrinsic::amdgcn_permlane_xor:
8850 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8852 case Intrinsic::amdgcn_dead: {
8856 MI.eraseFromParent();
8859 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8860 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8861 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8862 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8863 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8864 MI.eraseFromParent();
8866 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8867 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8868 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8869 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8870 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8871 MI.eraseFromParent();
8873 case Intrinsic::amdgcn_av_load_b128:
8874 case Intrinsic::amdgcn_av_store_b128: {
8875 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8876 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8877 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8879 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8880 **
MI.memoperands_begin());
8881 MI.eraseFromParent();
8884 case Intrinsic::amdgcn_flat_load_monitor_b32:
8885 case Intrinsic::amdgcn_flat_load_monitor_b64:
8886 case Intrinsic::amdgcn_flat_load_monitor_b128:
8887 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8888 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8889 .add(
MI.getOperand(0))
8890 .add(
MI.getOperand(2))
8891 .addMemOperand(*
MI.memoperands_begin());
8892 MI.eraseFromParent();
8894 case Intrinsic::amdgcn_global_load_monitor_b32:
8895 case Intrinsic::amdgcn_global_load_monitor_b64:
8896 case Intrinsic::amdgcn_global_load_monitor_b128:
8897 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8898 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8899 .add(
MI.getOperand(0))
8900 .add(
MI.getOperand(2))
8901 .addMemOperand(*
MI.memoperands_begin());
8902 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
bool legalizeTrapHsa(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrap(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFPow(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
unsigned allocateBarrierGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
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
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.