37#include "llvm/IR/IntrinsicsAMDGPU.h"
38#include "llvm/IR/IntrinsicsR600.h"
40#define DEBUG_TYPE "amdgpu-legalinfo"
50 "amdgpu-global-isel-new-legality",
51 cl::desc(
"Use GlobalISel desired legality, rather than try to use"
52 "rules compatible with selection patterns"),
67 unsigned Bits = Ty.getSizeInBits();
77 const LLT Ty = Query.Types[TypeIdx];
83 return Ty.getNumElements() % 2 != 0 &&
84 EltSize > 1 && EltSize < 32 &&
85 Ty.getSizeInBits() % 32 != 0;
91 const LLT Ty = Query.Types[TypeIdx];
98 const LLT Ty = Query.Types[TypeIdx];
100 return EltTy.
getSizeInBits() == 16 && Ty.getNumElements() > 2;
106 const LLT Ty = Query.Types[TypeIdx];
108 return std::pair(TypeIdx,
115 const LLT Ty = Query.Types[TypeIdx];
117 unsigned Size = Ty.getSizeInBits();
118 unsigned Pieces = (
Size + 63) / 64;
119 unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
129 const LLT Ty = Query.Types[TypeIdx];
132 const int Size = Ty.getSizeInBits();
134 const int NextMul32 = (
Size + 31) / 32;
138 const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
146 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
147 return std::make_pair(TypeIdx,
LLT::scalar(MemSize));
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();
218 const LLT QueryTy = Query.Types[TypeIdx];
225 const LLT QueryTy = Query.Types[TypeIdx];
232 const LLT QueryTy = Query.Types[TypeIdx];
238 return ((ST.useRealTrue16Insts() &&
Size == 16) ||
Size % 32 == 0) &&
244 return EltSize == 16 || EltSize % 32 == 0;
248 const int EltSize = Ty.getElementType().getSizeInBits();
249 return EltSize == 32 || EltSize == 64 ||
250 (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
251 EltSize == 128 || EltSize == 256;
280 LLT Ty = Query.Types[TypeIdx];
288 const LLT QueryTy = Query.Types[TypeIdx];
373 if (Ty.isPointerOrPointerVector())
374 Ty = Ty.changeElementType(
LLT::scalar(Ty.getScalarSizeInBits()));
378 (ST.useRealTrue16Insts() && Ty ==
S16) ||
393 const LLT Ty = Query.Types[TypeIdx];
394 return !Ty.
isVector() && Ty.getSizeInBits() > 32 &&
395 Query.MMODescrs[0].MemoryTy.getSizeInBits() < Ty.getSizeInBits();
403 unsigned MemSize = Query.MMODescrs[0].MemoryTy.getSizeInBits();
413 bool IsLoad,
bool IsAtomic) {
417 return ST.hasFlatScratchEnabled() ? 128 : 32;
419 return ST.useDS128() ? 128 : 64;
430 return IsLoad ? 512 : 128;
435 return ST.hasMultiDwordFlatScratchAddressing() || IsAtomic ? 128 : 32;
444 const bool IsLoad = Query.
Opcode != AMDGPU::G_STORE;
446 unsigned RegSize = Ty.getSizeInBits();
449 unsigned AS = Query.
Types[1].getAddressSpace();
456 if (Ty.isVector() && MemSize !=
RegSize)
463 if (IsLoad && MemSize <
Size)
464 MemSize = std::max(MemSize,
Align);
484 if (!ST.hasDwordx3LoadStores())
497 if (AlignBits < MemSize) {
500 Align(AlignBits / 8)))
530 const unsigned Size = Ty.getSizeInBits();
531 if (Ty.isPointerVector())
541 unsigned EltSize = Ty.getScalarSizeInBits();
542 return EltSize != 32 && EltSize != 64;
556 const unsigned Size = Ty.getSizeInBits();
557 if (
Size != MemSizeInBits)
558 return Size <= 32 && Ty.isVector();
564 return Ty.isVector() && (!MemTy.
isVector() || MemTy == Ty) &&
573 uint64_t AlignInBits,
unsigned AddrSpace,
583 if (SizeInBits == 96 && ST.hasDwordx3LoadStores())
594 if (AlignInBits < RoundedSize)
601 RoundedSize, AddrSpace,
Align(AlignInBits / 8),
613 Query.
Types[1].getAddressSpace(), Opcode);
633 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
637 std::array<Register, 4> VectorElems;
638 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
639 for (
unsigned I = 0;
I < NumParts; ++
I)
641 B.buildExtractVectorElementConstant(
S32, VectorReg,
I).getReg(0);
642 B.buildMergeValues(MO, VectorElems);
647 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
648 auto Scalar =
B.buildBitcast(ScalarTy, BitcastReg);
649 B.buildIntToPtr(MO, Scalar);
669 const unsigned NumParts =
PointerTy.getSizeInBits() / 32;
670 auto Unmerged =
B.buildUnmerge(
LLT::scalar(32), Pointer);
671 for (
unsigned I = 0;
I < NumParts; ++
I)
673 return B.buildBuildVector(VectorTy, PointerParts).getReg(0);
675 Register Scalar =
B.buildPtrToInt(ScalarTy, Pointer).getReg(0);
676 return B.buildBitcast(VectorTy, Scalar).getReg(0);
695 auto GetAddrSpacePtr = [&TM](
unsigned AS) {
708 const LLT BufferStridedPtr =
711 const LLT CodePtr = FlatPtr;
713 const std::initializer_list<LLT> AddrSpaces64 = {
714 GlobalPtr, ConstantPtr, FlatPtr
717 const std::initializer_list<LLT> AddrSpaces32 = {
718 LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
721 const std::initializer_list<LLT> AddrSpaces128 = {RsrcPtr};
723 const std::initializer_list<LLT> FPTypesBase = {
727 const std::initializer_list<LLT> FPTypes16 = {
731 const std::initializer_list<LLT> FPTypesPK16 = {
735 const std::initializer_list<LLT> FPTypesPK16_64 = {
S32,
S64,
S16,
V2S16,
738 const LLT MinScalarFPTy = ST.has16BitInsts() ?
S16 :
S32;
761 if (ST.hasVOP3PInsts() && ST.hasAddNoCarryInsts() && ST.hasIntClamp()) {
763 if (ST.hasPackedU64Ops()) {
766 .clampMaxNumElementsStrict(0,
S16, 2)
772 }
else if (ST.hasScalarAddSub64()) {
775 .clampMaxNumElementsStrict(0,
S16, 2)
783 .clampMaxNumElementsStrict(0,
S16, 2)
790 if (ST.hasScalarSMulU64()) {
793 .clampMaxNumElementsStrict(0,
S16, 2)
801 .clampMaxNumElementsStrict(0,
S16, 2)
811 .minScalarOrElt(0,
S16)
816 }
else if (ST.has16BitInsts()) {
850 .widenScalarToNextMultipleOf(0, 32)
860 if (ST.hasMad64_32())
865 if (ST.hasIntClamp()) {
888 {G_SDIV, G_UDIV, G_SREM, G_UREM, G_SDIVREM, G_UDIVREM})
898 if (ST.hasVOP3PInsts()) {
900 .clampMaxNumElements(0,
S8, 2)
921 {G_UADDO, G_USUBO, G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
933 LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
940 .clampScalar(0,
S16,
S64);
975 { G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE,
976 G_STRICT_FADD, G_STRICT_FMUL, G_STRICT_FMA})
983 if (ST.has16BitInsts()) {
984 if (ST.hasVOP3PInsts())
987 FPOpActions.legalFor({
S16});
989 TrigActions.customFor({
S16});
990 FDIVActions.customFor({
S16});
993 if (ST.hasPackedFP32Ops()) {
994 FPOpActions.legalFor({
V2S32});
995 FPOpActions.clampMaxNumElementsStrict(0,
S32, 2);
998 if (ST.hasPackedFP64Ops()) {
999 FPOpActions.legalFor({
V2S64});
1000 FPOpActions.clampMaxNumElementsStrict(0,
S64, 2);
1003 if (ST.hasPackedFP64Ops()) {
1004 FPOpActions.legalFor({
V2S64});
1005 FPOpActions.clampMaxNumElementsStrict(0,
S64, 2);
1008 auto &MinNumMaxNumIeee =
1011 if (ST.hasVOP3PInsts()) {
1012 MinNumMaxNumIeee.legalFor(FPTypesPK16)
1014 .clampMaxNumElements(0,
S16, 2)
1015 .clampScalar(0,
S16,
S64)
1017 }
else if (ST.has16BitInsts()) {
1018 MinNumMaxNumIeee.legalFor(FPTypes16).clampScalar(0,
S16,
S64).scalarize(0);
1020 MinNumMaxNumIeee.legalFor(FPTypesBase)
1021 .clampScalar(0,
S32,
S64)
1026 {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM});
1028 if (ST.hasPackedFP64Ops()) {
1029 MinNumMaxNum.customFor(FPTypesPK16_64)
1031 .clampMaxNumElements(0,
S16, 2)
1032 .clampMaxNumElements(0,
S64, 2)
1033 .clampScalar(0,
S16,
S64)
1035 }
else if (ST.hasVOP3PInsts()) {
1036 MinNumMaxNum.customFor(FPTypesPK16)
1038 .clampMaxNumElements(0,
S16, 2)
1039 .clampScalar(0,
S16,
S64)
1041 }
else if (ST.has16BitInsts()) {
1042 MinNumMaxNum.customFor(FPTypes16)
1043 .clampScalar(0,
S16,
S64)
1046 MinNumMaxNum.customFor(FPTypesBase)
1047 .clampScalar(0,
S32,
S64)
1051 if (ST.hasVOP3PInsts())
1068 .
legalFor(ST.hasPackedFP32Ops(), {V2S32})
1070 if (ST.hasPackedFP32Ops())
1074 if (ST.has16BitInsts()) {
1108 if (ST.hasFractBug()) {
1142 if (ST.hasCvtPkF16F32Inst()) {
1144 .clampMaxNumElements(0,
S16, 2);
1148 FPTruncActions.scalarize(0).lower();
1156 if (ST.has16BitInsts()) {
1170 if (ST.hasPackedFP32Ops())
1180 if (ST.hasMadF16() && ST.hasMadMacF32Insts())
1181 FMad.customFor({
S32,
S16});
1182 else if (ST.hasMadMacF32Insts())
1183 FMad.customFor({
S32});
1184 else if (ST.hasMadF16())
1185 FMad.customFor({
S16});
1190 if (ST.has16BitInsts()) {
1193 FRem.minScalar(0,
S32)
1202 .clampMaxNumElements(0,
S16, 2)
1222 if (ST.has16BitInsts())
1234 if (ST.has16BitInsts())
1247 .legalFor(ST.has16BitInsts(), {{S16, S16}})
1248 .legalFor(ST.hasVCvtPkIU16F32(), {{V2S16, V2S32}})
1252 if (
ST.has16BitInsts())
1255 if (
ST.hasVCvtPkIU16F32())
1265 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
1266 .clampScalar(0,
S16,
S64)
1270 getActionDefinitionsBuilder(G_INTRINSIC_FPTRUNC_ROUND)
1276 getActionDefinitionsBuilder({G_INTRINSIC_ROUND, G_FRINT, G_FNEARBYINT})
1280 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
1281 .clampScalar(0,
S16,
S64)
1285 if (
ST.has16BitInsts()) {
1286 getActionDefinitionsBuilder(
1287 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1289 .clampScalar(0,
S16,
S64)
1292 getActionDefinitionsBuilder(
1293 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1295 .clampScalar(0,
S32,
S64)
1298 getActionDefinitionsBuilder(
1299 {G_INTRINSIC_TRUNC, G_FCEIL, G_INTRINSIC_ROUNDEVEN})
1302 .clampScalar(0,
S32,
S64)
1306 getActionDefinitionsBuilder(G_PTR_ADD)
1312 getActionDefinitionsBuilder(G_PTRMASK)
1314 .scalarSameSizeAs(1, 0)
1318 getActionDefinitionsBuilder(G_ICMP)
1330 {
S1}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
1331 .legalForCartesianProduct(
1332 {
S32}, {
S32,
S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
1333 if (
ST.has16BitInsts()) {
1334 CmpBuilder.legalFor({{
S1,
S16}});
1345 {
S1},
ST.has16BitInsts() ? FPTypes16 : FPTypesBase);
1347 if (
ST.hasSALUFloatInsts())
1356 auto &ExpOps = getActionDefinitionsBuilder(G_FPOW);
1357 if (
ST.has16BitInsts())
1358 ExpOps.customFor({{
S32}, {
S16}});
1360 ExpOps.customFor({
S32});
1361 ExpOps.clampScalar(0, MinScalarFPTy,
S32)
1364 getActionDefinitionsBuilder(G_FPOWI)
1365 .clampScalar(0, MinScalarFPTy,
S32)
1368 getActionDefinitionsBuilder(G_FLOG2)
1369 .legalFor(
ST.has16BitInsts(), {S16})
1374 getActionDefinitionsBuilder(G_FEXP2)
1375 .legalFor(
ST.has16BitInsts(), {S16})
1381 getActionDefinitionsBuilder({G_FLOG, G_FLOG10, G_FEXP, G_FEXP10});
1383 LogOps.clampScalar(0, MinScalarFPTy,
S32)
1387 getActionDefinitionsBuilder(G_CTPOP)
1389 .clampScalar(0,
S32,
S32)
1390 .widenScalarToNextPow2(1, 32)
1391 .clampScalar(1,
S32,
S64)
1393 .widenScalarToNextPow2(0, 32);
1396 if (
ST.has16BitInsts())
1397 getActionDefinitionsBuilder(G_IS_FPCLASS)
1398 .legalForCartesianProduct({
S1}, FPTypes16)
1399 .widenScalarToNextPow2(1)
1403 getActionDefinitionsBuilder(G_IS_FPCLASS)
1404 .legalForCartesianProduct({
S1}, FPTypesBase)
1405 .lowerFor({
S1,
S16})
1406 .widenScalarToNextPow2(1)
1413 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ})
1415 .clampScalar(0,
S32,
S32)
1416 .clampScalar(1,
S32,
S64)
1417 .widenScalarToNextPow2(0, 32)
1418 .widenScalarToNextPow2(1, 32)
1422 getActionDefinitionsBuilder(G_CTLZ_ZERO_POISON)
1425 .clampScalar(0,
S32,
S32)
1426 .clampScalar(1,
S32,
S64)
1428 .widenScalarToNextPow2(0, 32)
1429 .widenScalarToNextPow2(1, 32);
1431 getActionDefinitionsBuilder(G_CTTZ_ZERO_POISON)
1433 .clampScalar(0,
S32,
S32)
1434 .clampScalar(1,
S32,
S64)
1436 .widenScalarToNextPow2(0, 32)
1437 .widenScalarToNextPow2(1, 32);
1439 getActionDefinitionsBuilder(G_CTLS)
1442 .clampScalar(0,
S32,
S32)
1443 .clampScalar(1,
S32,
S32);
1447 getActionDefinitionsBuilder(G_BITREVERSE)
1449 .clampScalar(0,
S32,
S64)
1451 .widenScalarToNextPow2(0);
1453 if (
ST.has16BitInsts()) {
1454 getActionDefinitionsBuilder(G_BSWAP)
1456 .clampMaxNumElementsStrict(0,
S16, 2)
1459 .widenScalarToNextPow2(0)
1460 .clampScalar(0,
S16,
S32)
1463 if (
ST.hasVOP3PInsts()) {
1464 getActionDefinitionsBuilder(G_ABS)
1466 .clampMaxNumElements(0,
S16, 2)
1468 .widenScalarToNextPow2(0)
1471 if (
ST.hasMinMaxI64Insts()) {
1472 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1474 .clampMaxNumElements(0,
S16, 2)
1476 .widenScalarToNextPow2(0)
1480 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1482 .clampMaxNumElements(0,
S16, 2)
1484 .widenScalarToNextPow2(0)
1489 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1491 .widenScalarToNextPow2(0)
1498 getActionDefinitionsBuilder(G_BSWAP)
1503 .widenScalarToNextPow2(0)
1508 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
1511 .widenScalarToNextPow2(0)
1516 getActionDefinitionsBuilder(G_INTTOPTR)
1518 .legalForCartesianProduct(AddrSpaces64, {
S64})
1519 .legalForCartesianProduct(AddrSpaces32, {
S32})
1532 getActionDefinitionsBuilder(G_PTRTOINT)
1534 .legalForCartesianProduct(AddrSpaces64, {
S64})
1535 .legalForCartesianProduct(AddrSpaces32, {
S32})
1548 getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
1552 const auto needToSplitMemOp = [=](
const LegalityQuery &Query,
1553 bool IsLoad) ->
bool {
1557 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1571 unsigned NumRegs = (MemSize + 31) / 32;
1573 if (!
ST.hasDwordx3LoadStores())
1584 unsigned GlobalAlign32 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 32;
1585 unsigned GlobalAlign16 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 16;
1586 unsigned GlobalAlign8 =
ST.hasUnalignedBufferAccessEnabled() ? 0 : 8;
1592 for (
unsigned Op : {G_LOAD, G_STORE}) {
1593 const bool IsStore =
Op == G_STORE;
1595 auto &Actions = getActionDefinitionsBuilder(
Op);
1598 Actions.legalForTypesWithMemDesc({{
S32, GlobalPtr,
S32, GlobalAlign32},
1601 {
S64, GlobalPtr,
S64, GlobalAlign32},
1604 {
S32, GlobalPtr,
S8, GlobalAlign8},
1605 {
S32, GlobalPtr,
S16, GlobalAlign16},
1607 {
S32, LocalPtr,
S32, 32},
1608 {
S64, LocalPtr,
S64, 32},
1610 {
S32, LocalPtr,
S8, 8},
1611 {
S32, LocalPtr,
S16, 16},
1614 {
S32, PrivatePtr,
S32, 32},
1615 {
S32, PrivatePtr,
S8, 8},
1616 {
S32, PrivatePtr,
S16, 16},
1619 {
S32, ConstantPtr,
S32, GlobalAlign32},
1622 {
S64, ConstantPtr,
S64, GlobalAlign32},
1623 {
V2S32, ConstantPtr,
V2S32, GlobalAlign32}});
1625 Actions.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1626 {{S16, GlobalPtr, S8, GlobalAlign8},
1627 {S16, GlobalPtr, S16, GlobalAlign16},
1628 {S16, LocalPtr, S8, 8},
1629 {S16, LocalPtr, S16, 16},
1630 {S16, PrivatePtr, S8, 8},
1631 {S16, PrivatePtr, S16, 16}});
1641 Actions.unsupportedIf(
1642 typeInSet(1, {BufferFatPtr, BufferStridedPtr, RsrcPtr}));
1656 Actions.customIf(
typeIs(1, Constant32Ptr));
1682 return !Query.
Types[0].isVector() &&
1683 needToSplitMemOp(Query,
Op == G_LOAD);
1685 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1690 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1693 if (DstSize > MemSize)
1699 if (MemSize > MaxSize)
1707 return Query.
Types[0].isVector() &&
1708 needToSplitMemOp(Query,
Op == G_LOAD);
1710 [=](
const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
1724 unsigned MemSize = Query.
MMODescrs[0].MemoryTy.getSizeInBits();
1725 if (MemSize > MaxSize) {
1729 if (MaxSize % EltSize == 0) {
1735 unsigned NumPieces = MemSize / MaxSize;
1739 if (NumPieces == 1 || NumPieces >= NumElts ||
1740 NumElts % NumPieces != 0)
1741 return std::pair(0, EltTy);
1749 return std::pair(0, EltTy);
1764 return std::pair(0, EltTy);
1769 .widenScalarToNextPow2(0)
1776 getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
1777 .legalForTypesWithMemDesc({{
S32, GlobalPtr,
S8, 8},
1778 {
S32, GlobalPtr,
S16, 2 * 8},
1779 {
S32, LocalPtr,
S8, 8},
1780 {
S32, LocalPtr,
S16, 16},
1781 {
S32, PrivatePtr,
S8, 8},
1782 {
S32, PrivatePtr,
S16, 16},
1783 {
S32, ConstantPtr,
S8, 8},
1784 {
S32, ConstantPtr,
S16, 2 * 8}})
1785 .legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1786 {{S16, GlobalPtr, S8, GlobalAlign8},
1787 {S16, LocalPtr, S8, GlobalAlign8},
1788 {S16, PrivatePtr, S8, GlobalAlign8},
1789 {S16, ConstantPtr, S8, GlobalAlign8}})
1794 if (
ST.hasFlatAddressSpace()) {
1795 ExtLoads.legalForTypesWithMemDesc(
1796 {{
S32, FlatPtr,
S8, 8}, {
S32, FlatPtr,
S16, 16}});
1798 ExtLoads.legalForTypesWithMemDesc(
ST.useRealTrue16Insts(),
1799 {{S16, FlatPtr, S8, GlobalAlign8}});
1807 ExtLoads.customIf(
typeIs(1, Constant32Ptr));
1809 ExtLoads.narrowScalarIf(
1816 ExtLoads.clampScalar(0,
S32,
S32)
1817 .widenScalarToNextPow2(0)
1820 auto &Atomics = getActionDefinitionsBuilder(
1821 {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
1822 G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
1823 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
1824 G_ATOMICRMW_UMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
1825 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr},
1826 {
S64, GlobalPtr}, {
S64, LocalPtr},
1827 {
S32, RegionPtr}, {
S64, RegionPtr}});
1828 if (
ST.hasFlatAddressSpace()) {
1829 Atomics.legalFor({{
S32, FlatPtr}, {
S64, FlatPtr}});
1833 getActionDefinitionsBuilder({G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT})
1834 .legalFor({{
S32, GlobalPtr}, {
S32, LocalPtr}, {
S32, RegionPtr}});
1835 if (
ST.hasFlatAddressSpace()) {
1836 Atomics32.legalFor({{
S32, FlatPtr}});
1840 auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD);
1841 if (
ST.hasLDSFPAtomicAddF32()) {
1842 Atomic.legalFor({{
S32, LocalPtr}, {
S32, RegionPtr}});
1843 if (
ST.hasLdsAtomicAddF64())
1844 Atomic.legalFor({{
S64, LocalPtr}});
1845 if (
ST.hasAtomicDsPkAdd16Insts())
1846 Atomic.legalFor({{
V2F16, LocalPtr}, {
V2BF16, LocalPtr}});
1848 if (
ST.hasAtomicFaddInsts())
1849 Atomic.legalFor({{
S32, GlobalPtr}});
1850 if (
ST.hasFlatAtomicFaddF32Inst())
1851 Atomic.legalFor({{
S32, FlatPtr}});
1853 if (
ST.hasGFX90AInsts() ||
ST.hasGFX1250Insts()) {
1864 if (
ST.hasAtomicBufferGlobalPkAddF16NoRtnInsts() ||
1865 ST.hasAtomicBufferGlobalPkAddF16Insts())
1866 Atomic.legalFor({{
V2F16, GlobalPtr}, {
V2F16, BufferFatPtr}});
1867 if (
ST.hasAtomicGlobalPkAddBF16Inst())
1868 Atomic.legalFor({{
V2BF16, GlobalPtr}});
1869 if (
ST.hasAtomicFlatPkAdd16Insts())
1870 Atomic.legalFor({{
V2F16, FlatPtr}, {
V2BF16, FlatPtr}});
1875 auto &AtomicFMinFMax =
1876 getActionDefinitionsBuilder({G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
1877 .legalFor({{
F32, LocalPtr}, {
F64, LocalPtr}});
1879 if (
ST.hasAtomicFMinFMaxF32GlobalInsts())
1880 AtomicFMinFMax.legalFor({{
F32, GlobalPtr},{
F32, BufferFatPtr}});
1881 if (
ST.hasAtomicFMinFMaxF64GlobalInsts())
1882 AtomicFMinFMax.legalFor({{
F64, GlobalPtr}, {
F64, BufferFatPtr}});
1883 if (
ST.hasAtomicFMinFMaxF32FlatInsts())
1884 AtomicFMinFMax.legalFor({
F32, FlatPtr});
1885 if (
ST.hasAtomicFMinFMaxF64FlatInsts())
1886 AtomicFMinFMax.legalFor({
F64, FlatPtr});
1890 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1891 .customFor({{
S32, GlobalPtr}, {
S64, GlobalPtr},
1892 {
S32, FlatPtr}, {
S64, FlatPtr}})
1893 .legalFor({{
S32, LocalPtr}, {
S64, LocalPtr},
1894 {
S32, RegionPtr}, {
S64, RegionPtr}});
1898 getActionDefinitionsBuilder(G_SELECT)
1900 LocalPtr, FlatPtr, PrivatePtr,
1904 .clampScalar(0,
S16,
S64)
1908 .clampMaxNumElements(0,
S32, 2)
1909 .clampMaxNumElements(0, LocalPtr, 2)
1910 .clampMaxNumElements(0, PrivatePtr, 2)
1912 .widenScalarToNextPow2(0)
1917 auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
1919 if (
ST.has16BitInsts()) {
1920 if (
ST.hasVOP3PInsts()) {
1922 .clampMaxNumElements(0,
S16, 2);
1924 Shifts.legalFor({{
S16,
S16}});
1927 Shifts.widenScalarIf(
1932 const LLT AmountTy = Query.
Types[1];
1937 Shifts.clampScalar(1,
S32,
S32);
1938 Shifts.widenScalarToNextPow2(0, 16);
1939 Shifts.clampScalar(0,
S16,
S64);
1941 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1949 Shifts.clampScalar(1,
S32,
S32);
1950 Shifts.widenScalarToNextPow2(0, 32);
1951 Shifts.clampScalar(0,
S32,
S64);
1953 getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT})
1958 Shifts.scalarize(0);
1960 for (
unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
1961 unsigned VecTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
1962 unsigned EltTypeIdx =
Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
1963 unsigned IdxTypeIdx = 2;
1965 getActionDefinitionsBuilder(
Op)
1967 const LLT EltTy = Query.
Types[EltTypeIdx];
1968 const LLT VecTy = Query.
Types[VecTypeIdx];
1969 const LLT IdxTy = Query.
Types[IdxTypeIdx];
1971 const bool isLegalVecType =
1981 return (EltSize == 32 || EltSize == 64) &&
1997 const LLT EltTy = Query.
Types[EltTypeIdx];
1998 const LLT VecTy = Query.
Types[VecTypeIdx];
2002 const unsigned TargetEltSize =
2003 DstEltSize % 64 == 0 ? 64 : 32;
2004 return std::pair(VecTypeIdx,
2008 .clampScalar(EltTypeIdx,
S32,
S64)
2009 .clampScalar(VecTypeIdx,
S32,
S64)
2010 .clampScalar(IdxTypeIdx,
S32,
S32)
2011 .clampMaxNumElements(VecTypeIdx,
S32, 32)
2020 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
2022 const LLT &EltTy = Query.
Types[1].getElementType();
2023 return Query.
Types[0] != EltTy;
2026 for (
unsigned Op : {G_EXTRACT, G_INSERT}) {
2027 unsigned BigTyIdx =
Op == G_EXTRACT ? 1 : 0;
2028 unsigned LitTyIdx =
Op == G_EXTRACT ? 0 : 1;
2029 getActionDefinitionsBuilder(
Op)
2032 const LLT BigTy = Query.
Types[BigTyIdx];
2038 const LLT LitTy = Query.
Types[LitTyIdx];
2043 .widenScalarToNextPow2(BigTyIdx, 32)
2051 const LLT BigTy = Query.
Types[BigTyIdx];
2052 const LLT LitTy = Query.
Types[LitTyIdx];
2060 getActionDefinitionsBuilder(G_BUILD_VECTOR)
2069 if (
ST.hasScalarPackInsts()) {
2072 .minScalarOrElt(0,
S16)
2075 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2079 BuildVector.customFor({
V2S16,
S16});
2080 BuildVector.minScalarOrElt(0,
S32);
2082 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
2090 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
2092 .clampMaxNumElements(0,
S32, 32)
2093 .clampMaxNumElements(1,
S16, 2)
2094 .clampMaxNumElements(0,
S16, 64);
2096 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
2099 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
2100 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
2101 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
2103 auto notValidElt = [=](
const LegalityQuery &Query,
unsigned TypeIdx) {
2104 const LLT Ty = Query.
Types[TypeIdx];
2116 getActionDefinitionsBuilder(
Op)
2120 const LLT BigTy = Query.
Types[BigTyIdx];
2126 .widenScalarToNextPow2(LitTyIdx, 16)
2135 .clampScalar(LitTyIdx,
S32,
S512)
2136 .widenScalarToNextPow2(LitTyIdx, 32)
2140 return notValidElt(Query, LitTyIdx);
2145 return notValidElt(Query, BigTyIdx);
2150 if (
Op == G_MERGE_VALUES) {
2151 Builder.widenScalarIf(
2154 const LLT Ty = Query.
Types[LitTyIdx];
2160 Builder.widenScalarIf(
2162 const LLT Ty = Query.
Types[BigTyIdx];
2168 const LLT &Ty = Query.
Types[BigTyIdx];
2170 if (NewSizeInBits >= 256) {
2172 if (RoundedTo < NewSizeInBits)
2173 NewSizeInBits = RoundedTo;
2175 return std::pair(BigTyIdx,
LLT::scalar(NewSizeInBits));
2184 auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG)
2185 .legalFor({{
S32}, {
S64}})
2186 .clampScalar(0,
S32,
S64);
2188 if (
ST.hasVOP3PInsts()) {
2189 SextInReg.lowerFor({{
V2S16}})
2193 .clampMaxNumElementsStrict(0,
S16, 2);
2194 }
else if (
ST.has16BitInsts()) {
2195 SextInReg.lowerFor({{
S32}, {
S64}, {
S16}});
2199 SextInReg.lowerFor({{
S32}, {
S64}});
2204 .clampScalar(0,
S32,
S64)
2207 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
2211 auto &FSHRActionDefs = getActionDefinitionsBuilder(G_FSHR);
2212 FSHRActionDefs.legalFor({{
S32,
S32}})
2213 .clampMaxNumElementsStrict(0,
S16, 2);
2214 if (
ST.hasVOP3PInsts())
2216 FSHRActionDefs.scalarize(0).lower();
2218 if (
ST.hasVOP3PInsts()) {
2219 getActionDefinitionsBuilder(G_FSHL)
2221 .clampMaxNumElementsStrict(0,
S16, 2)
2225 getActionDefinitionsBuilder(G_FSHL)
2230 getActionDefinitionsBuilder(G_READCYCLECOUNTER)
2233 getActionDefinitionsBuilder(G_READSTEADYCOUNTER).legalFor({
S64});
2235 getActionDefinitionsBuilder(G_FENCE)
2238 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
2243 getActionDefinitionsBuilder({G_SBFX, G_UBFX})
2245 .clampScalar(1,
S32,
S32)
2246 .clampScalar(0,
S32,
S64)
2247 .widenScalarToNextPow2(0)
2250 getActionDefinitionsBuilder(
2254 G_ATOMIC_CMPXCHG_WITH_SUCCESS, G_ATOMICRMW_NAND, G_ATOMICRMW_FSUB,
2255 G_READ_REGISTER, G_WRITE_REGISTER,
2260 if (
ST.hasIEEEMinimumMaximumInsts()) {
2261 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2262 .legalFor(FPTypesPK16)
2263 .clampMaxNumElements(0,
S16, 2)
2265 }
else if (
ST.hasVOP3PInsts()) {
2266 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2268 .clampMaxNumElementsStrict(0,
S16, 2)
2272 getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
2274 .clampScalar(0,
S32,
S64)
2278 getActionDefinitionsBuilder(
2279 {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
2282 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
2284 getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
2285 G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
2286 G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
2289 getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
2291 getActionDefinitionsBuilder(
2292 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
2293 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
2294 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
2295 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
2300 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS,
2301 G_INTRINSIC_CONVERGENT,
2302 G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS})
2314 switch (
MI.getOpcode()) {
2315 case TargetOpcode::G_ADDRSPACE_CAST:
2317 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
2319 case TargetOpcode::G_FCEIL:
2321 case TargetOpcode::G_FREM:
2323 case TargetOpcode::G_INTRINSIC_TRUNC:
2325 case TargetOpcode::G_SITOFP:
2327 case TargetOpcode::G_UITOFP:
2329 case TargetOpcode::G_FPTOSI:
2331 case TargetOpcode::G_FPTOUI:
2333 case TargetOpcode::G_FMINNUM:
2334 case TargetOpcode::G_FMAXNUM:
2335 case TargetOpcode::G_FMINIMUMNUM:
2336 case TargetOpcode::G_FMAXIMUMNUM:
2338 case TargetOpcode::G_EXTRACT:
2340 case TargetOpcode::G_INSERT:
2342 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
2344 case TargetOpcode::G_INSERT_VECTOR_ELT:
2346 case TargetOpcode::G_FSIN:
2347 case TargetOpcode::G_FCOS:
2349 case TargetOpcode::G_GLOBAL_VALUE:
2351 case TargetOpcode::G_LOAD:
2352 case TargetOpcode::G_SEXTLOAD:
2353 case TargetOpcode::G_ZEXTLOAD:
2355 case TargetOpcode::G_STORE:
2357 case TargetOpcode::G_FMAD:
2359 case TargetOpcode::G_FDIV:
2361 case TargetOpcode::G_FFREXP:
2363 case TargetOpcode::G_FSQRT:
2365 case TargetOpcode::G_UDIV:
2366 case TargetOpcode::G_UREM:
2367 case TargetOpcode::G_UDIVREM:
2369 case TargetOpcode::G_SDIV:
2370 case TargetOpcode::G_SREM:
2371 case TargetOpcode::G_SDIVREM:
2373 case TargetOpcode::G_ATOMIC_CMPXCHG:
2375 case TargetOpcode::G_FLOG2:
2377 case TargetOpcode::G_FLOG:
2378 case TargetOpcode::G_FLOG10:
2380 case TargetOpcode::G_FEXP2:
2382 case TargetOpcode::G_FEXP:
2383 case TargetOpcode::G_FEXP10:
2385 case TargetOpcode::G_FPOW:
2387 case TargetOpcode::G_FFLOOR:
2389 case TargetOpcode::G_BUILD_VECTOR:
2390 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
2392 case TargetOpcode::G_MUL:
2394 case TargetOpcode::G_CTLZ:
2395 case TargetOpcode::G_CTTZ:
2397 case TargetOpcode::G_CTLS:
2399 case TargetOpcode::G_CTLZ_ZERO_POISON:
2401 case TargetOpcode::G_STACKSAVE:
2403 case TargetOpcode::G_GET_FPENV:
2405 case TargetOpcode::G_SET_FPENV:
2407 case TargetOpcode::G_TRAP:
2409 case TargetOpcode::G_DEBUGTRAP:
2429 if (ST.hasApertureRegs()) {
2434 ? AMDGPU::SRC_SHARED_BASE
2435 : AMDGPU::SRC_PRIVATE_BASE;
2436 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
2437 !ST.hasGloballyAddressableScratch()) &&
2438 "Cannot use src_private_base with globally addressable scratch!");
2441 B.buildCopy({Dst}, {
Register(ApertureRegNo)});
2442 return B.buildUnmerge(I32, Dst).getReg(1);
2457 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
2473 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
2476 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2498 B.buildObjectPtrOffset(
2501 return B.buildLoad(I32, LoadAddr, *MMO).getReg(0);
2509 switch (Def->getOpcode()) {
2510 case AMDGPU::G_FRAME_INDEX:
2511 case AMDGPU::G_GLOBAL_VALUE:
2512 case AMDGPU::G_BLOCK_ADDR:
2514 case AMDGPU::G_CONSTANT: {
2515 const ConstantInt *CI = Def->getOperand(1).getCImm();
2532 assert(
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2534 Intrinsic::amdgcn_addrspacecast_nonnull));
2540 :
MI.getOperand(1).getReg();
2544 unsigned SrcAS = SrcTy.getAddressSpace();
2554 MI.setDesc(
B.getTII().get(TargetOpcode::G_BITCAST));
2561 auto castFlatToLocalOrPrivate = [&](
const DstOp &Dst) ->
Register {
2563 ST.hasGloballyAddressableScratch()) {
2566 Register SrcLo =
B.buildExtract(I32, Src, 0).getReg(0);
2568 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
2569 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)})
2571 MRI.
setRegClass(FlatScratchBaseLo, &AMDGPU::SReg_32RegClass);
2572 Register Sub =
B.buildSub(I32, SrcLo, FlatScratchBaseLo).getReg(0);
2573 return B.buildIntToPtr(Dst,
Sub).getReg(0);
2577 return B.buildExtract(Dst, Src, 0).getReg(0);
2583 castFlatToLocalOrPrivate(Dst);
2584 MI.eraseFromParent();
2590 auto SegmentNull =
B.buildConstant(DstTy, NullVal);
2591 auto FlatNull =
B.buildConstant(SrcTy, 0);
2594 auto PtrLo32 = castFlatToLocalOrPrivate(DstTy);
2598 B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
2600 MI.eraseFromParent();
2607 auto castLocalOrPrivateToFlat = [&](
const DstOp &Dst) ->
Register {
2610 Register SrcAsInt =
B.buildPtrToInt(I32, Src).getReg(0);
2613 ST.hasGloballyAddressableScratch()) {
2617 Register ThreadID =
B.buildConstant(I32, 0).getReg(0);
2618 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_lo, {I32})
2622 if (ST.isWave64()) {
2623 ThreadID =
B.buildIntrinsic(Intrinsic::amdgcn_mbcnt_hi, {I32})
2629 B.buildConstant(I32, 57 - 32 - ST.getWavefrontSizeLog2()).getReg(0);
2630 Register SrcHi =
B.buildShl(I32, ThreadID, ShAmt).getReg(0);
2632 B.buildMergeLikeInstr(DstTy, {SrcAsInt, SrcHi}).
getReg(0);
2636 B.buildInstr(AMDGPU::S_MOV_B64, {I64},
2637 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE)})
2639 MRI.
setRegClass(FlatScratchBase, &AMDGPU::SReg_64RegClass);
2640 return B.buildPtrAdd(Dst, CvtPtr, FlatScratchBase).getReg(0);
2649 return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).
getReg(0);
2655 castLocalOrPrivateToFlat(Dst);
2656 MI.eraseFromParent();
2660 Register BuildPtr = castLocalOrPrivateToFlat(DstTy);
2667 SegmentNull.getReg(0));
2669 B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
2671 MI.eraseFromParent();
2676 SrcTy.getSizeInBits() == 64) {
2678 B.buildExtract(Dst, Src, 0);
2679 MI.eraseFromParent();
2686 uint32_t AddrHiVal = Info->get32BitAddressHighBits();
2687 auto PtrLo =
B.buildPtrToInt(I32, Src);
2688 if (AddrHiVal == 0) {
2689 auto Zext =
B.buildZExt(I64, PtrLo);
2690 B.buildIntToPtr(Dst, Zext);
2692 auto HighAddr =
B.buildConstant(I32, AddrHiVal);
2693 B.buildMergeLikeInstr(Dst, {PtrLo, HighAddr});
2696 MI.eraseFromParent();
2703 MI.eraseFromParent();
2712 assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
2717 auto C1 =
B.buildFConstant(Ty, C1Val);
2718 auto CopySign =
B.buildFCopysign(Ty, C1, Src);
2721 auto Tmp1 =
B.buildFAdd(Ty, Src, CopySign);
2722 auto Tmp2 =
B.buildFSub(Ty, Tmp1, CopySign);
2724 auto C2 =
B.buildFConstant(Ty, C2Val);
2725 auto Fabs =
B.buildFAbs(Ty, Src);
2728 B.buildSelect(
MI.getOperand(0).getReg(),
Cond, Src, Tmp2);
2729 MI.eraseFromParent();
2747 auto Trunc =
B.buildIntrinsicTrunc(
F64, Src);
2749 const auto Zero =
B.buildFConstant(
F64, 0.0);
2750 const auto One =
B.buildFConstant(
F64, 1.0);
2753 auto And =
B.buildAnd(
S1, Lt0, NeTrunc);
2754 auto Add =
B.buildSelect(
F64,
And, One, Zero);
2757 B.buildFAdd(
MI.getOperand(0).getReg(), Trunc,
Add);
2758 MI.eraseFromParent();
2766 Register Src0Reg =
MI.getOperand(1).getReg();
2767 Register Src1Reg =
MI.getOperand(2).getReg();
2768 auto Flags =
MI.getFlags();
2771 auto Div =
B.buildFDiv(Ty, Src0Reg, Src1Reg, Flags);
2772 auto Trunc =
B.buildIntrinsicTrunc(Ty, Div, Flags);
2773 auto Neg =
B.buildFNeg(Ty, Trunc, Flags);
2774 B.buildFMA(DstReg, Neg, Src1Reg, Src0Reg, Flags);
2775 MI.eraseFromParent();
2781 const unsigned FractBits = 52;
2782 const unsigned ExpBits = 11;
2785 auto Const0 =
B.buildConstant(I32, FractBits - 32);
2786 auto Const1 =
B.buildConstant(I32, ExpBits);
2788 auto ExpPart =
B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {I32})
2790 .addUse(Const0.getReg(0))
2791 .addUse(Const1.getReg(0));
2793 return B.buildSub(I32, ExpPart,
B.buildConstant(I32, 1023));
2806 auto SrcInt =
B.buildBitcast(I64, Src);
2809 auto Unmerge =
B.buildUnmerge({I32, I32}, SrcInt);
2816 const unsigned FractBits = 52;
2819 const auto SignBitMask =
B.buildConstant(I32, UINT32_C(1) << 31);
2820 auto SignBit =
B.buildAnd(I32,
Hi, SignBitMask);
2822 const auto FractMask =
B.buildConstant(I64, (UINT64_C(1) << FractBits) - 1);
2824 const auto Zero32 =
B.buildConstant(I32, 0);
2827 auto SignBit64 =
B.buildMergeLikeInstr(I64, {Zero32, SignBit});
2829 auto Shr =
B.buildAShr(I64, FractMask, Exp);
2830 auto Not =
B.buildNot(I64, Shr);
2831 auto Tmp0 =
B.buildAnd(I64, SrcInt, Not);
2832 auto FiftyOne =
B.buildConstant(I32, FractBits - 1);
2837 auto Tmp1 =
B.buildSelect(I64, ExpLt0, SignBit64, Tmp0);
2838 auto Res =
B.buildSelect(I64, ExpGt51, SrcInt, Tmp1);
2839 B.buildBitcast(
MI.getOperand(0).getReg(), Res);
2840 MI.eraseFromParent();
2858 auto Unmerge =
B.buildUnmerge({I32, I32}, Src);
2859 auto ThirtyTwo =
B.buildConstant(I32, 32);
2862 auto CvtHi =
Signed ?
B.buildSITOFP(
F64, Unmerge.getReg(1))
2863 :
B.buildUITOFP(
F64, Unmerge.getReg(1));
2865 auto CvtLo =
B.buildUITOFP(
F64, Unmerge.getReg(0));
2866 auto LdExp =
B.buildFLdexp(
F64, CvtHi, ThirtyTwo);
2869 B.buildFAdd(Dst, LdExp, CvtLo);
2870 MI.eraseFromParent();
2876 auto One =
B.buildConstant(I32, 1);
2880 auto ThirtyOne =
B.buildConstant(I32, 31);
2881 auto X =
B.buildXor(I32, Unmerge.getReg(0), Unmerge.getReg(1));
2882 auto OppositeSign =
B.buildAShr(I32,
X, ThirtyOne);
2883 auto MaxShAmt =
B.buildAdd(I32, ThirtyTwo, OppositeSign);
2884 auto LS =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32})
2885 .addUse(Unmerge.getReg(1));
2886 auto LS2 =
B.buildSub(I32, LS, One);
2887 ShAmt =
B.buildUMin(I32, LS2, MaxShAmt);
2889 ShAmt =
B.buildCTLZ(I32, Unmerge.getReg(1));
2890 auto Norm =
B.buildShl(I64, Src, ShAmt);
2891 auto Unmerge2 =
B.buildUnmerge({I32, I32}, Norm);
2892 auto Adjust =
B.buildUMin(I32, One, Unmerge2.getReg(0));
2893 auto Norm2 =
B.buildOr(I32, Unmerge2.getReg(1), Adjust);
2894 auto FVal =
Signed ?
B.buildSITOFP(
F32, Norm2) :
B.buildUITOFP(
F32, Norm2);
2895 auto Scale =
B.buildSub(I32, ThirtyTwo, ShAmt);
2896 B.buildFLdexp(Dst, FVal, Scale);
2897 MI.eraseFromParent();
2919 unsigned Flags =
MI.getFlags();
2930 auto Trunc =
B.buildIntrinsicTrunc(SrcLT, Src, Flags);
2938 auto SrcInt =
B.buildBitcast(I32, Src);
2939 Sign =
B.buildAShr(I32, SrcInt,
B.buildConstant(I32, 31));
2940 Trunc =
B.buildFAbs(
F32, Trunc, Flags);
2944 K0 =
B.buildFConstant(
2946 K1 =
B.buildFConstant(
2949 K0 =
B.buildFConstant(
2951 K1 =
B.buildFConstant(
2955 auto Mul =
B.buildFMul(SrcLT, Trunc, K0, Flags);
2956 auto FloorMul =
B.buildFFloor(SrcLT,
Mul, Flags);
2957 auto Fma =
B.buildFMA(SrcLT, FloorMul, K1, Trunc, Flags);
2959 auto Hi = (
Signed && SrcLT ==
F64) ?
B.buildFPTOSI(I32, FloorMul)
2960 :
B.buildFPTOUI(I32, FloorMul);
2961 auto Lo =
B.buildFPTOUI(I32, Fma);
2965 Sign =
B.buildMergeLikeInstr(I64, {Sign, Sign});
2967 B.buildSub(Dst,
B.buildXor(I64,
B.buildMergeLikeInstr(I64, {Lo, Hi}), Sign),
2970 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
2971 MI.eraseFromParent();
3003 unsigned StartIdx =
Offset / 32;
3007 if (DstCount == 1) {
3009 B.buildIntToPtr(DstReg, Unmerge.getReg(StartIdx));
3014 for (
unsigned I = 0;
I < DstCount; ++
I)
3015 MergeVec.
push_back(Unmerge.getReg(StartIdx +
I));
3016 B.buildMergeLikeInstr(DstReg, MergeVec);
3019 MI.eraseFromParent();
3029 Register InsertSrc =
MI.getOperand(2).getReg();
3038 if (
Offset % 32 != 0 || DstSize % 32 != 0 || InsertSize % 32 != 0)
3042 unsigned DstCount = DstSize / 32;
3043 unsigned InsertCount = InsertSize / 32;
3044 unsigned StartIdx =
Offset / 32;
3046 auto SrcUnmerge =
B.buildUnmerge(I32, SrcReg);
3049 for (
unsigned I = 0;
I < StartIdx; ++
I)
3052 if (InsertCount == 1) {
3056 InsertSrc =
B.buildPtrToInt(I32, InsertSrc).getReg(0);
3059 auto InsertUnmerge =
B.buildUnmerge(I32, InsertSrc);
3060 for (
unsigned I = 0;
I < InsertCount; ++
I)
3064 for (
unsigned I = StartIdx + InsertCount;
I < DstCount; ++
I)
3067 B.buildMergeLikeInstr(DstReg, MergeVec);
3069 MI.eraseFromParent();
3096 auto IntVec =
B.buildPtrToInt(IntVecTy, Vec);
3097 auto IntElt =
B.buildExtractVectorElement(IntTy, IntVec,
MI.getOperand(2));
3098 B.buildIntToPtr(Dst, IntElt);
3100 MI.eraseFromParent();
3107 std::optional<ValueAndVReg> MaybeIdxVal =
3111 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3114 auto Unmerge =
B.buildUnmerge(EltTy, Vec);
3115 B.buildCopy(Dst, Unmerge.getReg(IdxVal));
3120 MI.eraseFromParent();
3149 auto IntVecSource =
B.buildPtrToInt(IntVecTy, Vec);
3150 auto IntIns =
B.buildPtrToInt(IntTy, Ins);
3151 auto IntVecDest =
B.buildInsertVectorElement(IntVecTy, IntVecSource, IntIns,
3153 B.buildIntToPtr(Dst, IntVecDest);
3154 MI.eraseFromParent();
3161 std::optional<ValueAndVReg> MaybeIdxVal =
3166 const uint64_t IdxVal = MaybeIdxVal->Value.getZExtValue();
3169 if (IdxVal < NumElts) {
3171 for (
unsigned i = 0; i < NumElts; ++i)
3173 B.buildUnmerge(SrcRegs, Vec);
3175 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
3176 B.buildMergeLikeInstr(Dst, SrcRegs);
3181 MI.eraseFromParent();
3192 unsigned Flags =
MI.getFlags();
3196 if (ST.hasTrigReducedRange()) {
3197 auto MulVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
3198 TrigVal =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty})
3199 .addUse(MulVal.getReg(0))
3203 TrigVal =
B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
3206 Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
3210 MI.eraseFromParent();
3218 unsigned GAFlags)
const {
3247 B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
3249 if (ST.has64BitLiterals()) {
3253 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET64).addDef(PCReg);
3257 B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET).addDef(PCReg);
3266 if (!
B.getMRI()->getRegClassOrNull(PCReg))
3267 B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
3270 B.buildExtract(DstReg, PCReg, 0);
3280 if (RequiresHighHalf && ST.has64BitLiterals()) {
3282 MRI.
setRegClass(DstReg, &AMDGPU::SReg_64RegClass);
3283 B.buildInstr(AMDGPU::S_MOV_B64)
3298 MRI.
setRegClass(AddrLo, &AMDGPU::SReg_32RegClass);
3301 B.buildInstr(AMDGPU::S_MOV_B32)
3306 if (RequiresHighHalf) {
3308 "Must provide a 64-bit pointer type!");
3311 MRI.
setRegClass(AddrHi, &AMDGPU::SReg_32RegClass);
3313 B.buildInstr(AMDGPU::S_MOV_B32)
3324 MRI.
setRegClass(AddrDst, &AMDGPU::SReg_64RegClass);
3326 B.buildMergeValues(AddrDst, {AddrLo, AddrHi});
3330 if (AddrDst != DstReg)
3331 B.buildCast(DstReg, AddrDst);
3332 }
else if (AddrLo != DstReg) {
3335 B.buildCast(DstReg, AddrLo);
3344 unsigned AS = Ty.getAddressSpace();
3352 GV->
getName() !=
"llvm.amdgcn.module.lds" &&
3356 Fn,
"local memory global used by non-kernel function",
3365 B.buildUndef(DstReg);
3366 MI.eraseFromParent();
3390 auto Sz =
B.buildIntrinsic(Intrinsic::amdgcn_groupstaticsize, {I32});
3391 B.buildIntToPtr(DstReg, Sz);
3392 MI.eraseFromParent();
3398 MI.eraseFromParent();
3402 if (ST.isAmdPalOS() || ST.isMesa3DOS()) {
3404 MI.eraseFromParent();
3412 MI.eraseFromParent();
3418 MI.eraseFromParent();
3434 if (Ty.getSizeInBits() == 32) {
3436 auto Load =
B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
3437 B.buildExtract(DstReg, Load, 0);
3439 B.buildLoad(DstReg, GOTAddr, *GOTMMO);
3441 MI.eraseFromParent();
3464 auto Cast =
B.buildAddrSpaceCast(ConstPtr, PtrReg);
3466 MI.getOperand(1).setReg(Cast.getReg(0));
3471 if (
MI.getOpcode() != AMDGPU::G_LOAD)
3497 if (WideMemSize == ValSize) {
3503 MI.setMemRefs(MF, {WideMMO});
3509 if (ValSize > WideMemSize)
3516 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3517 B.buildTrunc(ValReg, WideLoad).getReg(0);
3524 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3525 B.buildExtract(ValReg, WideLoad, 0);
3529 WideLoad =
B.buildLoadFromOffset(WideTy, PtrReg, *MMO, 0).getReg(0);
3530 B.buildDeleteTrailingVectorElements(ValReg, WideLoad);
3534 MI.eraseFromParent();
3547 Register DataReg =
MI.getOperand(0).getReg();
3592 "this should not have been custom lowered");
3597 Register PackedVal =
B.buildBuildVector(VecTy, { NewVal, CmpVal }).
getReg(0);
3599 B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
3603 .setMemRefs(
MI.memoperands());
3605 MI.eraseFromParent();
3613 switch (
DefMI->getOpcode()) {
3614 case TargetOpcode::G_INTRINSIC: {
3616 case Intrinsic::amdgcn_frexp_mant:
3617 case Intrinsic::amdgcn_log:
3618 case Intrinsic::amdgcn_log_clamp:
3619 case Intrinsic::amdgcn_exp2:
3620 case Intrinsic::amdgcn_sqrt:
3628 case TargetOpcode::G_FSQRT:
3630 case TargetOpcode::G_FFREXP: {
3631 if (
DefMI->getOperand(0).getReg() == Src)
3635 case TargetOpcode::G_FPEXT: {
3656std::pair<Register, Register>
3658 unsigned Flags)
const {
3663 auto SmallestNormal =
B.buildFConstant(
3665 auto IsLtSmallestNormal =
3668 auto Scale32 =
B.buildFConstant(
F32, 0x1.0p+32);
3669 auto One =
B.buildFConstant(
F32, 1.0);
3671 B.buildSelect(
F32, IsLtSmallestNormal, Scale32, One, Flags);
3672 auto ScaledInput =
B.buildFMul(
F32, Src, ScaleFactor, Flags);
3674 return {ScaledInput.getReg(0), IsLtSmallestNormal.getReg(0)};
3687 LLT Ty =
B.getMRI()->getType(Dst);
3688 unsigned Flags =
MI.getFlags();
3693 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3694 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {
F32})
3695 .addUse(Ext.getReg(0))
3697 B.buildFPTrunc(Dst,
Log2, Flags);
3698 MI.eraseFromParent();
3706 B.buildIntrinsic(Intrinsic::amdgcn_log, {
MI.getOperand(0)})
3709 MI.eraseFromParent();
3713 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3714 .addUse(ScaledInput)
3717 auto ThirtyTwo =
B.buildFConstant(Ty, 32.0);
3718 auto Zero =
B.buildFConstant(Ty, 0.0);
3720 B.buildSelect(Ty, IsLtSmallestNormal, ThirtyTwo, Zero, Flags);
3721 B.buildFSub(Dst,
Log2, ResultOffset, Flags);
3723 MI.eraseFromParent();
3729 auto FMul =
B.buildFMul(Ty,
X,
Y, Flags);
3730 return B.buildFAdd(Ty,
FMul, Z, Flags).getReg(0);
3735 const bool IsLog10 =
MI.getOpcode() == TargetOpcode::G_FLOG10;
3736 assert(IsLog10 ||
MI.getOpcode() == TargetOpcode::G_FLOG);
3741 unsigned Flags =
MI.getFlags();
3754 auto PromoteSrc =
B.buildFPExt(
F32,
X);
3756 B.buildFPTrunc(Dst, LogVal);
3761 MI.eraseFromParent();
3770 B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty}).addUse(
X).setMIFlags(Flags);
3773 if (ST.hasFastFMAF32()) {
3775 const float c_log10 = 0x1.344134p-2f;
3776 const float cc_log10 = 0x1.09f79ep-26f;
3779 const float c_log = 0x1.62e42ep-1f;
3780 const float cc_log = 0x1.efa39ep-25f;
3782 auto C =
B.buildFConstant(Ty, IsLog10 ? c_log10 : c_log);
3783 auto CC =
B.buildFConstant(Ty, IsLog10 ? cc_log10 : cc_log);
3787 R =
B.buildFMul(Ty,
Y,
C, NewFlags).getReg(0);
3788 auto NegR =
B.buildFNeg(Ty, R, NewFlags);
3789 auto FMA0 =
B.buildFMA(Ty,
Y,
C, NegR, NewFlags);
3790 auto FMA1 =
B.buildFMA(Ty,
Y, CC, FMA0, NewFlags);
3791 R =
B.buildFAdd(Ty, R, FMA1, NewFlags).getReg(0);
3794 const float ch_log10 = 0x1.344000p-2f;
3795 const float ct_log10 = 0x1.3509f6p-18f;
3798 const float ch_log = 0x1.62e000p-1f;
3799 const float ct_log = 0x1.0bfbe8p-15f;
3801 auto CH =
B.buildFConstant(Ty, IsLog10 ? ch_log10 : ch_log);
3802 auto CT =
B.buildFConstant(Ty, IsLog10 ? ct_log10 : ct_log);
3804 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
3805 auto YH =
B.buildAnd(Ty,
Y, MaskConst);
3806 auto YT =
B.buildFSub(Ty,
Y, YH, Flags);
3810 auto YTCT =
B.buildFMul(Ty, YT, CT, NewFlags);
3813 getMad(
B, Ty, YH.getReg(0), CT.getReg(0), YTCT.getReg(0), NewFlags);
3815 R =
getMad(
B, Ty, YH.getReg(0),
CH.getReg(0), Mad1, NewFlags);
3818 const bool IsFiniteOnly =
3821 if (!IsFiniteOnly) {
3824 auto Fabs =
B.buildFAbs(Ty,
Y);
3827 R =
B.buildSelect(Ty, IsFinite, R,
Y, Flags).getReg(0);
3831 auto Zero =
B.buildFConstant(Ty, 0.0);
3833 B.buildFConstant(Ty, IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f);
3834 auto Shift =
B.buildSelect(Ty, IsScaled, ShiftK, Zero, Flags);
3835 B.buildFSub(Dst, R, Shift, Flags);
3837 B.buildCopy(Dst, R);
3840 MI.eraseFromParent();
3846 unsigned Flags)
const {
3847 const double Log2BaseInverted =
3850 LLT Ty =
B.getMRI()->getType(Dst);
3855 auto LogSrc =
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3858 auto ScaledResultOffset =
B.buildFConstant(Ty, -32.0 * Log2BaseInverted);
3859 auto Zero =
B.buildFConstant(Ty, 0.0);
3861 B.buildSelect(Ty, IsScaled, ScaledResultOffset, Zero, Flags);
3862 auto Log2Inv =
B.buildFConstant(Ty, Log2BaseInverted);
3864 if (ST.hasFastFMAF32())
3865 B.buildFMA(Dst, LogSrc, Log2Inv, ResultOffset, Flags);
3867 auto Mul =
B.buildFMul(Ty, LogSrc, Log2Inv, Flags);
3868 B.buildFAdd(Dst,
Mul, ResultOffset, Flags);
3876 ?
B.buildFLog2(Ty, Src, Flags)
3877 :
B.buildIntrinsic(Intrinsic::amdgcn_log, {Ty})
3880 auto Log2BaseInvertedOperand =
B.buildFConstant(Ty, Log2BaseInverted);
3881 B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
3892 unsigned Flags =
MI.getFlags();
3893 LLT Ty =
B.getMRI()->getType(Dst);
3903 auto Ext =
B.buildFPExt(
F32, Src, Flags);
3904 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {
F32})
3905 .addUse(Ext.getReg(0))
3907 B.buildFPTrunc(Dst,
Log2, Flags);
3908 MI.eraseFromParent();
3918 MI.eraseFromParent();
3926 auto RangeCheckConst =
B.buildFConstant(Ty, -0x1.f80000p+6f);
3928 RangeCheckConst, Flags);
3930 auto SixtyFour =
B.buildFConstant(Ty, 0x1.0p+6f);
3931 auto Zero =
B.buildFConstant(Ty, 0.0);
3932 auto AddOffset =
B.buildSelect(
F32, NeedsScaling, SixtyFour, Zero, Flags);
3933 auto AddInput =
B.buildFAdd(
F32, Src, AddOffset, Flags);
3935 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3936 .addUse(AddInput.getReg(0))
3939 auto TwoExpNeg64 =
B.buildFConstant(Ty, 0x1.0p-64f);
3940 auto One =
B.buildFConstant(Ty, 1.0);
3941 auto ResultScale =
B.buildSelect(
F32, NeedsScaling, TwoExpNeg64, One, Flags);
3942 B.buildFMul(Dst, Exp2, ResultScale, Flags);
3943 MI.eraseFromParent();
3948 const SrcOp &Src,
unsigned Flags) {
3949 LLT Ty = Dst.getLLTTy(*
B.getMRI());
3952 return B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Dst})
3953 .addUse(Src.getReg())
3956 return B.buildFExp2(Dst, Src, Flags);
3962 bool IsExp10)
const {
3963 LLT Ty =
B.getMRI()->getType(
X);
3967 auto Const =
B.buildFConstant(Ty, IsExp10 ? 0x1.a934f0p+1f :
numbers::log2e);
3968 auto Mul =
B.buildFMul(Ty,
X, Const, Flags);
3975 LLT Ty =
B.getMRI()->getType(Dst);
3982 auto Threshold =
B.buildFConstant(Ty, -0x1.5d58a0p+6f);
3985 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+6f);
3986 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
3987 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X, Flags);
3990 auto ExpInput =
B.buildFMul(Ty, AdjustedX, Log2E, Flags);
3992 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
3993 .addUse(ExpInput.getReg(0))
3996 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.969d48p-93f);
3997 auto AdjustedResult =
B.buildFMul(Ty, Exp2, ResultScaleFactor, Flags);
3998 B.buildSelect(Dst, NeedsScaling, AdjustedResult, Exp2, Flags);
4004 unsigned Flags)
const {
4005 LLT Ty =
B.getMRI()->getType(Dst);
4010 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4011 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4013 auto Mul1 =
B.buildFMul(Ty,
X, K1, Flags);
4014 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4015 auto Mul0 =
B.buildFMul(Ty,
X, K0, Flags);
4016 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4017 B.buildFMul(Dst, Exp2_0, Exp2_1, Flags);
4027 auto Threshold =
B.buildFConstant(Ty, -0x1.2f7030p+5f);
4031 auto ScaleOffset =
B.buildFConstant(Ty, 0x1.0p+5f);
4032 auto ScaledX =
B.buildFAdd(Ty,
X, ScaleOffset, Flags);
4033 auto AdjustedX =
B.buildSelect(Ty, NeedsScaling, ScaledX,
X);
4035 auto K0 =
B.buildFConstant(Ty, 0x1.a92000p+1f);
4036 auto K1 =
B.buildFConstant(Ty, 0x1.4f0978p-11f);
4038 auto Mul1 =
B.buildFMul(Ty, AdjustedX, K1, Flags);
4039 auto Exp2_1 =
buildExp(
B, Ty, Mul1, Flags);
4040 auto Mul0 =
B.buildFMul(Ty, AdjustedX, K0, Flags);
4041 auto Exp2_0 =
buildExp(
B, Ty, Mul0, Flags);
4043 auto MulExps =
B.buildFMul(Ty, Exp2_0, Exp2_1, Flags);
4044 auto ResultScaleFactor =
B.buildFConstant(Ty, 0x1.9f623ep-107f);
4045 auto AdjustedResult =
B.buildFMul(Ty, MulExps, ResultScaleFactor, Flags);
4047 B.buildSelect(Dst, NeedsScaling, AdjustedResult, MulExps);
4066 if (
MI.getOpcode() == TargetOpcode::G_FEXP2) {
4068 Dn =
B.buildFRint(
F64,
X, Flags).getReg(0);
4070 F =
B.buildFSub(
F64,
X, Dn, Flags).getReg(0);
4072 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4073 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4074 auto Mul2 =
B.buildFMul(
F64,
F, C2, Flags).getReg(0);
4075 T =
B.buildFMA(
F64,
F, C1, Mul2, Flags).getReg(0);
4077 }
else if (
MI.getOpcode() == TargetOpcode::G_FEXP10) {
4078 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.a934f0979a371p+1));
4079 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4080 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4082 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4083 auto C2 =
B.buildFConstant(
F64,
APFloat(-0x1.9dc1da994fd21p-59));
4084 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.34413509f79ffp-2));
4085 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4086 F =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4088 auto C4 =
B.buildFConstant(
F64,
APFloat(0x1.26bb1bbb55516p+1));
4089 auto C5 =
B.buildFConstant(
F64,
APFloat(-0x1.f48ad494ea3e9p-53));
4090 auto MulF =
B.buildFMul(
F64,
F, C5, Flags).getReg(0);
4091 T =
B.buildFMA(
F64,
F, C4, MulF, Flags).getReg(0);
4094 auto C1 =
B.buildFConstant(
F64,
APFloat(0x1.71547652b82fep+0));
4095 auto Mul =
B.buildFMul(
F64,
X, C1, Flags).getReg(0);
4096 Dn =
B.buildFRint(
F64,
Mul, Flags).getReg(0);
4098 auto NegDn =
B.buildFNeg(
F64, Dn, Flags).getReg(0);
4099 auto C2 =
B.buildFConstant(
F64,
APFloat(0x1.abc9e3b39803fp-56));
4100 auto C3 =
B.buildFConstant(
F64,
APFloat(0x1.62e42fefa39efp-1));
4101 auto Inner =
B.buildFMA(
F64, NegDn, C3,
X, Flags).getReg(0);
4102 T =
B.buildFMA(
F64, NegDn, C2, Inner, Flags).getReg(0);
4106 auto P =
B.buildFConstant(
F64, 0x1.ade156a5dcb37p-26);
4107 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.28af3fca7ab0cp-22),
4109 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.71dee623fde64p-19),
4111 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01997c89e6b0p-16),
4113 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.a01a014761f6ep-13),
4115 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.6c16c1852b7b0p-10),
4117 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.1111111122322p-7), Flags);
4118 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.55555555502a1p-5), Flags);
4119 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.5555555555511p-3), Flags);
4120 P =
B.buildFMA(
F64,
T,
P,
B.buildFConstant(
F64, 0x1.000000000000bp-1), Flags);
4122 auto One =
B.buildFConstant(
F64, 1.0);
4123 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4124 P =
B.buildFMA(
F64,
T,
P, One, Flags);
4127 auto DnInt =
B.buildFPTOSI(I32, Dn);
4128 auto Z =
B.buildFLdexp(
F64,
P, DnInt, Flags);
4135 Z =
B.buildSelect(
F64, CondHi, Z, PInf, Flags);
4142 B.buildSelect(
MI.getOperand(0).getReg(), CondLo, Z, Zero, Flags);
4144 MI.eraseFromParent();
4152 const unsigned Flags =
MI.getFlags();
4164 const bool IsExp10 =
MI.getOpcode() == TargetOpcode::G_FEXP10;
4172 MI.eraseFromParent();
4183 auto Ext =
B.buildFPExt(
F32,
X, Flags);
4186 B.buildFPTrunc(Dst, Lowered, Flags);
4187 MI.eraseFromParent();
4198 MI.eraseFromParent();
4226 const unsigned FlagsNoContract = Flags &
~MachineInstr::FmContract;
4229 if (ST.hasFastFMAF32()) {
4231 const float cc_exp = 0x1.4ae0bep-26f;
4232 const float c_exp10 = 0x1.a934f0p+1f;
4233 const float cc_exp10 = 0x1.2f346ep-24f;
4235 auto C =
B.buildFConstant(Ty, IsExp10 ? c_exp10 : c_exp);
4236 PH =
B.buildFMul(Ty,
X,
C, Flags).getReg(0);
4237 auto NegPH =
B.buildFNeg(Ty, PH, Flags);
4238 auto FMA0 =
B.buildFMA(Ty,
X,
C, NegPH, Flags);
4240 auto CC =
B.buildFConstant(Ty, IsExp10 ? cc_exp10 : cc_exp);
4241 PL =
B.buildFMA(Ty,
X, CC, FMA0, Flags).getReg(0);
4243 const float ch_exp = 0x1.714000p+0f;
4244 const float cl_exp = 0x1.47652ap-12f;
4246 const float ch_exp10 = 0x1.a92000p+1f;
4247 const float cl_exp10 = 0x1.4f0978p-11f;
4249 auto MaskConst =
B.buildConstant(Ty, 0xfffff000);
4250 auto XH =
B.buildAnd(Ty,
X, MaskConst);
4251 auto XL =
B.buildFSub(Ty,
X, XH, Flags);
4253 auto CH =
B.buildFConstant(Ty, IsExp10 ? ch_exp10 : ch_exp);
4254 PH =
B.buildFMul(Ty, XH,
CH, Flags).getReg(0);
4256 auto CL =
B.buildFConstant(Ty, IsExp10 ? cl_exp10 : cl_exp);
4257 auto XLCL =
B.buildFMul(Ty, XL, CL, Flags);
4260 getMad(
B, Ty, XL.getReg(0),
CH.getReg(0), XLCL.getReg(0), Flags);
4261 PL =
getMad(
B, Ty, XH.getReg(0), CL.getReg(0), Mad0, Flags);
4264 auto E =
B.buildIntrinsicRoundeven(Ty, PH, Flags);
4267 auto PHSubE =
B.buildFSub(Ty, PH, E, FlagsNoContract);
4268 auto A =
B.buildFAdd(Ty, PHSubE, PL, Flags);
4270 auto IntE =
B.buildFPTOSI(I32, E);
4272 auto Exp2 =
B.buildIntrinsic(Intrinsic::amdgcn_exp2, {Ty})
4273 .addUse(
A.getReg(0))
4275 auto R =
B.buildFLdexp(Ty, Exp2, IntE, Flags);
4277 auto UnderflowCheckConst =
4278 B.buildFConstant(Ty, IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f);
4279 auto Zero =
B.buildFConstant(Ty, 0.0);
4283 R =
B.buildSelect(Ty, Underflow, Zero, R);
4286 auto OverflowCheckConst =
4287 B.buildFConstant(Ty, IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f);
4292 R =
B.buildSelect(Ty, Overflow, Inf, R, Flags);
4295 B.buildCopy(Dst, R);
4296 MI.eraseFromParent();
4305 unsigned Flags =
MI.getFlags();
4306 LLT Ty =
B.getMRI()->getType(Dst);
4311 auto Log =
B.buildFLog2(
F32, Src0, Flags);
4312 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4313 .addUse(Log.getReg(0))
4316 B.buildFExp2(Dst,
Mul, Flags);
4317 }
else if (Ty == F16) {
4319 auto Log =
B.buildFLog2(F16, Src0, Flags);
4320 auto Ext0 =
B.buildFPExt(
F32, Log, Flags);
4321 auto Ext1 =
B.buildFPExt(
F32, Src1, Flags);
4322 auto Mul =
B.buildIntrinsic(Intrinsic::amdgcn_fmul_legacy, {
F32})
4323 .addUse(Ext0.getReg(0))
4324 .addUse(Ext1.getReg(0))
4326 B.buildFExp2(Dst,
B.buildFPTrunc(F16,
Mul), Flags);
4330 MI.eraseFromParent();
4338 ModSrc = SrcFNeg->getOperand(1).getReg();
4340 ModSrc = SrcFAbs->getOperand(1).getReg();
4342 ModSrc = SrcFAbs->getOperand(1).getReg();
4353 Register OrigSrc =
MI.getOperand(1).getReg();
4354 unsigned Flags =
MI.getFlags();
4356 "this should not have been custom lowered");
4366 auto Fract =
B.buildIntrinsic(Intrinsic::amdgcn_fract, {
F64})
4386 B.buildFMinNumIEEE(Min, Fract, Const, Flags);
4388 B.buildFMinNum(Min, Fract, Const, Flags);
4393 CorrectedFract =
B.buildSelect(
F64, IsNan, ModSrc, Min, Flags).getReg(0);
4396 auto NegFract =
B.buildFNeg(
F64, CorrectedFract, Flags);
4397 B.buildFAdd(Dst, OrigSrc, NegFract, Flags);
4399 MI.eraseFromParent();
4417 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC) {
4419 Src0 =
B.buildTrunc(I16,
MI.getOperand(1).getReg()).getReg(0);
4420 Src1 =
B.buildTrunc(I16,
MI.getOperand(2).getReg()).getReg(0);
4423 auto Merge =
B.buildMergeLikeInstr(I32, {Src0, Src1});
4424 B.buildBitcast(Dst,
Merge);
4426 MI.eraseFromParent();
4443 bool UsePartialMad64_32,
4444 bool SeparateOddAlignedProducts)
const {
4459 auto getZero32 = [&]() ->
Register {
4461 Zero32 =
B.buildConstant(I32, 0).getReg(0);
4464 auto getZero64 = [&]() ->
Register {
4466 Zero64 =
B.buildConstant(I64, 0).getReg(0);
4471 for (
unsigned i = 0; i < Src0.
size(); ++i) {
4482 if (CarryIn.empty())
4485 bool HaveCarryOut =
true;
4487 if (CarryIn.size() == 1) {
4489 LocalAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4493 CarryAccum = getZero32();
4495 CarryAccum =
B.buildZExt(I32, CarryIn[0]).getReg(0);
4496 for (
unsigned i = 1; i + 1 < CarryIn.size(); ++i) {
4498 B.buildUAdde(I32,
S1, CarryAccum, getZero32(), CarryIn[i])
4503 LocalAccum = getZero32();
4504 HaveCarryOut =
false;
4509 B.buildUAdde(I32,
S1, CarryAccum, LocalAccum, CarryIn.back());
4510 LocalAccum =
Add.getReg(0);
4524 auto buildMadChain =
4527 assert((DstIndex + 1 < Accum.
size() && LocalAccum.size() == 2) ||
4528 (DstIndex + 1 >= Accum.
size() && LocalAccum.size() == 1));
4535 if (LocalAccum.size() == 1 &&
4536 (!UsePartialMad64_32 || !CarryIn.empty())) {
4539 unsigned j1 = DstIndex - j0;
4540 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4544 auto Mul =
B.buildMul(I32, Src0[j0], Src1[j1]);
4546 LocalAccum[0] =
Mul.getReg(0);
4548 if (CarryIn.empty()) {
4549 LocalAccum[0] =
B.buildAdd(I32, LocalAccum[0],
Mul).getReg(0);
4552 B.buildUAdde(I32,
S1, LocalAccum[0],
Mul, CarryIn.back())
4558 }
while (j0 <= DstIndex && (!UsePartialMad64_32 || !CarryIn.empty()));
4562 if (j0 <= DstIndex) {
4563 bool HaveSmallAccum =
false;
4566 if (LocalAccum[0]) {
4567 if (LocalAccum.size() == 1) {
4568 Tmp =
B.buildAnyExt(I64, LocalAccum[0]).getReg(0);
4569 HaveSmallAccum =
true;
4570 }
else if (LocalAccum[1]) {
4571 Tmp =
B.buildMergeLikeInstr(I64, LocalAccum).getReg(0);
4572 HaveSmallAccum =
false;
4574 Tmp =
B.buildZExt(I64, LocalAccum[0]).getReg(0);
4575 HaveSmallAccum =
true;
4578 assert(LocalAccum.size() == 1 || !LocalAccum[1]);
4580 HaveSmallAccum =
true;
4584 unsigned j1 = DstIndex - j0;
4585 if (Src0KnownZeros[j0] || Src1KnownZeros[j1]) {
4589 auto Mad =
B.buildInstr(AMDGPU::G_AMDGPU_MAD_U64_U32, {I64,
S1},
4590 {Src0[j0], Src1[j1], Tmp});
4591 Tmp = Mad.getReg(0);
4592 if (!HaveSmallAccum)
4593 CarryOut.push_back(Mad.getReg(1));
4594 HaveSmallAccum =
false;
4597 }
while (j0 <= DstIndex);
4599 auto Unmerge =
B.buildUnmerge(I32, Tmp);
4600 LocalAccum[0] = Unmerge.getReg(0);
4601 if (LocalAccum.size() > 1)
4602 LocalAccum[1] = Unmerge.getReg(1);
4629 for (
unsigned i = 0; i <= Accum.
size() / 2; ++i) {
4630 Carry OddCarryIn = std::move(OddCarry);
4631 Carry EvenCarryIn = std::move(EvenCarry);
4636 if (2 * i < Accum.
size()) {
4637 auto LocalAccum = Accum.
drop_front(2 * i).take_front(2);
4638 EvenCarry = buildMadChain(LocalAccum, 2 * i, EvenCarryIn);
4643 if (!SeparateOddAlignedProducts) {
4644 auto LocalAccum = Accum.
drop_front(2 * i - 1).take_front(2);
4645 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4647 bool IsHighest = 2 * i >= Accum.
size();
4650 .take_front(IsHighest ? 1 : 2);
4651 OddCarry = buildMadChain(LocalAccum, 2 * i - 1, OddCarryIn);
4657 Lo =
B.buildUAddo(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0]);
4659 Lo =
B.buildAdd(I32, Accum[2 * i - 1], SeparateOddOut[0]);
4661 Lo =
B.buildUAdde(I32,
S1, Accum[2 * i - 1], SeparateOddOut[0],
4664 Accum[2 * i - 1] =
Lo->getOperand(0).getReg();
4667 auto Hi =
B.buildUAdde(I32,
S1, Accum[2 * i], SeparateOddOut[1],
4668 Lo->getOperand(1).getReg());
4669 Accum[2 * i] =
Hi.getReg(0);
4670 SeparateOddCarry =
Hi.getReg(1);
4677 if (
Register CarryOut = mergeCarry(Accum[2 * i - 1], OddCarryIn))
4678 EvenCarryIn.push_back(CarryOut);
4680 if (2 * i < Accum.
size()) {
4681 if (
Register CarryOut = mergeCarry(Accum[2 * i], EvenCarryIn))
4682 OddCarry.push_back(CarryOut);
4694 assert(ST.hasMad64_32());
4695 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
4707 unsigned Size = Ty.getSizeInBits();
4708 if (ST.hasVMulU64Inst() &&
Size == 64)
4711 unsigned NumParts =
Size / 32;
4723 const bool SeparateOddAlignedProducts = ST.hasFullRate64Ops();
4727 for (
unsigned i = 0; i < NumParts; ++i) {
4731 B.buildUnmerge(Src0Parts, Src0);
4732 B.buildUnmerge(Src1Parts, Src1);
4735 buildMultiply(Helper, AccumRegs, Src0Parts, Src1Parts, UsePartialMad64_32,
4736 SeparateOddAlignedProducts);
4738 B.buildMergeLikeInstr(DstReg, AccumRegs);
4739 MI.eraseFromParent();
4754 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_CTLZ
4755 ? AMDGPU::G_AMDGPU_FFBH_U32
4756 : AMDGPU::G_AMDGPU_FFBL_B32;
4757 auto Tmp =
B.buildInstr(NewOpc, {DstTy}, {Src});
4760 MI.eraseFromParent();
4770 TypeSize NumBits = SrcTy.getSizeInBits();
4775 auto ShiftAmt =
B.buildConstant(I32, 32u - NumBits);
4776 auto Extend =
B.buildAnyExt(I32, {Src}).
getReg(0u);
4777 auto Shift =
B.buildShl(I32, Extend, ShiftAmt);
4778 auto Ctlz =
B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {I32}, {Shift});
4779 B.buildTrunc(Dst, Ctlz);
4780 MI.eraseFromParent();
4791 assert(SrcTy == I32 &&
"legalizeCTLS only supports i32");
4792 unsigned BitWidth = SrcTy.getSizeInBits();
4794 auto Sffbh =
B.buildIntrinsic(Intrinsic::amdgcn_sffbh, {I32}).addUse(Src);
4795 auto Clamped =
B.buildUMin(I32, Sffbh,
B.buildConstant(I32,
BitWidth));
4796 B.buildSub(Dst, Clamped,
B.buildConstant(I32, 1));
4797 MI.eraseFromParent();
4803 if (
MI.getOpcode() != TargetOpcode::G_XOR)
4806 return ConstVal == -1;
4813 Register CondDef =
MI.getOperand(0).getReg();
4832 if (
UseMI->getParent() != Parent ||
UseMI->getOpcode() != AMDGPU::G_BRCOND)
4841 UncondBrTarget = &*NextMBB;
4843 if (
Next->getOpcode() != AMDGPU::G_BR)
4862 *ArgRC,
B.getDebugLoc(), ArgTy);
4866 const unsigned Mask = Arg->
getMask();
4874 auto ShiftAmt =
B.buildConstant(I32, Shift);
4875 AndMaskSrc =
B.buildLShr(I32, LiveIn, ShiftAmt).getReg(0);
4878 B.buildAnd(DstReg, AndMaskSrc,
B.buildConstant(I32, Mask >> Shift));
4880 B.buildCopy(DstReg, LiveIn);
4890 if (!ST.hasClusters()) {
4893 MI.eraseFromParent();
4913 auto One =
B.buildConstant(I32, 1);
4914 auto ClusterSizeXYZ =
B.buildAdd(I32, ClusterMaxIdXYZ, One);
4915 auto GlobalIdXYZ =
B.buildAdd(I32, ClusterWorkGroupIdXYZ,
4916 B.buildMul(I32, ClusterIdXYZ, ClusterSizeXYZ));
4923 B.buildCopy(DstReg, GlobalIdXYZ);
4924 MI.eraseFromParent();
4928 B.buildCopy(DstReg, ClusterIdXYZ);
4929 MI.eraseFromParent();
4934 unsigned ClusterIdField = HwregEncoding::encode(ID_IB_STS2, 6, 4);
4936 MRI.
setRegClass(ClusterId, &AMDGPU::SReg_32RegClass);
4937 B.buildInstr(AMDGPU::S_GETREG_B32_const)
4939 .addImm(ClusterIdField);
4940 auto Zero =
B.buildConstant(I32, 0);
4943 B.buildSelect(DstReg, NoClusters, ClusterIdXYZ, GlobalIdXYZ);
4944 MI.eraseFromParent();
4986 auto LoadConstant = [&](
unsigned N) {
4987 B.buildConstant(DstReg,
N);
4991 if (ST.hasArchitectedSGPRs() &&
4998 Arg = &WorkGroupIDX;
4999 ArgRC = &AMDGPU::SReg_32RegClass;
5003 Arg = &WorkGroupIDY;
5004 ArgRC = &AMDGPU::SReg_32RegClass;
5008 Arg = &WorkGroupIDZ;
5009 ArgRC = &AMDGPU::SReg_32RegClass;
5013 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
5014 return LoadConstant(0);
5015 Arg = &ClusterWorkGroupIDX;
5016 ArgRC = &AMDGPU::SReg_32RegClass;
5020 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
5021 return LoadConstant(0);
5022 Arg = &ClusterWorkGroupIDY;
5023 ArgRC = &AMDGPU::SReg_32RegClass;
5027 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
5028 return LoadConstant(0);
5029 Arg = &ClusterWorkGroupIDZ;
5030 ArgRC = &AMDGPU::SReg_32RegClass;
5035 return LoadConstant(ClusterDims.
getDims()[0] - 1);
5036 Arg = &ClusterWorkGroupMaxIDX;
5037 ArgRC = &AMDGPU::SReg_32RegClass;
5042 return LoadConstant(ClusterDims.
getDims()[1] - 1);
5043 Arg = &ClusterWorkGroupMaxIDY;
5044 ArgRC = &AMDGPU::SReg_32RegClass;
5049 return LoadConstant(ClusterDims.
getDims()[2] - 1);
5050 Arg = &ClusterWorkGroupMaxIDZ;
5051 ArgRC = &AMDGPU::SReg_32RegClass;
5055 Arg = &ClusterWorkGroupMaxFlatID;
5056 ArgRC = &AMDGPU::SReg_32RegClass;
5071 return LoadConstant(0);
5076 B.buildUndef(DstReg);
5080 if (!Arg->isRegister() || !Arg->getRegister().isValid())
5092 MI.eraseFromParent();
5098 B.buildConstant(
MI.getOperand(0).getReg(),
C);
5099 MI.eraseFromParent();
5106 unsigned MaxID = ST.getMaxWorkitemID(
B.getMF().getFunction(), Dim);
5120 B.buildUndef(DstReg);
5121 MI.eraseFromParent();
5125 if (Arg->isMasked()) {
5139 MI.eraseFromParent();
5154 Register KernArgReg =
B.getMRI()->createGenericVirtualRegister(PtrTy);
5163 return B.buildObjectPtrOffset(PtrTy, KernArgReg, COffset).getReg(0);
5171 Align Alignment)
const {
5175 "unexpected kernarg parameter type");
5182 MI.eraseFromParent();
5218 auto FloatY =
B.buildUITOFP(
F32,
Y);
5219 auto RcpIFlag =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {FloatY});
5221 auto ScaledY =
B.buildFMul(
F32, RcpIFlag, Scale);
5222 auto Z =
B.buildFPTOUI(I32, ScaledY);
5225 auto NegY =
B.buildSub(I32,
B.buildConstant(I32, 0),
Y);
5226 auto NegYZ =
B.buildMul(I32, NegY, Z);
5227 Z =
B.buildAdd(I32, Z,
B.buildUMulH(I32, Z, NegYZ));
5230 auto Q =
B.buildUMulH(I32,
X, Z);
5231 auto R =
B.buildSub(I32,
X,
B.buildMul(I32, Q,
Y));
5234 auto One =
B.buildConstant(I32, 1);
5237 Q =
B.buildSelect(I32,
Cond,
B.buildAdd(I32, Q, One), Q);
5238 R =
B.buildSelect(I32,
Cond,
B.buildSub(I32, R,
Y), R);
5243 B.buildSelect(DstDivReg,
Cond,
B.buildAdd(I32, Q, One), Q);
5246 B.buildSelect(DstRemReg,
Cond,
B.buildSub(I32, R,
Y), R);
5266 auto Unmerge =
B.buildUnmerge(I32, Val);
5268 auto CvtLo =
B.buildUITOFP(
F32, Unmerge.getReg(0));
5269 auto CvtHi =
B.buildUITOFP(
F32, Unmerge.getReg(1));
5271 auto Mad =
B.buildFMAD(
5275 auto Rcp =
B.buildInstr(AMDGPU::G_AMDGPU_RCP_IFLAG, {
F32}, {Mad});
5276 auto Mul1 =
B.buildFMul(
5280 auto Mul2 =
B.buildFMul(
5282 auto Trunc =
B.buildIntrinsicTrunc(
F32, Mul2);
5285 auto Mad2 =
B.buildFMAD(
5289 auto ResultLo =
B.buildFPTOUI(I32, Mad2);
5290 auto ResultHi =
B.buildFPTOUI(I32, Trunc);
5292 return {ResultLo.getReg(0), ResultHi.getReg(0)};
5307 auto Rcp =
B.buildMergeLikeInstr(I64, {RcpLo, RcpHi});
5309 auto Zero64 =
B.buildConstant(I64, 0);
5310 auto NegDenom =
B.buildSub(I64, Zero64, Denom);
5312 auto MulLo1 =
B.buildMul(I64, NegDenom, Rcp);
5313 auto MulHi1 =
B.buildUMulH(I64, Rcp, MulLo1);
5315 auto UnmergeMulHi1 =
B.buildUnmerge(I32, MulHi1);
5316 Register MulHi1_Lo = UnmergeMulHi1.getReg(0);
5317 Register MulHi1_Hi = UnmergeMulHi1.getReg(1);
5319 auto Add1_Lo =
B.buildUAddo(I32,
S1, RcpLo, MulHi1_Lo);
5320 auto Add1_Hi =
B.buildUAdde(I32,
S1, RcpHi, MulHi1_Hi, Add1_Lo.getReg(1));
5321 auto Add1 =
B.buildMergeLikeInstr(I64, {Add1_Lo, Add1_Hi});
5323 auto MulLo2 =
B.buildMul(I64, NegDenom, Add1);
5324 auto MulHi2 =
B.buildUMulH(I64, Add1, MulLo2);
5325 auto UnmergeMulHi2 =
B.buildUnmerge(I32, MulHi2);
5326 Register MulHi2_Lo = UnmergeMulHi2.getReg(0);
5327 Register MulHi2_Hi = UnmergeMulHi2.getReg(1);
5329 auto Zero32 =
B.buildConstant(I32, 0);
5330 auto Add2_Lo =
B.buildUAddo(I32,
S1, Add1_Lo, MulHi2_Lo);
5331 auto Add2_Hi =
B.buildUAdde(I32,
S1, Add1_Hi, MulHi2_Hi, Add2_Lo.getReg(1));
5332 auto Add2 =
B.buildMergeLikeInstr(I64, {Add2_Lo, Add2_Hi});
5334 auto UnmergeNumer =
B.buildUnmerge(I32, Numer);
5335 Register NumerLo = UnmergeNumer.getReg(0);
5336 Register NumerHi = UnmergeNumer.getReg(1);
5338 auto MulHi3 =
B.buildUMulH(I64, Numer, Add2);
5339 auto Mul3 =
B.buildMul(I64, Denom, MulHi3);
5340 auto UnmergeMul3 =
B.buildUnmerge(I32, Mul3);
5341 Register Mul3_Lo = UnmergeMul3.getReg(0);
5342 Register Mul3_Hi = UnmergeMul3.getReg(1);
5343 auto Sub1_Lo =
B.buildUSubo(I32,
S1, NumerLo, Mul3_Lo);
5344 auto Sub1_Hi =
B.buildUSube(I32,
S1, NumerHi, Mul3_Hi, Sub1_Lo.getReg(1));
5345 auto Sub1_Mi =
B.buildSub(I32, NumerHi, Mul3_Hi);
5346 auto Sub1 =
B.buildMergeLikeInstr(I64, {Sub1_Lo, Sub1_Hi});
5348 auto UnmergeDenom =
B.buildUnmerge(I32, Denom);
5349 Register DenomLo = UnmergeDenom.getReg(0);
5350 Register DenomHi = UnmergeDenom.getReg(1);
5353 auto C1 =
B.buildSExt(I32, CmpHi);
5356 auto C2 =
B.buildSExt(I32, CmpLo);
5359 auto C3 =
B.buildSelect(I32, CmpEq, C2, C1);
5366 auto Sub2_Lo =
B.buildUSubo(I32,
S1, Sub1_Lo, DenomLo);
5367 auto Sub2_Mi =
B.buildUSube(I32,
S1, Sub1_Mi, DenomHi, Sub1_Lo.getReg(1));
5368 auto Sub2_Hi =
B.buildUSube(I32,
S1, Sub2_Mi, Zero32, Sub2_Lo.getReg(1));
5369 auto Sub2 =
B.buildMergeLikeInstr(I64, {Sub2_Lo, Sub2_Hi});
5371 auto One64 =
B.buildConstant(I64, 1);
5372 auto Add3 =
B.buildAdd(I64, MulHi3, One64);
5378 auto C6 =
B.buildSelect(
5382 auto Add4 =
B.buildAdd(I64, Add3, One64);
5383 auto Sub3_Lo =
B.buildUSubo(I32,
S1, Sub2_Lo, DenomLo);
5385 auto Sub3_Mi =
B.buildUSube(I32,
S1, Sub2_Mi, DenomHi, Sub2_Lo.getReg(1));
5386 auto Sub3_Hi =
B.buildUSube(I32,
S1, Sub3_Mi, Zero32, Sub3_Lo.getReg(1));
5387 auto Sub3 =
B.buildMergeLikeInstr(I64, {Sub3_Lo, Sub3_Hi});
5393 auto Sel1 =
B.buildSelect(
5400 auto Sel2 =
B.buildSelect(
5411 switch (
MI.getOpcode()) {
5414 case AMDGPU::G_UDIV: {
5415 DstDivReg =
MI.getOperand(0).getReg();
5418 case AMDGPU::G_UREM: {
5419 DstRemReg =
MI.getOperand(0).getReg();
5422 case AMDGPU::G_UDIVREM: {
5423 DstDivReg =
MI.getOperand(0).getReg();
5424 DstRemReg =
MI.getOperand(1).getReg();
5431 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5432 Register Num =
MI.getOperand(FirstSrcOpIdx).getReg();
5433 Register Den =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5443 MI.eraseFromParent();
5454 if (Ty != I32 && Ty != I64)
5457 const unsigned FirstSrcOpIdx =
MI.getNumExplicitDefs();
5458 Register LHS =
MI.getOperand(FirstSrcOpIdx).getReg();
5459 Register RHS =
MI.getOperand(FirstSrcOpIdx + 1).getReg();
5461 auto SignBitOffset =
B.buildConstant(I32, Ty.getSizeInBits() - 1);
5462 auto LHSign =
B.buildAShr(Ty, LHS, SignBitOffset);
5463 auto RHSign =
B.buildAShr(Ty, RHS, SignBitOffset);
5465 LHS =
B.buildAdd(Ty, LHS, LHSign).getReg(0);
5466 RHS =
B.buildAdd(Ty, RHS, RHSign).getReg(0);
5468 LHS =
B.buildXor(Ty, LHS, LHSign).getReg(0);
5469 RHS =
B.buildXor(Ty, RHS, RHSign).getReg(0);
5471 Register DstDivReg, DstRemReg, TmpDivReg, TmpRemReg;
5472 switch (
MI.getOpcode()) {
5475 case AMDGPU::G_SDIV: {
5476 DstDivReg =
MI.getOperand(0).getReg();
5480 case AMDGPU::G_SREM: {
5481 DstRemReg =
MI.getOperand(0).getReg();
5485 case AMDGPU::G_SDIVREM: {
5486 DstDivReg =
MI.getOperand(0).getReg();
5487 DstRemReg =
MI.getOperand(1).getReg();
5500 auto Sign =
B.buildXor(Ty, LHSign, RHSign).getReg(0);
5501 auto SignXor =
B.buildXor(Ty, TmpDivReg, Sign).getReg(0);
5502 B.buildSub(DstDivReg, SignXor, Sign);
5506 auto Sign = LHSign.getReg(0);
5507 auto SignXor =
B.buildXor(Ty, TmpRemReg, Sign).getReg(0);
5508 B.buildSub(DstRemReg, SignXor, Sign);
5511 MI.eraseFromParent();
5538 if (CLHS->isOne()) {
5539 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5543 MI.eraseFromParent();
5548 if (CLHS->isMinusOne()) {
5549 auto FNeg =
B.buildFNeg(ResTy, RHS, Flags);
5550 B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res)
5551 .addUse(FNeg.getReg(0))
5554 MI.eraseFromParent();
5561 if (!AllowInaccurateRcp &&
5566 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5569 B.buildFMul(Res, LHS, RCP, Flags);
5571 MI.eraseFromParent();
5586 if (!AllowInaccurateRcp)
5594 X =
B.buildFConstant(ResTy, 1.0).getReg(0);
5596 Register NegY = IsNegRcp ?
Y :
B.buildFNeg(ResTy,
Y).getReg(0);
5597 auto One =
B.buildFConstant(ResTy, 1.0);
5599 auto R =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy})
5603 R =
B.buildFNeg(ResTy, R);
5605 auto Tmp0 =
B.buildFMA(ResTy, NegY, R, One);
5606 R =
B.buildFMA(ResTy, Tmp0, R, R);
5608 auto Tmp1 =
B.buildFMA(ResTy, NegY, R, One);
5609 R =
B.buildFMA(ResTy, Tmp1, R, R);
5612 if (IsNegRcp || (CLHS && CLHS->
isOne())) {
5613 B.buildCopy(Res, R);
5614 MI.eraseFromParent();
5618 auto Ret =
B.buildFMul(ResTy,
X, R);
5619 auto Tmp2 =
B.buildFMA(ResTy, NegY, Ret,
X);
5621 B.buildFMA(Res, Tmp2, R, Ret);
5622 MI.eraseFromParent();
5655 auto LHSExt =
B.buildFPExt(
F32, LHS, Flags);
5656 auto RHSExt =
B.buildFPExt(
F32, RHS, Flags);
5657 auto NegRHSExt =
B.buildFNeg(
F32, RHSExt);
5658 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5659 .addUse(RHSExt.getReg(0))
5661 auto Quot =
B.buildFMul(
F32, LHSExt, Rcp, Flags);
5663 if (ST.hasMadMacF32Insts()) {
5664 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5665 Quot =
B.buildFMAD(
F32, Err, Rcp, Quot, Flags);
5666 Err =
B.buildFMAD(
F32, NegRHSExt, Quot, LHSExt, Flags);
5668 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5669 Quot =
B.buildFMA(
F32, Err, Rcp, Quot, Flags);
5670 Err =
B.buildFMA(
F32, NegRHSExt, Quot, LHSExt, Flags);
5672 auto Tmp =
B.buildFMul(
F32, Err, Rcp, Flags);
5673 auto TmpInt =
B.buildBitcast(I32, Tmp);
5674 auto MaskedInt =
B.buildAnd(I32, TmpInt,
B.buildConstant(I32, 0xff800000));
5675 auto Masked =
B.buildBitcast(
F32, MaskedInt);
5676 Quot =
B.buildFAdd(
F32,
Masked, Quot, Flags);
5677 auto RDst =
B.buildFPTrunc(F16, Quot, Flags);
5678 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5679 .addUse(RDst.getReg(0))
5684 MI.eraseFromParent();
5697 unsigned SPDenormMode =
5700 if (ST.hasDenormModeInst()) {
5702 uint32_t DPDenormModeDefault =
Mode.fpDenormModeDPValue();
5704 uint32_t NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
5705 B.buildInstr(AMDGPU::S_DENORM_MODE)
5706 .addImm(NewDenormModeValue);
5709 B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
5710 .addImm(SPDenormMode)
5732 auto One =
B.buildFConstant(
F32, 1.0f);
5734 auto DenominatorScaled =
5735 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5740 auto NumeratorScaled =
5741 B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F32,
S1})
5747 auto ApproxRcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5748 .addUse(DenominatorScaled.getReg(0))
5750 auto NegDivScale0 =
B.buildFNeg(
F32, DenominatorScaled, Flags);
5753 const bool HasDynamicDenormals =
5758 if (!PreservesDenormals) {
5759 if (HasDynamicDenormals) {
5761 B.buildInstr(AMDGPU::S_GETREG_B32)
5762 .addDef(SavedSPDenormMode)
5768 auto Fma0 =
B.buildFMA(
F32, NegDivScale0, ApproxRcp, One, Flags);
5769 auto Fma1 =
B.buildFMA(
F32, Fma0, ApproxRcp, ApproxRcp, Flags);
5770 auto Mul =
B.buildFMul(
F32, NumeratorScaled, Fma1, Flags);
5771 auto Fma2 =
B.buildFMA(
F32, NegDivScale0,
Mul, NumeratorScaled, Flags);
5772 auto Fma3 =
B.buildFMA(
F32, Fma2, Fma1,
Mul, Flags);
5773 auto Fma4 =
B.buildFMA(
F32, NegDivScale0, Fma3, NumeratorScaled, Flags);
5775 if (!PreservesDenormals) {
5776 if (HasDynamicDenormals) {
5777 assert(SavedSPDenormMode);
5778 B.buildInstr(AMDGPU::S_SETREG_B32)
5779 .addReg(SavedSPDenormMode)
5785 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F32})
5786 .addUse(Fma4.getReg(0))
5787 .addUse(Fma1.getReg(0))
5788 .addUse(Fma3.getReg(0))
5789 .addUse(NumeratorScaled.getReg(1))
5792 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res)
5793 .addUse(Fmas.getReg(0))
5798 MI.eraseFromParent();
5817 auto One =
B.buildFConstant(
F64, 1.0);
5819 auto DivScale0 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5825 auto NegDivScale0 =
B.buildFNeg(
F64, DivScale0.getReg(0), Flags);
5827 auto Rcp =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F64})
5828 .addUse(DivScale0.getReg(0))
5831 auto Fma0 =
B.buildFMA(
F64, NegDivScale0, Rcp, One, Flags);
5832 auto Fma1 =
B.buildFMA(
F64, Rcp, Fma0, Rcp, Flags);
5833 auto Fma2 =
B.buildFMA(
F64, NegDivScale0, Fma1, One, Flags);
5835 auto DivScale1 =
B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {
F64,
S1})
5841 auto Fma3 =
B.buildFMA(
F64, Fma1, Fma2, Fma1, Flags);
5842 auto Mul =
B.buildFMul(
F64, DivScale1.getReg(0), Fma3, Flags);
5843 auto Fma4 =
B.buildFMA(
F64, NegDivScale0,
Mul, DivScale1.getReg(0), Flags);
5846 if (!ST.hasUsableDivScaleConditionOutput()) {
5853 auto NumUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, LHS));
5854 auto DenUnmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, RHS));
5855 auto Scale0Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale0));
5856 auto Scale1Unmerge =
B.buildUnmerge(I32,
B.buildBitcast(I64, DivScale1));
5859 Scale1Unmerge.getReg(1));
5861 Scale0Unmerge.getReg(1));
5862 Scale =
B.buildXor(
S1, CmpNum, CmpDen).getReg(0);
5864 Scale = DivScale1.getReg(1);
5867 auto Fmas =
B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {
F64})
5868 .addUse(Fma4.getReg(0))
5869 .addUse(Fma3.getReg(0))
5870 .addUse(
Mul.getReg(0))
5874 B.buildIntrinsic(Intrinsic::amdgcn_div_fixup,
ArrayRef(Res))
5875 .addUse(Fmas.getReg(0))
5880 MI.eraseFromParent();
5895 auto Mant =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_mant, {Ty})
5898 auto Exp =
B.buildIntrinsic(Intrinsic::amdgcn_frexp_exp, {InstrExpTy})
5902 if (ST.hasFractBug()) {
5903 auto Fabs =
B.buildFAbs(Ty, Val);
5907 auto Zero =
B.buildConstant(InstrExpTy, 0);
5908 Exp =
B.buildSelect(InstrExpTy, IsFinite, Exp, Zero);
5909 Mant =
B.buildSelect(Ty, IsFinite, Mant, Val);
5912 B.buildCopy(Res0, Mant);
5913 B.buildSExtOrTrunc(Res1, Exp);
5915 MI.eraseFromParent();
5930 auto Abs =
B.buildFAbs(
F32, RHS, Flags);
5933 auto C0 =
B.buildFConstant(
F32, 0x1p+96f);
5934 auto C1 =
B.buildFConstant(
F32, 0x1p-32f);
5935 auto C2 =
B.buildFConstant(
F32, 1.0f);
5938 auto Sel =
B.buildSelect(
F32, CmpRes, C1, C2, Flags);
5940 auto Mul0 =
B.buildFMul(
F32, RHS, Sel, Flags);
5942 auto RCP =
B.buildIntrinsic(Intrinsic::amdgcn_rcp, {
F32})
5943 .addUse(Mul0.getReg(0))
5946 auto Mul1 =
B.buildFMul(
F32, LHS, RCP, Flags);
5948 B.buildFMul(Res, Sel, Mul1, Flags);
5950 MI.eraseFromParent();
5959 unsigned Flags =
MI.getFlags();
5960 assert(!ST.has16BitInsts());
5962 auto Ext =
B.buildFPExt(
F32,
MI.getOperand(1), Flags);
5963 auto Log2 =
B.buildIntrinsic(Intrinsic::amdgcn_sqrt, {
F32})
5964 .addUse(Ext.getReg(0))
5966 B.buildFPTrunc(
MI.getOperand(0),
Log2, Flags);
5967 MI.eraseFromParent();
5977 const unsigned Flags =
MI.getFlags();
5986 MI.eraseFromParent();
5990 auto ScaleThreshold =
B.buildFConstant(
F32, 0x1.0p-96f);
5992 auto ScaleUpFactor =
B.buildFConstant(
F32, 0x1.0p+32f);
5993 auto ScaledX =
B.buildFMul(
F32,
X, ScaleUpFactor, Flags);
5994 auto SqrtX =
B.buildSelect(
F32, NeedScale, ScaledX,
X, Flags);
5999 .addUse(SqrtX.getReg(0))
6002 auto SqrtSInt =
B.buildBitcast(I32, SqrtS);
6003 auto NegOne =
B.buildConstant(I32, -1);
6004 auto SqrtSNextDown =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, NegOne));
6006 auto NegSqrtSNextDown =
B.buildFNeg(
F32, SqrtSNextDown, Flags);
6007 auto SqrtVP =
B.buildFMA(
F32, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
6009 auto PosOne =
B.buildConstant(I32, 1);
6010 auto SqrtSNextUp =
B.buildBitcast(
F32,
B.buildAdd(I32, SqrtSInt, PosOne));
6012 auto NegSqrtSNextUp =
B.buildFNeg(
F32, SqrtSNextUp, Flags);
6013 auto SqrtVS =
B.buildFMA(
F32, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
6015 auto Zero =
B.buildFConstant(
F32, 0.0f);
6019 B.buildSelect(
F32, SqrtVPLE0, SqrtSNextDown, SqrtS, Flags).getReg(0);
6023 B.buildSelect(
F32, SqrtVPVSGT0, SqrtSNextUp, SqrtS, Flags).getReg(0);
6026 B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F32}).addReg(SqrtX.getReg(0));
6027 B.buildFMul(SqrtS, SqrtX, SqrtR, Flags);
6029 auto Half =
B.buildFConstant(
F32, 0.5f);
6030 auto SqrtH =
B.buildFMul(
F32, SqrtR, Half, Flags);
6031 auto NegSqrtH =
B.buildFNeg(
F32, SqrtH, Flags);
6032 auto SqrtE =
B.buildFMA(
F32, NegSqrtH, SqrtS, Half, Flags);
6033 SqrtH =
B.buildFMA(
F32, SqrtH, SqrtE, SqrtH, Flags);
6034 SqrtS =
B.buildFMA(
F32, SqrtS, SqrtE, SqrtS, Flags).getReg(0);
6035 auto NegSqrtS =
B.buildFNeg(
F32, SqrtS, Flags);
6036 auto SqrtD =
B.buildFMA(
F32, NegSqrtS, SqrtS, SqrtX, Flags);
6037 SqrtS =
B.buildFMA(
F32, SqrtD, SqrtH, SqrtS, Flags).getReg(0);
6040 auto ScaleDownFactor =
B.buildFConstant(
F32, 0x1.0p-16f);
6042 auto ScaledDown =
B.buildFMul(
F32, SqrtS, ScaleDownFactor, Flags);
6044 SqrtS =
B.buildSelect(
F32, NeedScale, ScaledDown, SqrtS, Flags).getReg(0);
6047 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtS, Flags);
6049 MI.eraseFromParent();
6084 unsigned Flags =
MI.getFlags();
6089 auto ScaleConstant =
B.buildFConstant(
F64, 0x1.0p-767);
6091 ZeroInt =
B.buildConstant(I32, 0).getReg(0);
6095 auto ScaleUpFactor =
B.buildConstant(I32, 256);
6096 auto ScaleUp =
B.buildSelect(I32, Scaling, ScaleUpFactor, ZeroInt);
6097 SqrtX =
B.buildFLdexp(
F64,
X, ScaleUp, Flags).getReg(0);
6100 auto SqrtY =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {
F64}).addReg(SqrtX);
6102 auto Half =
B.buildFConstant(
F64, 0.5);
6103 auto SqrtH0 =
B.buildFMul(
F64, SqrtY, Half);
6104 auto SqrtS0 =
B.buildFMul(
F64, SqrtX, SqrtY);
6106 auto NegSqrtH0 =
B.buildFNeg(
F64, SqrtH0);
6107 auto SqrtR0 =
B.buildFMA(
F64, NegSqrtH0, SqrtS0, Half);
6109 auto SqrtS1 =
B.buildFMA(
F64, SqrtS0, SqrtR0, SqrtS0);
6110 auto SqrtH1 =
B.buildFMA(
F64, SqrtH0, SqrtR0, SqrtH0);
6112 auto NegSqrtS1 =
B.buildFNeg(
F64, SqrtS1);
6113 auto SqrtD0 =
B.buildFMA(
F64, NegSqrtS1, SqrtS1, SqrtX);
6115 auto SqrtS2 =
B.buildFMA(
F64, SqrtD0, SqrtH1, SqrtS1);
6117 Register SqrtRet = SqrtS2.getReg(0);
6119 auto NegSqrtS2 =
B.buildFNeg(
F64, SqrtS2);
6120 auto SqrtD1 =
B.buildFMA(
F64, NegSqrtS2, SqrtS2, SqrtX);
6121 auto SqrtD2 =
B.buildFMA(
F64, SqrtD1, SqrtH1, SqrtS2);
6124 auto ScaleDownFactor =
B.buildConstant(I32, -128);
6125 auto ScaleDown =
B.buildSelect(I32, Scaling, ScaleDownFactor, ZeroInt);
6126 SqrtRet =
B.buildFLdexp(
F64, SqrtD2, ScaleDown, Flags).getReg(0);
6131 auto ZeroFP =
B.buildFConstant(
F64, 0.0);
6140 B.buildSelect(Dst, IsZeroOrInf, SqrtX, SqrtRet, Flags);
6142 MI.eraseFromParent();
6173 auto Flags =
MI.getFlags();
6185 auto Rsq =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {Ty})
6195 auto ClampMax = UseIEEE ?
B.buildFMinNumIEEE(Ty, Rsq, MaxFlt, Flags) :
6196 B.buildFMinNum(Ty, Rsq, MaxFlt, Flags);
6201 B.buildFMaxNumIEEE(Dst, ClampMax, MinFlt, Flags);
6203 B.buildFMaxNum(Dst, ClampMax, MinFlt, Flags);
6204 MI.eraseFromParent();
6216 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
6217 IID == Intrinsic::amdgcn_permlanex16;
6218 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
6219 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
6220 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
6221 IID == Intrinsic::amdgcn_permlane_up ||
6222 IID == Intrinsic::amdgcn_permlane_down ||
6223 IID == Intrinsic::amdgcn_permlane_xor;
6227 auto LaneOp =
B.buildIntrinsic(IID, {VT}).addUse(Src0);
6229 case Intrinsic::amdgcn_readfirstlane:
6230 case Intrinsic::amdgcn_permlane64:
6231 return LaneOp.getReg(0);
6232 case Intrinsic::amdgcn_readlane:
6233 case Intrinsic::amdgcn_set_inactive:
6234 case Intrinsic::amdgcn_set_inactive_chain_arg:
6235 return LaneOp.addUse(Src1).getReg(0);
6236 case Intrinsic::amdgcn_writelane:
6237 case Intrinsic::amdgcn_permlane_bcast:
6238 case Intrinsic::amdgcn_permlane_up:
6239 case Intrinsic::amdgcn_permlane_down:
6240 case Intrinsic::amdgcn_permlane_xor:
6241 return LaneOp.addUse(Src1).addUse(Src2).getReg(0);
6242 case Intrinsic::amdgcn_permlane16:
6243 case Intrinsic::amdgcn_permlanex16: {
6245 int64_t Src4 =
MI.getOperand(6).getImm();
6246 int64_t Src5 =
MI.getOperand(7).getImm();
6247 return LaneOp.addUse(Src1)
6254 case Intrinsic::amdgcn_mov_dpp8:
6255 return LaneOp.addImm(
MI.getOperand(3).getImm()).getReg(0);
6256 case Intrinsic::amdgcn_update_dpp:
6257 return LaneOp.addUse(Src1)
6258 .addImm(
MI.getOperand(4).getImm())
6259 .addImm(
MI.getOperand(5).getImm())
6260 .addImm(
MI.getOperand(6).getImm())
6261 .addImm(
MI.getOperand(7).getImm())
6271 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
6272 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
6273 IsPermlaneShuffle) {
6274 Src1 =
MI.getOperand(3).getReg();
6275 if (IID == Intrinsic::amdgcn_writelane || IsPermLane16 ||
6276 IsPermlaneShuffle) {
6277 Src2 =
MI.getOperand(4).getReg();
6282 unsigned Size = Ty.getSizeInBits();
6284 unsigned SplitSize = 32;
6285 if (IID == Intrinsic::amdgcn_update_dpp && (
Size % 64 == 0) &&
6286 ST.hasDPALU_DPP() &&
6290 if (
Size == SplitSize) {
6297 bool IsFloat = Ty.getScalarType().isFloat();
6301 Src0 =
B.buildBitcast(IntTy, Src0).getReg(0);
6303 Src1 =
B.buildBitcast(IntTy, Src1).getReg(0);
6305 Src2 =
B.buildBitcast(IntTy, Src2).getReg(0);
6309 Src0 =
B.buildAnyExt(I32, Src0).getReg(0);
6311 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6312 Src1 =
B.buildAnyExt(I32, Src1).getReg(0);
6314 if (IID == Intrinsic::amdgcn_writelane)
6315 Src2 =
B.buildAnyExt(I32, Src2).getReg(0);
6317 Register LaneOpDst = createLaneOp(Src0, Src1, Src2, I32);
6319 B.buildBitcast(DstReg,
B.buildTrunc(IntTy, LaneOpDst));
6321 B.buildTrunc(DstReg, LaneOpDst);
6322 MI.eraseFromParent();
6326 if (
Size % SplitSize != 0)
6330 bool NeedsBitcast =
false;
6331 if (IntTy.isVector()) {
6334 if (EltSize == SplitSize) {
6335 PartialResTy = EltTy;
6336 }
else if (EltSize == 16 || EltSize == 32) {
6337 unsigned NElem = SplitSize / EltSize;
6340 NeedsBitcast =
true;
6345 unsigned NumParts =
Size / SplitSize;
6349 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6350 Src1Parts =
B.buildUnmerge(PartialResTy, Src1);
6352 if (IID == Intrinsic::amdgcn_writelane)
6353 Src2Parts =
B.buildUnmerge(PartialResTy, Src2);
6355 for (
unsigned i = 0; i < NumParts; ++i) {
6356 Src0 = Src0Parts.
getReg(i);
6358 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
6359 Src1 = Src1Parts.
getReg(i);
6361 if (IID == Intrinsic::amdgcn_writelane)
6362 Src2 = Src2Parts.
getReg(i);
6364 PartialRes.
push_back(createLaneOp(Src0, Src1, Src2, PartialResTy));
6367 if (NeedsBitcast || IsFloat)
6370 B.buildMergeLikeInstr(
LLT::integer(IntTy.getSizeInBits()), PartialRes));
6372 B.buildMergeLikeInstr(DstReg, PartialRes);
6374 MI.eraseFromParent();
6382 ST.getTargetLowering()->getImplicitParameterOffset(
6392 B.buildObjectPtrOffset(DstReg, KernargPtrReg,
6393 B.buildConstant(IdxTy,
Offset).getReg(0));
6404 Register Pointer =
MI.getOperand(2).getReg();
6406 Register NumRecords =
MI.getOperand(4).getReg();
6412 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6414 auto ExtStride =
B.buildAnyExt(I32, Stride);
6416 if (ST.has45BitNumRecordsBufferResource()) {
6417 Register Zero =
B.buildConstant(I32, 0).getReg(0);
6421 auto PointerInt =
B.buildPtrToInt(PtrIntTy, Pointer);
6422 auto ExtPointer =
B.buildAnyExtOrTrunc(I64, PointerInt);
6423 auto NumRecordsLHS =
B.buildShl(I64, NumRecords,
B.buildConstant(I32, 57));
6424 Register LowHalf =
B.buildOr(I64, ExtPointer, NumRecordsLHS).getReg(0);
6428 auto NumRecordsRHS =
B.buildLShr(I64, NumRecords,
B.buildConstant(I32, 7));
6429 auto ShiftedStride =
B.buildShl(I32, ExtStride,
B.buildConstant(I32, 12));
6430 auto ExtShiftedStride =
6431 B.buildMergeValues(I64, {Zero, ShiftedStride.getReg(0)});
6432 auto ShiftedFlags =
B.buildShl(I32, Flags,
B.buildConstant(I32, 28));
6433 auto ExtShiftedFlags =
6434 B.buildMergeValues(I64, {Zero, ShiftedFlags.getReg(0)});
6435 auto CombinedFields =
B.buildOr(I64, NumRecordsRHS, ExtShiftedStride);
6437 B.buildOr(I64, CombinedFields, ExtShiftedFlags).getReg(0);
6438 B.buildMergeValues(Result, {LowHalf, HighHalf});
6440 NumRecords =
B.buildTrunc(I32, NumRecords).getReg(0);
6441 auto Unmerge =
B.buildUnmerge(I32, Pointer);
6442 auto LowHalf = Unmerge.getReg(0);
6443 auto HighHalf = Unmerge.getReg(1);
6445 auto AndMask =
B.buildConstant(I32, 0x0000ffff);
6446 auto Masked =
B.buildAnd(I32, HighHalf, AndMask);
6447 auto ShiftConst =
B.buildConstant(I32, 16);
6448 auto ShiftedStride =
B.buildShl(I32, ExtStride, ShiftConst);
6449 auto NewHighHalf =
B.buildOr(I32,
Masked, ShiftedStride);
6450 Register NewHighHalfReg = NewHighHalf.getReg(0);
6451 B.buildMergeValues(Result, {LowHalf, NewHighHalfReg, NumRecords, Flags});
6454 MI.eraseFromParent();
6471 MI.eraseFromParent();
6479 std::optional<uint32_t> KnownSize =
6481 if (KnownSize.has_value())
6482 B.buildConstant(DstReg, *KnownSize);
6500 MI.eraseFromParent();
6507 unsigned AddrSpace)
const {
6509 auto Unmerge =
B.buildUnmerge(I32,
MI.getOperand(2).getReg());
6513 ST.hasGloballyAddressableScratch()) {
6515 B.buildInstr(AMDGPU::S_MOV_B32, {I32},
6516 {
Register(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)})
6518 MRI.
setRegClass(FlatScratchBaseHi, &AMDGPU::SReg_32RegClass);
6520 Register XOR =
B.buildXor(I32, Hi32, FlatScratchBaseHi).getReg(0);
6522 B.buildConstant(I32, 1u << 26));
6527 MI.eraseFromParent();
6537std::pair<Register, unsigned>
6549 bool CheckNUW = ST.hasGFX1250Insts();
6551 MRI, OrigOffset,
nullptr, CheckNUW);
6555 BaseReg =
B.buildPtrToInt(MRI.
getType(OrigOffset), BaseReg).getReg(0);
6565 unsigned Overflow = ImmOffset & ~MaxImm;
6566 ImmOffset -= Overflow;
6567 if ((int32_t)Overflow < 0) {
6568 Overflow += ImmOffset;
6572 if (Overflow != 0) {
6574 BaseReg =
B.buildConstant(I32, Overflow).getReg(0);
6576 auto OverflowVal =
B.buildConstant(I32, Overflow);
6577 BaseReg =
B.buildAdd(I32, BaseReg, OverflowVal).getReg(0);
6582 BaseReg =
B.buildConstant(I32, 0).getReg(0);
6584 return std::pair(BaseReg, ImmOffset);
6591 bool ImageStore)
const {
6599 StoreVT == I16Vec ? Reg :
B.buildBitcast(I16Vec, Reg).getReg(0);
6601 if (ST.hasUnpackedD16VMem()) {
6602 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6605 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6606 WideRegs.
push_back(
B.buildAnyExt(I32, Unmerge.getReg(
I)).getReg(0));
6614 if (ImageStore && ST.hasImageStoreD16Bug()) {
6617 Reg =
B.buildBitcast(I32, RegI16).getReg(0);
6619 PackedRegs.
resize(2,
B.buildUndef(I32).getReg(0));
6626 auto Unmerge =
B.buildUnmerge(I16, RegI16);
6627 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6629 PackedRegs.
resize(6,
B.buildUndef(I16).getReg(0));
6637 auto Unmerge =
B.buildUnmerge(I32, Reg);
6638 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
6640 PackedRegs.
resize(4,
B.buildUndef(I32).getReg(0));
6650 Reg =
B.buildPadVectorWithUndefElements(
6659 bool IsFormat)
const {
6669 VData =
B.buildBitcast(Ty, VData).getReg(0);
6677 if (Ty.isVector()) {
6678 if (Ty.getElementType().getSizeInBits() == 16 && Ty.getNumElements() <= 4) {
6690 bool IsFormat)
const {
6697 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6712 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6715 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
6719 VIndex =
MI.getOperand(3).getReg();
6722 VIndex =
B.buildConstant(I32, 0).getReg(0);
6725 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6726 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6730 Format =
MI.getOperand(5 + OpOffset).getImm();
6734 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6740 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
6741 AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
6742 }
else if (IsFormat) {
6743 Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
6744 AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
6748 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
6751 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
6754 Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
6759 auto MIB =
B.buildInstr(
Opc)
6770 MIB.addImm(AuxiliaryData)
6771 .addImm(HasVIndex ? -1 : 0)
6772 .addMemOperand(MMO);
6774 MI.eraseFromParent();
6780 unsigned ImmOffset,
unsigned Format,
6783 auto MIB =
B.buildInstr(
Opc)
6794 MIB.addImm(AuxiliaryData)
6795 .addImm(HasVIndex ? -1 : 0)
6796 .addMemOperand(MMO);
6802 bool IsTyped)
const {
6816 assert(
MI.getNumExplicitDefs() == 1 ||
MI.getNumExplicitDefs() == 2);
6817 bool IsTFE =
MI.getNumExplicitDefs() == 2;
6819 StatusDst =
MI.getOperand(1).getReg();
6824 Register RSrc =
MI.getOperand(2 + OpOffset).getReg();
6827 const unsigned NumVIndexOps = IsTyped ? 8 : 7;
6830 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps + OpOffset;
6833 VIndex =
MI.getOperand(3 + OpOffset).getReg();
6836 VIndex =
B.buildConstant(I32, 0).getReg(0);
6839 Register VOffset =
MI.getOperand(3 + OpOffset).getReg();
6840 Register SOffset =
MI.getOperand(4 + OpOffset).getReg();
6844 Format =
MI.getOperand(5 + OpOffset).getImm();
6848 unsigned AuxiliaryData =
MI.getOperand(5 + OpOffset).getImm();
6858 Dst =
MI.getOperand(0).getReg();
6859 B.setInsertPt(
B.getMBB(),
MI);
6866 Dst =
MI.getOperand(0).getReg();
6867 B.setInsertPt(
B.getMBB(),
MI);
6871 const bool IsD16 = IsFormat && (EltTy.
getSizeInBits() == 16);
6872 const bool Unpacked = ST.hasUnpackedD16VMem();
6882 Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
6883 AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
6884 }
else if (IsFormat) {
6888 Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16;
6890 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE
6891 : AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
6896 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE
6897 : AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
6900 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE
6901 : AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
6904 Opc = IsTFE ? AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE
6905 : AMDGPU::G_AMDGPU_BUFFER_LOAD;
6911 unsigned NumValueDWords =
divideCeil(Ty.getSizeInBits(), 32);
6912 unsigned NumLoadDWords = NumValueDWords + 1;
6914 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(LoadTy);
6916 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6917 bool IsFloat = Ty.getScalarType().isFloat();
6922 IsFloat ?
B.getMRI()->createGenericVirtualRegister(DstIntTy) : Dst;
6924 Register ExtDst =
B.getMRI()->createGenericVirtualRegister(I32);
6925 B.buildUnmerge({ExtDst, StatusDst}, LoadDstReg);
6926 B.buildTrunc(DstInt, ExtDst);
6927 }
else if (NumValueDWords == 1) {
6928 B.buildUnmerge({DstInt, StatusDst}, LoadDstReg);
6931 for (
unsigned I = 0;
I != NumValueDWords; ++
I)
6932 LoadElts.
push_back(
B.getMRI()->createGenericVirtualRegister(I32));
6934 B.buildUnmerge(LoadElts, LoadDstReg);
6936 B.buildMergeLikeInstr(DstInt, LoadElts);
6939 B.buildBitcast(Dst, DstInt);
6941 (IsD16 && !Ty.isVector())) {
6942 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(I32);
6944 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6945 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6946 B.buildTrunc(Dst, LoadDstReg);
6947 }
else if (Unpacked && IsD16 && Ty.isVector()) {
6949 Register LoadDstReg =
B.getMRI()->createGenericVirtualRegister(UnpackedTy);
6951 Format, AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6952 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
6954 auto Unmerge =
B.buildUnmerge(I32, LoadDstReg);
6956 for (
unsigned I = 0,
N = Unmerge->getNumOperands() - 1;
I !=
N; ++
I)
6957 Repack.
push_back(
B.buildTrunc(EltTy, Unmerge.getReg(
I)).getReg(0));
6958 B.buildMergeLikeInstr(Dst, Repack);
6961 AuxiliaryData, MMO, IsTyped, HasVIndex,
B);
6964 MI.eraseFromParent();
6970 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
6971 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
6972 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
6973 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
6974 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
6975 case Intrinsic::amdgcn_raw_buffer_atomic_add:
6976 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
6977 case Intrinsic::amdgcn_struct_buffer_atomic_add:
6978 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
6979 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
6980 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
6981 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
6982 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
6983 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
6984 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
6985 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
6986 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
6987 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
6988 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
6989 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
6990 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
6991 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
6992 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
6993 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
6994 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
6995 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
6996 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
6997 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
6998 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
6999 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
7000 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
7001 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
7002 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
7003 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
7004 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
7005 case Intrinsic::amdgcn_raw_buffer_atomic_and:
7006 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
7007 case Intrinsic::amdgcn_struct_buffer_atomic_and:
7008 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
7009 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
7010 case Intrinsic::amdgcn_raw_buffer_atomic_or:
7011 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
7012 case Intrinsic::amdgcn_struct_buffer_atomic_or:
7013 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
7014 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
7015 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
7016 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
7017 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
7018 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
7019 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
7020 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
7021 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
7022 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
7023 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
7024 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
7025 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
7026 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
7027 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
7028 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
7029 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
7030 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
7031 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
7032 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
7033 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
7034 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
7035 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
7036 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
7037 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
7038 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
7039 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD;
7040 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
7041 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
7042 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
7043 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
7044 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN;
7045 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
7046 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
7047 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
7048 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
7049 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX;
7050 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
7051 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
7052 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
7053 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
7054 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32;
7055 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
7056 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
7057 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
7058 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
7059 return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32;
7068 const bool IsCmpSwap =
7069 IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
7070 IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap ||
7071 IID == Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap ||
7072 IID == Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap;
7083 CmpVal =
MI.getOperand(3).getReg();
7088 Register RSrc =
MI.getOperand(3 + OpOffset).getReg();
7089 const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
7092 const bool HasVIndex =
MI.getNumOperands() == NumVIndexOps;
7095 VIndex =
MI.getOperand(4 + OpOffset).getReg();
7101 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
7102 Register SOffset =
MI.getOperand(5 + OpOffset).getReg();
7103 unsigned AuxiliaryData =
MI.getOperand(6 + OpOffset).getImm();
7122 .addImm(AuxiliaryData)
7123 .addImm(HasVIndex ? -1 : 0)
7124 .addMemOperand(MMO);
7126 MI.eraseFromParent();
7136 bool IsA16,
bool IsG16) {
7152 (
B.getMRI()->getType(AddrReg) == F16)) {
7157 B.buildBuildVector(
V2F16, {AddrReg, B.buildUndef(F16).getReg(0)})
7161 "Bias needs to be converted to 16 bit in A16 mode");
7163 AddrReg =
B.buildBitcast(
V2F16, AddrReg).getReg(0);
7167 const LLT EltTy =
B.getMRI()->getType(AddrReg);
7171 if (((
I + 1) >= EndIdx) ||
7178 !
MI.getOperand(ArgOffset +
I + 1).isReg()) {
7180 B.buildBuildVector(V2EltTy,
7181 {AddrReg, B.buildUndef(EltTy).getReg(0)})
7186 V2EltTy, {AddrReg, MI.getOperand(ArgOffset + I + 1).getReg()})
7197 int DimIdx,
int NumVAddrs) {
7199 for (
int I = 0;
I != NumVAddrs; ++
I) {
7201 if (
SrcOp.isReg()) {
7204 assert(
B.getMRI()->getType(
Reg).getSizeInBits() == 32);
7205 if (
B.getMRI()->getType(
Reg) != I32)
7206 Reg =
B.buildBitcast(I32,
Reg).getReg(0);
7211 int NumAddrRegs = AddrRegs.
size();
7212 if (NumAddrRegs != 1) {
7213 LLT EltTy =
B.getMRI()->getType(AddrRegs[0]);
7216 MI.getOperand(DimIdx).setReg(VAddr.getReg(0));
7219 for (
int I = 1;
I != NumVAddrs; ++
I) {
7222 MI.getOperand(DimIdx +
I).setReg(AMDGPU::NoRegister);
7244 const unsigned NumDefs =
MI.getNumExplicitDefs();
7245 const unsigned ArgOffset = NumDefs + 1;
7246 bool IsTFE = NumDefs == 2;
7266 VData =
MI.getOperand(NumDefs == 0 ? 1 : 0).getReg();
7270 const bool IsAtomicPacked16Bit =
7271 (BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
7272 BaseOpcode->
BaseOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16);
7279 const bool GradTyIs16 = GradTy == I16 || GradTy == F16;
7280 const bool AddrTyIs16 = AddrTy == I16 || AddrTy == F16;
7281 const bool DataTyIs16 =
7282 Ty.getScalarType() == I16 || Ty.getScalarType() == F16;
7284 ST.hasG16() ? (BaseOpcode->
Gradients && GradTyIs16) : GradTyIs16;
7285 const bool IsA16 = AddrTyIs16;
7286 const bool IsD16 = !IsAtomicPacked16Bit && DataTyIs16;
7289 if (!BaseOpcode->
Atomic) {
7290 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
7293 }
else if (DMask != 0) {
7295 }
else if (!IsTFE && !BaseOpcode->
Store) {
7297 B.buildUndef(
MI.getOperand(0));
7298 MI.eraseFromParent();
7306 const unsigned StoreOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16
7307 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE;
7308 const unsigned LoadOpcode = IsD16 ? AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16
7309 : AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD;
7310 unsigned NewOpcode = LoadOpcode;
7311 if (BaseOpcode->
Store)
7312 NewOpcode = StoreOpcode;
7314 NewOpcode = AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET;
7317 MI.setDesc(
B.getTII().get(NewOpcode));
7321 if (IsTFE && DMask == 0) {
7324 MI.getOperand(ArgOffset + Intr->
DMaskIndex).setImm(DMask);
7327 if (BaseOpcode->
Atomic) {
7332 if (Ty.isVector() && !IsAtomicPacked16Bit)
7339 auto Concat =
B.buildBuildVector(PackedTy, {VData0, VData1});
7340 MI.getOperand(2).setReg(
Concat.getReg(0));
7341 MI.getOperand(3).setReg(AMDGPU::NoRegister);
7345 unsigned CorrectedNumVAddrs = Intr->
NumVAddrs;
7348 if (BaseOpcode->
Gradients && !ST.hasG16() && (IsA16 != IsG16)) {
7354 if (IsA16 && !ST.hasA16()) {
7359 const unsigned NSAMaxSize = ST.getNSAMaxSize(BaseOpcode->
Sampler);
7360 const unsigned HasPartialNSA = ST.hasPartialNSAEncoding();
7362 if (IsA16 || IsG16) {
7370 const bool UseNSA = ST.hasNSAEncoding() &&
7371 PackedRegs.
size() >= ST.getNSAThreshold(MF) &&
7372 (PackedRegs.
size() <= NSAMaxSize || HasPartialNSA);
7373 const bool UsePartialNSA =
7374 UseNSA && HasPartialNSA && PackedRegs.
size() > NSAMaxSize;
7376 if (UsePartialNSA) {
7380 auto Concat =
B.buildConcatVectors(
7381 PackedAddrTy,
ArrayRef(PackedRegs).slice(NSAMaxSize - 1));
7382 PackedRegs[NSAMaxSize - 1] =
Concat.getReg(0);
7383 PackedRegs.
resize(NSAMaxSize);
7384 }
else if (!UseNSA && PackedRegs.
size() > 1) {
7386 auto Concat =
B.buildConcatVectors(PackedAddrTy, PackedRegs);
7387 PackedRegs[0] =
Concat.getReg(0);
7391 const unsigned NumPacked = PackedRegs.
size();
7394 if (!
SrcOp.isReg()) {
7404 SrcOp.setReg(AMDGPU::NoRegister);
7421 const bool UseNSA = ST.hasNSAEncoding() &&
7422 CorrectedNumVAddrs >= ST.getNSAThreshold(MF) &&
7423 (CorrectedNumVAddrs <= NSAMaxSize || HasPartialNSA);
7424 const bool UsePartialNSA =
7425 UseNSA && HasPartialNSA && CorrectedNumVAddrs > NSAMaxSize;
7427 if (UsePartialNSA) {
7429 ArgOffset + Intr->
VAddrStart + NSAMaxSize - 1,
7431 }
else if (!UseNSA && Intr->
NumVAddrs > 1) {
7446 if (!Ty.isVector() || !IsD16)
7450 if (RepackedReg != VData) {
7451 MI.getOperand(1).setReg(RepackedReg);
7459 const int NumElts = Ty.isVector() ? Ty.getNumElements() : 1;
7462 if (NumElts < DMaskLanes)
7465 if (NumElts > 4 || DMaskLanes > 4)
7476 const unsigned AdjustedNumElts = DMaskLanes == 0 ? 1 : DMaskLanes;
7477 const LLT AdjustedTy =
7493 if (IsD16 && ST.hasUnpackedD16VMem()) {
7500 unsigned RoundedElts = (AdjustedTy.
getSizeInBits() + 31) / 32;
7501 unsigned RoundedSize = 32 * RoundedElts;
7505 RegTy = !IsTFE && EltSize == 16 ? V2I16 : I32;
7510 if (!IsTFE && (RoundedTy == Ty || !Ty.
isVector()))
7516 B.setInsertPt(*
MI.getParent(), ++
MI.getIterator());
7520 const LLT LoadResultTy = IsTFE ? TFETy : RoundedTy;
7521 const int ResultNumRegs = LoadResultTy.
getSizeInBits() / 32;
7525 MI.getOperand(0).setReg(NewResultReg);
7533 Dst1Reg =
MI.getOperand(1).getReg();
7534 if (MRI->
getType(Dst1Reg) != I32)
7538 MI.removeOperand(1);
7541 if (!Ty.isVector() && Ty.getSizeInBits() == 32) {
7542 auto Unmerge =
B.buildUnmerge({I32, I32}, NewResultReg);
7543 B.buildBitcast(DstReg, Unmerge.getReg(0));
7544 B.buildCopy(Dst1Reg, Unmerge.getReg(1));
7553 const int NumDataRegs = IsTFE ? ResultNumRegs - 1 : ResultNumRegs;
7555 if (ResultNumRegs == 1) {
7557 ResultRegs[0] = NewResultReg;
7560 for (
int I = 0;
I != NumDataRegs; ++
I)
7562 B.buildUnmerge(ResultRegs, NewResultReg);
7567 ResultRegs.
resize(NumDataRegs);
7572 if (IsD16 && !Ty.isVector()) {
7573 B.buildTrunc(DstReg, ResultRegs[0]);
7578 if ((Ty == V2I16 || Ty ==
V2F16) && NumDataRegs == 1 &&
7579 !ST.hasUnpackedD16VMem()) {
7580 B.buildBitcast(DstReg, ResultRegs[0]);
7592 if (RegTy != V2I16 && !ST.hasUnpackedD16VMem()) {
7594 Reg =
B.buildBitcast(V2I16, Reg).getReg(0);
7595 }
else if (ST.hasUnpackedD16VMem()) {
7597 Reg =
B.buildTrunc(I16, Reg).getReg(0);
7601 auto padWithUndef = [&](
LLT Ty,
int NumElts) {
7605 for (
int I = 0;
I != NumElts; ++
I)
7612 padWithUndef(ResTy, NumElts - ResultRegs.
size());
7613 B.buildBuildVector(DstReg, ResultRegs);
7617 assert(!ST.hasUnpackedD16VMem() && (ResTy == V2I16 || ResTy ==
V2F16));
7618 const int RegsToCover = (Ty.getSizeInBits() + 31) / 32;
7623 if (Ty == V3I16 || Ty == V3F16) {
7625 if (ResultRegs.
size() == 1) {
7626 NewResultReg = ResultRegs[0];
7627 }
else if (ResultRegs.
size() == 2) {
7629 NewResultReg =
B.buildConcatVectors(V4I16, ResultRegs).getReg(0);
7644 B.buildDeleteTrailingVectorElements(ResizeDst, NewResultReg);
7646 B.buildPadVectorWithUndefElements(ResizeDst, NewResultReg);
7648 if (ResizeDst != DstReg)
7649 B.buildBitcast(DstReg, ResizeDst);
7653 padWithUndef(ResTy, RegsToCover - ResultRegs.
size());
7654 B.buildConcatVectors(DstReg, ResultRegs);
7663 Register OrigDst =
MI.getOperand(0).getReg();
7665 LLT Ty =
B.getMRI()->getType(OrigDst);
7666 unsigned Size = Ty.getSizeInBits();
7669 if (
Size < 32 && ST.hasScalarSubwordLoads()) {
7671 Opc =
Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
7672 : AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
7675 Dst =
B.getMRI()->createGenericVirtualRegister(
LLT::integer(32));
7677 Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
7686 B.setInsertPt(
B.getMBB(),
MI);
7691 B.setInsertPt(
B.getMBB(),
MI);
7697 MI.setDesc(
B.getTII().get(
Opc));
7698 MI.removeOperand(1);
7701 const unsigned MemSize = (
Size + 7) / 8;
7702 const Align MemAlign =
B.getDataLayout().getABITypeAlign(
7709 MI.addMemOperand(MF, MMO);
7710 if (Dst != OrigDst) {
7711 MI.getOperand(0).setReg(Dst);
7712 B.setInsertPt(
B.getMBB(), ++
B.getInsertPt());
7713 B.buildTrunc(OrigDst, Dst);
7735 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH));
7736 MI.removeOperand(0);
7746 if (!ST.hasTrapHandler() ||
7750 return ST.supportsGetDoorbellID() ?
7763 MI.eraseFromParent();
7773 BuildMI(*TrapBB, TrapBB->
end(),
DL,
B.getTII().get(AMDGPU::S_ENDPGM))
7775 BuildMI(BB, &
MI,
DL,
B.getTII().get(AMDGPU::S_CBRANCH_EXECNZ))
7779 MI.eraseFromParent();
7788 Register SGPR01(AMDGPU::SGPR0_SGPR1);
7795 ST.getTargetLowering()->getImplicitParameterOffset(
B.getMF(), Param);
7815 B.buildObjectPtrOffset(LoadAddr, KernargPtrReg,
7818 Register Temp =
B.buildLoad(I64, LoadAddr, *MMO).getReg(0);
7819 B.buildCopy(SGPR01, Temp);
7820 B.buildInstr(AMDGPU::S_TRAP)
7823 MI.eraseFromParent();
7834 B.buildCopy(SGPR01, LiveIn);
7835 B.buildInstr(AMDGPU::S_TRAP)
7839 MI.eraseFromParent();
7848 if (ST.hasPrivEnabledTrap2NopBug()) {
7849 ST.getInstrInfo()->insertSimulatedTrap(MRI,
B.getMBB(),
MI,
7851 MI.eraseFromParent();
7855 B.buildInstr(AMDGPU::S_TRAP)
7857 MI.eraseFromParent();
7866 if (!ST.hasTrapHandler() ||
7870 Fn,
"debugtrap handler not supported",
MI.getDebugLoc(),
DS_Warning));
7873 B.buildInstr(AMDGPU::S_TRAP)
7877 MI.eraseFromParent();
7891 Register NodePtr =
MI.getOperand(2).getReg();
7892 Register RayExtent =
MI.getOperand(3).getReg();
7893 Register RayOrigin =
MI.getOperand(4).getReg();
7895 Register RayInvDir =
MI.getOperand(6).getReg();
7898 if (!ST.hasGFX10_AEncoding()) {
7901 Fn,
"intrinsic not supported on subtarget",
MI.getDebugLoc()));
7905 RayExtent =
B.buildBitcast(I32, RayExtent).getReg(0);
7912 const unsigned NumVDataDwords = 4;
7913 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
7914 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
7916 IsGFX12Plus || (ST.hasNSAEncoding() && NumVAddrs <= ST.getNSAMaxSize());
7918 const unsigned BaseOpcodes[2][2] = {
7919 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
7920 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
7921 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
7925 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
7926 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
7927 : AMDGPU::MIMGEncGfx10NSA,
7928 NumVDataDwords, NumVAddrDwords);
7932 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
7933 : AMDGPU::MIMGEncGfx10Default,
7934 NumVDataDwords, NumVAddrDwords);
7939 if (UseNSA && IsGFX11Plus) {
7940 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7941 auto SrcInt =
B.buildBitcast(V3I32, Src);
7942 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7943 auto Merged =
B.buildMergeLikeInstr(
7944 V3I32, {Unmerge.getReg(0), Unmerge.getReg(1), Unmerge.getReg(2)});
7945 Ops.push_back(Merged.getReg(0));
7948 Ops.push_back(NodePtr);
7949 Ops.push_back(RayExtent);
7950 packLanes(RayOrigin);
7953 auto UnmergeRayDir =
7954 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7955 auto UnmergeRayInvDir =
7956 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
7957 auto MergedDir =
B.buildMergeLikeInstr(
7960 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(0),
7961 UnmergeRayDir.getReg(0)}))
7964 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(1),
7965 UnmergeRayDir.getReg(1)}))
7968 I32,
B.buildMergeLikeInstr(V2I16, {UnmergeRayInvDir.getReg(2),
7969 UnmergeRayDir.getReg(2)}))
7971 Ops.push_back(MergedDir.getReg(0));
7974 packLanes(RayInvDir);
7978 auto Unmerge =
B.buildUnmerge({I32, I32}, NodePtr);
7979 Ops.push_back(Unmerge.getReg(0));
7980 Ops.push_back(Unmerge.getReg(1));
7982 Ops.push_back(NodePtr);
7984 Ops.push_back(RayExtent);
7986 auto packLanes = [&
Ops, &I32, &V3I32, &
B](
Register Src) {
7987 auto SrcInt =
B.buildBitcast(V3I32, Src);
7988 auto Unmerge =
B.buildUnmerge({I32, I32, I32}, SrcInt);
7989 Ops.push_back(Unmerge.getReg(0));
7990 Ops.push_back(Unmerge.getReg(1));
7991 Ops.push_back(Unmerge.getReg(2));
7994 packLanes(RayOrigin);
7996 auto UnmergeRayDir =
7997 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayDir));
7998 auto UnmergeRayInvDir =
7999 B.buildUnmerge({I16, I16, I16},
B.buildBitcast(V3I16, RayInvDir));
8003 B.buildMergeLikeInstr(R1,
8004 {UnmergeRayDir.getReg(0), UnmergeRayDir.getReg(1)});
8005 B.buildMergeLikeInstr(
8006 R2, {UnmergeRayDir.getReg(2), UnmergeRayInvDir.getReg(0)});
8007 B.buildMergeLikeInstr(
8008 R3, {UnmergeRayInvDir.getReg(1), UnmergeRayInvDir.getReg(2)});
8014 packLanes(RayInvDir);
8023 Ops.push_back(MergedOps);
8026 auto MIB =
B.buildInstr(AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY)
8035 .addImm(IsA16 ? 1 : 0)
8038 MI.eraseFromParent();
8048 Register DstOrigin =
MI.getOperand(1).getReg();
8050 Register NodePtr =
MI.getOperand(4).getReg();
8051 Register RayExtent =
MI.getOperand(5).getReg();
8052 Register InstanceMask =
MI.getOperand(6).getReg();
8053 Register RayOrigin =
MI.getOperand(7).getReg();
8055 Register Offsets =
MI.getOperand(9).getReg();
8056 Register TDescr =
MI.getOperand(10).getReg();
8058 if (!ST.hasBVHDualAndBVH8Insts()) {
8061 Fn,
"intrinsic not supported on subtarget",
MI.getDebugLoc()));
8066 Intrinsic::amdgcn_image_bvh8_intersect_ray;
8067 const unsigned NumVDataDwords = 10;
8068 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
8070 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
8071 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
8072 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
8075 auto RayExtentInstanceMaskVec =
8076 B.buildMergeLikeInstr(V2I32, {
B.buildBitcast(I32, RayExtent),
8077 B.buildAnyExt(I32, InstanceMask)});
8079 B.buildInstr(IsBVH8 ? AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY
8080 : AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY)
8086 .addUse(RayExtentInstanceMaskVec.getReg(0))
8093 MI.eraseFromParent();
8102 B.buildInstr(AMDGPU::G_AMDGPU_WAVE_ADDRESS, {DstReg}, {StackPtr});
8103 MI.eraseFromParent();
8110 if (!ST.hasArchitectedSGPRs())
8114 auto TTMP8 =
B.buildCopy(I32,
Register(AMDGPU::TTMP8));
8115 auto LSB =
B.buildConstant(I32, 25);
8116 auto Width =
B.buildConstant(I32, 5);
8117 B.buildUbfx(DstReg, TTMP8, LSB, Width);
8118 MI.eraseFromParent();
8126 unsigned Width)
const {
8130 MRI.
setRegClass(DstReg, &AMDGPU::SReg_32RegClass);
8131 B.buildInstr(AMDGPU::S_GETREG_B32_const)
8134 MI.eraseFromParent();
8154 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8158 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {I32},
8161 B.buildMergeLikeInstr(Src, {ModeReg, TrapReg});
8162 MI.eraseFromParent();
8175 auto Unmerge =
B.buildUnmerge({I32, I32},
MI.getOperand(0));
8179 .addReg(Unmerge.getReg(0));
8183 .addReg(Unmerge.getReg(1));
8184 MI.eraseFromParent();
8196 case Intrinsic::amdgcn_icmp: {
8207 if (!Src1Const || Src1Const->Value != 0)
8211 int64_t Pred =
MI.getOperand(4).getImm();
8217 B.buildIntrinsic(Intrinsic::amdgcn_ballot, Dst).addUse(Src0);
8218 MI.eraseFromParent();
8221 case Intrinsic::sponentry:
8227 B.buildInstr(AMDGPU::G_AMDGPU_SPONENTRY).addDef(TmpReg);
8230 B.buildIntToPtr(DstReg, TmpReg);
8231 MI.eraseFromParent();
8233 int FI =
B.getMF().getFrameInfo().CreateFixedObject(
8235 B.buildFrameIndex(
MI.getOperand(0), FI);
8236 MI.eraseFromParent();
8239 case Intrinsic::amdgcn_if:
8240 case Intrinsic::amdgcn_else: {
8243 bool Negated =
false;
8255 std::swap(CondBrTarget, UncondBrTarget);
8257 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8258 if (IntrID == Intrinsic::amdgcn_if) {
8259 B.buildInstr(AMDGPU::SI_IF)
8262 .addMBB(UncondBrTarget);
8264 B.buildInstr(AMDGPU::SI_ELSE)
8267 .addMBB(UncondBrTarget);
8276 B.buildBr(*CondBrTarget);
8281 MI.eraseFromParent();
8282 BrCond->eraseFromParent();
8288 case Intrinsic::amdgcn_loop: {
8291 bool Negated =
false;
8301 std::swap(CondBrTarget, UncondBrTarget);
8303 B.setInsertPt(
B.getMBB(), BrCond->getIterator());
8304 B.buildInstr(AMDGPU::SI_LOOP)
8306 .addMBB(UncondBrTarget);
8311 B.buildBr(*CondBrTarget);
8313 MI.eraseFromParent();
8314 BrCond->eraseFromParent();
8321 case Intrinsic::amdgcn_wave_reduce_min:
8322 case Intrinsic::amdgcn_wave_reduce_umin:
8323 case Intrinsic::amdgcn_wave_reduce_fmin:
8324 case Intrinsic::amdgcn_wave_reduce_max:
8325 case Intrinsic::amdgcn_wave_reduce_umax:
8326 case Intrinsic::amdgcn_wave_reduce_fmax:
8327 case Intrinsic::amdgcn_wave_reduce_add:
8328 case Intrinsic::amdgcn_wave_reduce_fadd:
8329 case Intrinsic::amdgcn_wave_reduce_sub:
8330 case Intrinsic::amdgcn_wave_reduce_fsub:
8331 case Intrinsic::amdgcn_wave_reduce_and:
8332 case Intrinsic::amdgcn_wave_reduce_or:
8333 case Intrinsic::amdgcn_wave_reduce_xor: {
8338 bool IsFPOp = IntrID == Intrinsic::amdgcn_wave_reduce_fmin ||
8339 IntrID == Intrinsic::amdgcn_wave_reduce_fmax ||
8340 IntrID == Intrinsic::amdgcn_wave_reduce_fadd ||
8341 IntrID == Intrinsic::amdgcn_wave_reduce_fsub;
8342 bool NeedsSignExt = IntrID == Intrinsic::amdgcn_wave_reduce_min ||
8343 IntrID == Intrinsic::amdgcn_wave_reduce_max ||
8344 IntrID == Intrinsic::amdgcn_wave_reduce_add ||
8345 IntrID == Intrinsic::amdgcn_wave_reduce_sub;
8353 .addUse(Ext.getReg(0))
8354 .addImm(
MI.getOperand(3).getImm());
8356 B.buildFPTrunc(DstReg, NewDst);
8358 B.buildTrunc(DstReg, NewDst);
8359 MI.eraseFromParent();
8362 case Intrinsic::amdgcn_addrspacecast_nonnull:
8364 case Intrinsic::amdgcn_make_buffer_rsrc:
8366 case Intrinsic::amdgcn_kernarg_segment_ptr:
8369 B.buildConstant(
MI.getOperand(0).getReg(), 0);
8370 MI.eraseFromParent();
8376 case Intrinsic::amdgcn_implicitarg_ptr:
8378 case Intrinsic::amdgcn_workitem_id_x:
8381 case Intrinsic::amdgcn_workitem_id_y:
8384 case Intrinsic::amdgcn_workitem_id_z:
8387 case Intrinsic::amdgcn_workgroup_id_x:
8392 case Intrinsic::amdgcn_workgroup_id_y:
8397 case Intrinsic::amdgcn_workgroup_id_z:
8402 case Intrinsic::amdgcn_cluster_id_x:
8403 return ST.hasClusters() &&
8406 case Intrinsic::amdgcn_cluster_id_y:
8407 return ST.hasClusters() &&
8410 case Intrinsic::amdgcn_cluster_id_z:
8411 return ST.hasClusters() &&
8414 case Intrinsic::amdgcn_cluster_workgroup_id_x:
8415 return ST.hasClusters() &&
8418 case Intrinsic::amdgcn_cluster_workgroup_id_y:
8419 return ST.hasClusters() &&
8422 case Intrinsic::amdgcn_cluster_workgroup_id_z:
8423 return ST.hasClusters() &&
8426 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
8427 return ST.hasClusters() &&
8429 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
8430 return ST.hasClusters() &&
8433 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
8434 return ST.hasClusters() &&
8437 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
8438 return ST.hasClusters() &&
8441 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
8442 return ST.hasClusters() &&
8446 case Intrinsic::amdgcn_wave_id:
8448 case Intrinsic::amdgcn_lds_kernel_id:
8451 case Intrinsic::amdgcn_dispatch_ptr:
8454 case Intrinsic::amdgcn_queue_ptr:
8457 case Intrinsic::amdgcn_implicit_buffer_ptr:
8460 case Intrinsic::amdgcn_dispatch_id:
8463 case Intrinsic::r600_read_ngroups_x:
8467 case Intrinsic::r600_read_ngroups_y:
8470 case Intrinsic::r600_read_ngroups_z:
8473 case Intrinsic::r600_read_local_size_x:
8476 case Intrinsic::r600_read_local_size_y:
8480 case Intrinsic::r600_read_local_size_z:
8483 case Intrinsic::amdgcn_fdiv_fast:
8485 case Intrinsic::amdgcn_is_shared:
8487 case Intrinsic::amdgcn_is_private:
8489 case Intrinsic::amdgcn_wavefrontsize: {
8490 B.buildConstant(
MI.getOperand(0), ST.getWavefrontSize());
8491 MI.eraseFromParent();
8494 case Intrinsic::amdgcn_s_buffer_load:
8496 case Intrinsic::amdgcn_raw_buffer_store:
8497 case Intrinsic::amdgcn_raw_ptr_buffer_store:
8498 case Intrinsic::amdgcn_struct_buffer_store:
8499 case Intrinsic::amdgcn_struct_ptr_buffer_store:
8501 case Intrinsic::amdgcn_raw_buffer_store_format:
8502 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
8503 case Intrinsic::amdgcn_struct_buffer_store_format:
8504 case Intrinsic::amdgcn_struct_ptr_buffer_store_format:
8506 case Intrinsic::amdgcn_raw_tbuffer_store:
8507 case Intrinsic::amdgcn_raw_ptr_tbuffer_store:
8508 case Intrinsic::amdgcn_struct_tbuffer_store:
8509 case Intrinsic::amdgcn_struct_ptr_tbuffer_store:
8511 case Intrinsic::amdgcn_raw_buffer_load:
8512 case Intrinsic::amdgcn_raw_ptr_buffer_load:
8513 case Intrinsic::amdgcn_raw_atomic_buffer_load:
8514 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
8515 case Intrinsic::amdgcn_struct_buffer_load:
8516 case Intrinsic::amdgcn_struct_ptr_buffer_load:
8517 case Intrinsic::amdgcn_struct_atomic_buffer_load:
8518 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load:
8520 case Intrinsic::amdgcn_raw_buffer_load_format:
8521 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
8522 case Intrinsic::amdgcn_struct_buffer_load_format:
8523 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
8525 case Intrinsic::amdgcn_raw_tbuffer_load:
8526 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
8527 case Intrinsic::amdgcn_struct_tbuffer_load:
8528 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
8530 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
8531 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
8532 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
8533 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
8534 case Intrinsic::amdgcn_raw_buffer_atomic_add:
8535 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
8536 case Intrinsic::amdgcn_struct_buffer_atomic_add:
8537 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
8538 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
8539 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
8540 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
8541 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
8542 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
8543 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
8544 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
8545 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
8546 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
8547 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
8548 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
8549 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
8550 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
8551 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
8552 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
8553 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
8554 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
8555 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
8556 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
8557 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
8558 case Intrinsic::amdgcn_raw_buffer_atomic_and:
8559 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
8560 case Intrinsic::amdgcn_struct_buffer_atomic_and:
8561 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
8562 case Intrinsic::amdgcn_raw_buffer_atomic_or:
8563 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
8564 case Intrinsic::amdgcn_struct_buffer_atomic_or:
8565 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
8566 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
8567 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
8568 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
8569 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
8570 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
8571 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
8572 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
8573 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
8574 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
8575 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
8576 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
8577 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
8578 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
8579 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap:
8580 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
8581 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap:
8582 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
8583 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
8584 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
8585 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
8586 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
8587 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
8588 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
8589 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
8590 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
8591 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
8592 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
8593 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
8594 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
8595 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
8596 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
8597 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
8598 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
8599 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
8600 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
8601 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
8603 case Intrinsic::amdgcn_rsq_clamp:
8605 case Intrinsic::amdgcn_image_bvh_intersect_ray:
8607 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
8608 case Intrinsic::amdgcn_image_bvh8_intersect_ray:
8610 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
8611 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
8612 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
8613 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
8614 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
8615 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
8616 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
8617 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
8621 if (IndexArgTy != I64) {
8622 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(I64, Index)
8623 :
B.buildAnyExt(I64, Index);
8624 MI.getOperand(5).setReg(NewIndex.getReg(0));
8628 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
8629 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
8630 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
8631 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
8632 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
8633 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
8634 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
8635 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
8638 if (MRI.
getType(Index) != I32)
8639 MI.getOperand(5).setReg(
B.buildAnyExt(I32, Index).getReg(0));
8642 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
8643 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
8644 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
8645 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
8646 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
8647 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
8648 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
8649 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
8650 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
8652 LLT IdxTy = IntrID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
8656 if (IndexArgTy != IdxTy) {
8657 auto NewIndex = IndexArgTy.
isVector() ?
B.buildBitcast(IdxTy, Index)
8658 :
B.buildAnyExt(IdxTy, Index);
8659 MI.getOperand(7).setReg(NewIndex.getReg(0));
8664 case Intrinsic::amdgcn_fmed3: {
8670 MI.setDesc(
B.getTII().get(AMDGPU::G_AMDGPU_FMED3));
8671 MI.removeOperand(1);
8675 case Intrinsic::amdgcn_readlane:
8676 case Intrinsic::amdgcn_writelane:
8677 case Intrinsic::amdgcn_readfirstlane:
8678 case Intrinsic::amdgcn_permlane16:
8679 case Intrinsic::amdgcn_permlanex16:
8680 case Intrinsic::amdgcn_permlane64:
8681 case Intrinsic::amdgcn_set_inactive:
8682 case Intrinsic::amdgcn_set_inactive_chain_arg:
8683 case Intrinsic::amdgcn_mov_dpp8:
8684 case Intrinsic::amdgcn_update_dpp:
8685 case Intrinsic::amdgcn_permlane_bcast:
8686 case Intrinsic::amdgcn_permlane_up:
8687 case Intrinsic::amdgcn_permlane_down:
8688 case Intrinsic::amdgcn_permlane_xor:
8690 case Intrinsic::amdgcn_s_buffer_prefetch_data:
8692 case Intrinsic::amdgcn_dead: {
8696 MI.eraseFromParent();
8699 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
8700 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
8701 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
8702 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8703 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8704 MI.eraseFromParent();
8706 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
8707 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
8708 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
8709 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8710 B.buildStore(
MI.getOperand(2),
MI.getOperand(1), **
MI.memoperands_begin());
8711 MI.eraseFromParent();
8713 case Intrinsic::amdgcn_av_load_b128:
8714 case Intrinsic::amdgcn_av_store_b128: {
8716 if (!ST.hasFlatGlobalInsts()) {
8717 const char *Name = IntrID == Intrinsic::amdgcn_av_load_b128
8718 ?
"llvm.amdgcn.av.load.b128"
8719 :
"llvm.amdgcn.av.store.b128";
8722 Fn,
Twine(Name) +
" not supported on subtarget",
MI.getDebugLoc()));
8725 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8726 if (IntrID == Intrinsic::amdgcn_av_load_b128)
8727 B.buildLoad(
MI.getOperand(0),
MI.getOperand(2), **
MI.memoperands_begin());
8729 B.buildStore(
MI.getOperand(2),
MI.getOperand(1),
8730 **
MI.memoperands_begin());
8731 MI.eraseFromParent();
8734 case Intrinsic::amdgcn_flat_load_monitor_b32:
8735 case Intrinsic::amdgcn_flat_load_monitor_b64:
8736 case Intrinsic::amdgcn_flat_load_monitor_b128:
8737 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8738 B.buildInstr(AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR)
8739 .add(
MI.getOperand(0))
8740 .add(
MI.getOperand(2))
8741 .addMemOperand(*
MI.memoperands_begin());
8742 MI.eraseFromParent();
8744 case Intrinsic::amdgcn_global_load_monitor_b32:
8745 case Intrinsic::amdgcn_global_load_monitor_b64:
8746 case Intrinsic::amdgcn_global_load_monitor_b128:
8747 assert(
MI.hasOneMemOperand() &&
"Expected IRTranslator to set MemOp!");
8748 B.buildInstr(AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR)
8749 .add(
MI.getOperand(0))
8750 .add(
MI.getOperand(2))
8751 .addMemOperand(*
MI.memoperands_begin());
8752 MI.eraseFromParent();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID)
static LLT getBufferRsrcScalarType(const LLT Ty)
static LegalityPredicate isIllegalRegisterType(const GCNSubtarget &ST, unsigned TypeIdx)
static cl::opt< bool > EnableNewLegality("amdgpu-global-isel-new-legality", cl::desc("Use GlobalISel desired legality, rather than try to use" "rules compatible with selection patterns"), cl::init(false), cl::ReallyHidden)
static MachineInstrBuilder buildExp(MachineIRBuilder &B, const DstOp &Dst, const SrcOp &Src, unsigned Flags)
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src, unsigned Flags)
constexpr std::initializer_list< LLT > AllVectors
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx)
static LegalityPredicate isSmallOddVector(unsigned TypeIdx)
static LegalizeMutation oneMoreElement(unsigned TypeIdx)
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size)
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags)
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty, const LLT MemTy)
Return true if a load or store of the type should be lowered with a bitcast to a different type.
static constexpr unsigned FPEnvModeBitField
static LegalizeMutation getScalarTypeFromMemDesc(unsigned TypeIdx)
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size)
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy, uint64_t AlignInBits, unsigned AddrSpace, unsigned Opcode)
Return true if we should legalize a load by widening an odd sized memory access up to the alignment.
static bool isRegisterVectorElementType(LLT EltTy)
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx)
static LegalityPredicate isWideVec16(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllScalarTypes
static LegalityPredicate isTruncStoreToSizePowerOf2(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS32Vectors
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx)
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B)
Cast a buffer resource (an address space 8 pointer) into a 4xi32, which is the form in which the valu...
static bool isRegisterClassType(const GCNSubtarget &ST, LLT Ty)
static std::pair< Register, Register > emitReciprocalU64(MachineIRBuilder &B, Register Val)
static LLT getBitcastRegisterType(const LLT Ty)
static LLT getBufferRsrcRegisterType(const LLT Ty)
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx)
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI)
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B, MachineRegisterInfo &MRI, unsigned Idx)
Mutates IR (typicaly a load instruction) to use a <4 x s32> as the initial type of the operand idx an...
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI, int64_t C)
static constexpr unsigned SPDenormModeBitField
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS, bool IsLoad, bool IsAtomic)
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static MachineInstr * verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, MachineBasicBlock *&UncondBrTarget, bool &Negated)
static LegalityPredicate numElementsNotEven(unsigned TypeIdx)
constexpr std::initializer_list< LLT > AllS64Vectors
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B, unsigned Idx)
static constexpr unsigned FPEnvTrapBitField
static constexpr unsigned MaxRegisterSize
static bool isRegisterSize(const GCNSubtarget &ST, unsigned Size)
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx)
static bool hasBufferRsrcWorkaround(const LLT Ty)
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, SIModeRegisterDefaults Mode)
constexpr std::initializer_list< LLT > AllS16Vectors
static bool loadStoreBitcastWorkaround(const LLT Ty)
static LLT widenToNextPowerOf2(LLT Ty)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI, int DimIdx, int NumVAddrs)
Convert from separate vaddr components to a single vector address register, and replace the remaining...
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query)
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx)
static LLT getPow2VectorType(LLT Ty)
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc, Register VIndex, Register VOffset, Register SOffset, unsigned ImmOffset, unsigned Format, unsigned AuxiliaryData, MachineMemOperand *MMO, bool IsTyped, bool HasVIndex, MachineIRBuilder &B)
static LLT getPow2ScalarType(LLT Ty)
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx)
static bool isRegisterVectorType(LLT Ty)
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx)
static bool isRegisterType(const GCNSubtarget &ST, LLT Ty)
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< 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 make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
bool legalizeConstHwRegRead(MachineInstr &MI, MachineIRBuilder &B, AMDGPU::Hwreg::Id HwReg, unsigned LowBit, unsigned Width) const
void buildMultiply(LegalizerHelper &Helper, MutableArrayRef< Register > Accum, ArrayRef< Register > Src0, ArrayRef< Register > Src1, bool UsePartialMad64_32, bool SeparateOddAlignedProducts) const
bool legalizeGlobalValue(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeIntrinsicTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeInsert(LegalizerHelper &Helper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register OrigOffset) const
bool legalizeBVHIntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIsAddrSpace(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned AddrSpace) const
bool legalizeUnsignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLZ_ZERO_POISON(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeAtomicCmpXChg(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferStore(MachineInstr &MI, LegalizerHelper &Helper, bool IsTyped, bool IsFormat) const
bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFFREXP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getSegmentAperture(unsigned AddrSpace, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePointerAsRsrcIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
To create a buffer resource from a 64-bit pointer, mask off the upper 32 bits of the pointer and repl...
bool legalizeFlogCommon(MachineInstr &MI, MachineIRBuilder &B) const
bool getLDSKernelId(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExp2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBufferAtomic(MachineInstr &MI, MachineIRBuilder &B, Intrinsic::ID IID) const
void legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg, bool ImageStore=false) const
Handle register layout difference for f16 images for some subtargets.
bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFFloor(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
AMDGPULegalizerInfo(const GCNSubtarget &ST, const GCNTargetMachine &TM)
bool legalizeFDIV32(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFMad(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSBufferPrefetch(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFExp10Unsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFExp(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
bool legalizeFrem(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizePreloadedArgIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeStore(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool buildPCRelGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, int64_t Offset, unsigned GAFlags=SIInstrInfo::MO_NONE) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
bool legalizeFDIV16(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeRsqClampIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafeImpl(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags, bool IsExp10) const
std::pair< Register, Register > getScaledLogInput(MachineIRBuilder &B, Register Src, unsigned Flags) const
bool legalizeFDIVFastIntrin(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
bool legalizeBVHDualOrBVH8IntersectRayIntrinsic(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeInsertVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst, Register Src, unsigned Flags) const
bool legalizeFEXPF64(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeAddrSpaceCast(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtract(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeBufferLoad(MachineInstr &MI, LegalizerHelper &Helper, bool IsFormat, bool IsTyped) const
bool legalizeImplicitArgPtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeMinNumMaxNum(LegalizerHelper &Helper, MachineInstr &MI) const
void legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B, Register DstDivReg, Register DstRemReg, Register Num, Register Den) const
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeSinCos(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeCTLS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWaveID(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFroundeven(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLDSKernelId(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkGroupId(MachineInstr &MI, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ClusterIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterMaxIdPV, AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const
bool legalizeSignedDIV_REM(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeFPow(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFastUnsafeFDIV64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFPTOI(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, bool Signed) const
bool legalizeStackSave(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst, Register Src, bool IsLog10, unsigned Flags) const
bool legalizeKernargMemParameter(MachineInstr &MI, MachineIRBuilder &B, uint64_t Offset, Align Alignment=Align(4)) const
Legalize a value that's loaded from kernel arguments.
bool legalizeImageIntrinsic(MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const
Rewrite image intrinsics to use register layouts expected by the subtarget.
void buildAbsGlobalAddress(Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV, MachineRegisterInfo &MRI) const
bool legalizeGetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool getImplicitArgPtr(Register DstReg, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRT(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
Register getKernargParameterPtr(MachineIRBuilder &B, int64_t Offset) const
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const
bool legalizeFceil(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFSQRTF64(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeLoad(LegalizerHelper &Helper, MachineInstr &MI) const
Register fixStoreSourceType(MachineIRBuilder &B, Register VData, LLT MemTy, bool IsFormat) const
bool legalizeLaneOp(LegalizerHelper &Helper, MachineInstr &MI, Intrinsic::ID IID) const
bool legalizeSetFPEnv(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeWorkitemIDIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const
void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, const TargetRegisterClass *ArgRC, LLT ArgTy) const
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
bool legalizeFlog2(MachineInstr &MI, MachineIRBuilder &B) const
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
bool isModuleEntryFunction() const
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
bool isBottomOfStack() const
bool isEntryFunction() const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
ConstantFP - Floating Point Values [float, double].
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isOne() const
Returns true if this value is exactly +1.0.
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
KnownBits getKnownBits(Register R)
bool hasExternalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr bool isAnyScalar() 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)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
static constexpr LLT float32()
Get a 32-bit IEEE float value.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & unsupported()
The instruction is unsupported.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Remove elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & unsupportedFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy, unsigned NumElts)
Express EltTy vectors strictly using vectors with NumElts elements (or scalars when NumElts equals 1)...
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & widenScalarToNextMultipleOf(unsigned TypeIdx, unsigned Size)
Widen the scalar to the next multiple of Size.
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
GISelValueTracking * getValueTracking() const
@ Legalized
Instruction has been legalized and the MachineFunction changed.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
TypeSize getValue() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineFunction & getMF()
Getter for the function we currently build.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
bool shouldEmitFixup(const GlobalValue *GV) const
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool shouldEmitPCReloc(const GlobalValue *GV) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void truncate(size_type N)
Like resize, but requires that N is less than size().
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
unsigned getPointerSizeInBits(unsigned AS) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
bool isFlatGlobalAddrSpace(unsigned AS)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isGFX11Plus(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
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 scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
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.
std::function< std::pair< unsigned, LLT >(const LegalityQuery &)> LegalizeMutation
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool has_single_bit(T Value) noexcept
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
static constexpr uint64_t encode(Fields... Values)
MIMGBaseOpcode BaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MCRegister getRegister() const
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
bool isZero() const
Returns true if value is all zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.