27#include "llvm/IR/IntrinsicsAMDGPU.h"
35#define DEBUG_TYPE "AMDGPUtti"
39struct AMDGPUImageDMaskIntrinsic {
43#define GET_AMDGPUImageDMaskIntrinsicTable_IMPL
44#include "AMDGPUGenSearchableTables.inc"
55 "nans handled separately");
73 bool AllowI16SExt =
false) {
74 Type *VTy = V.getType();
83 APFloat FloatValue(ConstFloat->getValueAPF());
84 bool LosesInfo =
true;
93 APInt IntValue(ConstInt->getValue());
102 Value *CastCandidate;
109 if (!IsExt && !IsFloat && AllowI16SExt)
122 Type *VTy = V.getType();
131 return Builder.CreateExtractElement(VecCast->
getOperand(0), Idx);
155 Func(Args, OverloadTys);
171 bool RemoveOldIntr = &OldIntr != &InstToReplace;
180static std::optional<Instruction *>
188 if (
const auto *LZMappingInfo =
190 if (
auto *ConstantLod =
192 if (ConstantLod->isZero() || ConstantLod->isNegative()) {
197 II,
II, NewImageDimIntr->
Intr, IC, [&](
auto &Args,
auto &ArgTys) {
198 Args.erase(Args.begin() + ImageDimIntr->LodIndex);
205 if (
const auto *MIPMappingInfo =
207 if (
auto *ConstantMip =
209 if (ConstantMip->isZero()) {
214 II,
II, NewImageDimIntr->
Intr, IC, [&](
auto &Args,
auto &ArgTys) {
215 Args.erase(Args.begin() + ImageDimIntr->MipIndex);
222 if (
const auto *BiasMappingInfo =
224 if (
auto *ConstantBias =
226 if (ConstantBias->isZero()) {
231 II,
II, NewImageDimIntr->
Intr, IC, [&](
auto &Args,
auto &ArgTys) {
232 Args.erase(Args.begin() + ImageDimIntr->BiasIndex);
233 ArgTys.erase(ArgTys.begin() + ImageDimIntr->BiasTyArg);
240 if (
const auto *OffsetMappingInfo =
242 if (
auto *ConstantOffset =
244 if (ConstantOffset->isZero()) {
247 OffsetMappingInfo->NoOffset, ImageDimIntr->
Dim);
249 II,
II, NewImageDimIntr->
Intr, IC, [&](
auto &Args,
auto &ArgTys) {
250 Args.erase(Args.begin() + ImageDimIntr->OffsetIndex);
266 (DimInfo->
MSAA ? 1 : 0);
268 if (ConstantSlice && ConstantSlice->isZero()) {
273 [&](
auto &Args,
auto &ArgTys) {
274 Args.erase(Args.begin() + SliceIndex);
281 if (ST->hasD16Images()) {
287 if (
II.hasOneUse()) {
290 if (
User->getOpcode() == Instruction::FPTrunc &&
294 [&](
auto &Args,
auto &ArgTys) {
297 ArgTys[0] = User->getType();
306 bool AllHalfExtracts =
true;
308 for (
User *U :
II.users()) {
310 if (!Ext || !Ext->hasOneUse()) {
311 AllHalfExtracts =
false;
316 if (!Tr || !Tr->getType()->isHalfTy()) {
317 AllHalfExtracts =
false;
324 if (!ExtractTruncPairs.
empty() && AllHalfExtracts) {
335 OverloadTys[0] = HalfVecTy;
338 M, ImageDimIntr->
Intr, OverloadTys);
340 II.mutateType(HalfVecTy);
341 II.setCalledFunction(HalfDecl);
344 for (
auto &[Ext, Tr] : ExtractTruncPairs) {
345 Value *Idx = Ext->getIndexOperand();
347 Builder.SetInsertPoint(Tr);
349 Value *HalfExtract = Builder.CreateExtractElement(&
II, Idx);
352 Tr->replaceAllUsesWith(HalfExtract);
355 for (
auto &[Ext, Tr] : ExtractTruncPairs) {
366 if (!ST->hasA16() && !ST->hasG16())
371 bool HasSampler = BaseOpcode->
Sampler;
372 bool FloatCoord =
false;
374 bool OnlyDerivatives =
false;
379 bool AllowI16SExt = !HasSampler;
382 OperandIndex < ImageDimIntr->VAddrEnd; OperandIndex++) {
383 Value *Coord =
II.getOperand(OperandIndex);
386 if (OperandIndex < ImageDimIntr->CoordStart ||
391 OnlyDerivatives =
true;
400 if (!OnlyDerivatives && !ST->hasA16())
401 OnlyDerivatives =
true;
404 if (!OnlyDerivatives && ImageDimIntr->
NumBiasArgs != 0) {
407 "Only image instructions with a sampler can have a bias");
409 OnlyDerivatives =
true;
412 if (OnlyDerivatives && (!ST->hasG16() || ImageDimIntr->
GradientStart ==
420 II,
II,
II.getIntrinsicID(), IC, [&](
auto &Args,
auto &ArgTys) {
421 ArgTys[ImageDimIntr->GradientTyArg] = CoordType;
422 if (!OnlyDerivatives) {
423 ArgTys[ImageDimIntr->CoordTyArg] = CoordType;
426 if (ImageDimIntr->NumBiasArgs != 0)
427 ArgTys[ImageDimIntr->BiasTyArg] = Type::getHalfTy(II.getContext());
433 OperandIndex < EndIndex; OperandIndex++) {
435 convertTo16Bit(*II.getOperand(OperandIndex), IC.Builder);
440 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);
441 Args[ImageDimIntr->BiasIndex] = convertTo16Bit(*Bias, IC.Builder);
475 if (
I.hasNoSignedZeros() &&
485 Value *Src =
nullptr;
488 if (Src->getType()->isHalfTy())
505 unsigned VWidth = VTy->getNumElements();
508 for (
int i = VWidth - 1; i > 0; --i) {
530 unsigned VWidth = VTy->getNumElements();
536 SVI->getShuffleMask(ShuffleMask);
538 for (
int I = VWidth - 1;
I > 0; --
I) {
539 if (ShuffleMask.empty()) {
590 unsigned LaneArgIdx)
const {
591 unsigned MaskBits = ST->getWavefrontSizeLog2();
598 if (!
Known.isConstant())
605 Value *LaneArg =
II.getArgOperand(LaneArgIdx);
607 ConstantInt::get(LaneArg->
getType(),
Known.getConstant() & DemandedMask);
608 if (MaskedConst != LaneArg) {
609 II.getOperandUse(LaneArgIdx).set(MaskedConst);
621 CallInst *NewCall =
B.CreateCall(&NewCallee,
Ops, OpBundles);
637 if (ST.isWave32() &&
match(V, W32Pred))
639 if (ST.isWave64() &&
match(V, W64Pred))
648 const auto IID =
II.getIntrinsicID();
649 assert(IID == Intrinsic::amdgcn_readlane ||
650 IID == Intrinsic::amdgcn_readfirstlane ||
651 IID == Intrinsic::amdgcn_permlane64);
661 const bool IsReadLane = (IID == Intrinsic::amdgcn_readlane);
665 Value *LaneID =
nullptr;
667 LaneID =
II.getOperand(1);
681 const auto DoIt = [&](
unsigned OpIdx,
685 Ops.push_back(LaneID);
701 return DoIt(0,
II.getCalledFunction());
705 Type *SrcTy = Src->getType();
711 return DoIt(0, Remangled);
719 return DoIt(1,
II.getCalledFunction());
721 return DoIt(0,
II.getCalledFunction());
732 unsigned Depth = 0) {
742 return CI->getZExtValue();
751 std::optional<unsigned>
LHS =
755 std::optional<unsigned>
RHS =
764 return CI ? std::optional<unsigned>(CI->getZExtValue()) : std::nullopt;
772 unsigned WaveSize = ST.getWavefrontSize();
774 for (
unsigned Lane :
seq(WaveSize)) {
776 if (!Val || *Val >= WaveSize)
785template <
unsigned Period>
787 static_assert(
isPowerOf2_32(Period),
"Period must be a power of two");
788 for (
unsigned I = Period,
E = Ids.
size();
I <
E; ++
I)
789 if (Ids[
I] != Ids[
I % Period] + (
I & ~(Period - 1)))
797 for (
unsigned I = 0;
I <
N; ++
I)
813 return Ids[3] << 6 | Ids[2] << 4 | Ids[1] << 2 | Ids[0];
820 for (
unsigned J = 0; J <
N; ++J)
821 if (Ids[J] != (
N - 1) - J)
833 for (
unsigned J = 1; J < 16; ++J)
834 if (Ids[J] != (Ids[0] + J) % 16)
852 unsigned Mask = Ids[0];
855 for (
unsigned J = 0; J < 16; ++J)
856 if (Ids[J] != (Mask ^ J))
866 unsigned Selector = 0;
867 for (
unsigned J = 0; J < 8; ++J)
868 Selector |= Ids[J] << (J * 3);
877 for (
unsigned J = 0; J < 16; ++J)
878 Sel |=
static_cast<uint64_t>(Ids[J] & 0xF) << (J * 4);
885 if (Ids.
size() != 64)
887 for (
unsigned J = 0; J < 64; ++J)
888 if (Ids[J] != (J ^ 32))
899 for (
unsigned J = 0; J < 16; ++J) {
900 if (Ids[J] < 16 || Ids[J] >= 32)
902 if (Ids[J + 16] != Ids[J] - 16)
913static std::optional<unsigned>
922 unsigned AndMask = 0, OrMask = 0, XorMask = 0;
923 for (
unsigned B = 0;
B < 5; ++
B) {
924 unsigned Bit0 = (Ids[0] >>
B) & 1;
925 unsigned Bit1 = (Ids[1u <<
B] >>
B) & 1;
928 XorMask |= Bit0 <<
B;
936 for (
unsigned I :
seq(32u)) {
937 unsigned Expected = ((
I & AndMask) | OrMask) ^ XorMask;
952static std::optional<unsigned>
963 for (
unsigned I = 0;
I < 32; ++
I)
964 if (Ids[
I] != (
I +
N) % 32)
976 return B.CreateIntrinsic(Intrinsic::amdgcn_update_dpp, {Ty},
978 B.getInt32(0xF),
B.getInt32(0xF),
B.getTrue()});
983 return B.CreateIntrinsic(Intrinsic::amdgcn_mov_dpp8, {Val->
getType()},
984 {Val,
B.getInt32(Selector)});
991 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane16, {Ty},
993 B.getInt32(
Hi),
B.getFalse(),
B.getFalse()});
1001 return B.CreateIntrinsic(Intrinsic::amdgcn_permlanex16, {Ty},
1003 B.getInt32(
Hi),
B.getFalse(),
B.getFalse()});
1011 assert(
DL.getTypeSizeInBits(OrigTy) == 32 &&
1012 "ds_swizzle only supports 32-bit operands");
1016 Src =
B.CreatePtrToInt(Src, I32Ty);
1017 else if (OrigTy != I32Ty)
1018 Src =
B.CreateBitCast(Src, I32Ty);
1019 Value *Result =
B.CreateIntrinsic(Intrinsic::amdgcn_ds_swizzle, {},
1022 return B.CreateIntToPtr(Result, OrigTy);
1023 if (OrigTy != I32Ty)
1024 return B.CreateBitCast(Result, OrigTy);
1030 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane64, {Val->
getType()},
1041 [](
const auto &
E) {
return E.value() ==
E.index(); }))
1065 if (ST.hasDPPRowShare()) {
1070 if (ST.hasDPP() && ST.hasGFX10Insts()) {
1080 if (ST.hasPermlane16Insts()) {
1100 if (ST.hasDsSwizzleRotateMode()) {
1113static std::optional<Instruction *>
1117 if (
DL.getTypeSizeInBits(
II.getType()) != 32)
1118 return std::nullopt;
1120 if (!ST.isWaveSizeKnown())
1121 return std::nullopt;
1123 unsigned WaveSize = ST.getWavefrontSize();
1124 bool IsBpermute =
II.getIntrinsicID() == Intrinsic::amdgcn_ds_bpermute;
1125 Value *Src =
II.getArgOperand(IsBpermute ? 1 : 0);
1126 Value *Index =
II.getArgOperand(IsBpermute ? 0 : 1);
1131 for (
unsigned Lane :
seq(WaveSize)) {
1133 if (!Val || (*Val & 3) || (*Val >> 2) >= WaveSize)
1134 return std::nullopt;
1135 Ids[Lane] = *Val >> 2;
1139 return std::nullopt;
1144 return std::nullopt;
1159 const APInt *Acc =
nullptr;
1167 const APInt *AccumDelta =
nullptr;
1171 Constant *NewAcc = ConstantInt::get(
II.getType(), *Acc + *AccumDelta);
1178std::optional<Instruction *>
1182 case Intrinsic::amdgcn_implicitarg_ptr: {
1183 if (
II.getFunction()->hasFnAttribute(
"amdgpu-no-implicitarg-ptr"))
1185 uint64_t ImplicitArgBytes = ST->getImplicitArgNumBytes(*
II.getFunction());
1187 uint64_t CurrentOrNullBytes =
1188 II.getAttributes().getRetDereferenceableOrNullBytes();
1189 if (CurrentOrNullBytes != 0) {
1192 uint64_t NewBytes = std::max(CurrentOrNullBytes, ImplicitArgBytes);
1195 II.removeRetAttr(Attribute::DereferenceableOrNull);
1199 uint64_t CurrentBytes =
II.getAttributes().getRetDereferenceableBytes();
1200 uint64_t NewBytes = std::max(CurrentBytes, ImplicitArgBytes);
1201 if (NewBytes != CurrentBytes) {
1207 return std::nullopt;
1209 case Intrinsic::amdgcn_rcp: {
1210 Value *Src =
II.getArgOperand(0);
1221 if (
II.isStrictFP())
1239 auto IID = SrcCI->getIntrinsicID();
1244 if (IID == Intrinsic::amdgcn_sqrt || IID == Intrinsic::sqrt) {
1254 SrcCI->getModule(), Intrinsic::amdgcn_rsq, {SrcCI->getType()});
1257 II.setFastMathFlags(InnerFMF);
1259 II.setCalledFunction(NewDecl);
1265 case Intrinsic::amdgcn_sqrt:
1266 case Intrinsic::amdgcn_rsq:
1267 case Intrinsic::amdgcn_tanh: {
1268 Value *Src =
II.getArgOperand(0);
1280 if (IID == Intrinsic::amdgcn_sqrt && Src->getType()->isHalfTy()) {
1282 II.getModule(), Intrinsic::sqrt, {II.getType()});
1283 II.setCalledFunction(NewDecl);
1289 case Intrinsic::amdgcn_log:
1290 case Intrinsic::amdgcn_exp2: {
1291 const bool IsLog = IID == Intrinsic::amdgcn_log;
1292 const bool IsExp = IID == Intrinsic::amdgcn_exp2;
1293 Value *Src =
II.getArgOperand(0);
1303 if (
C->isInfinity()) {
1306 if (!
C->isNegative())
1310 if (IsExp &&
C->isNegative())
1314 if (
II.isStrictFP())
1318 Constant *Quieted = ConstantFP::get(Ty,
C->getValue().makeQuiet());
1323 if (
C->isZero() || (
C->getValue().isDenormal() && Ty->isFloatTy())) {
1325 : ConstantFP::get(Ty, 1.0);
1329 if (IsLog &&
C->isNegative())
1337 case Intrinsic::amdgcn_frexp_mant:
1338 case Intrinsic::amdgcn_frexp_exp: {
1339 Value *Src =
II.getArgOperand(0);
1345 if (IID == Intrinsic::amdgcn_frexp_mant) {
1347 II, ConstantFP::get(
II.getContext(), Significand));
1367 case Intrinsic::amdgcn_class: {
1368 Value *Src0 =
II.getArgOperand(0);
1369 Value *Src1 =
II.getArgOperand(1);
1373 II.getModule(), Intrinsic::is_fpclass, Src0->
getType()));
1376 II.setArgOperand(1, ConstantInt::get(Src1->
getType(),
1397 case Intrinsic::amdgcn_cvt_pkrtz: {
1398 auto foldFPTruncToF16RTZ = [](
Value *Arg) ->
Value * {
1411 return ConstantFP::get(HalfTy, Val);
1414 Value *Src =
nullptr;
1416 if (Src->getType()->isHalfTy())
1423 if (
Value *Src0 = foldFPTruncToF16RTZ(
II.getArgOperand(0))) {
1424 if (
Value *Src1 = foldFPTruncToF16RTZ(
II.getArgOperand(1))) {
1434 case Intrinsic::amdgcn_cvt_pknorm_i16:
1435 case Intrinsic::amdgcn_cvt_pknorm_u16:
1436 case Intrinsic::amdgcn_cvt_pk_i16:
1437 case Intrinsic::amdgcn_cvt_pk_u16: {
1438 Value *Src0 =
II.getArgOperand(0);
1439 Value *Src1 =
II.getArgOperand(1);
1451 case Intrinsic::amdgcn_cvt_off_f32_i4: {
1452 Value* Arg =
II.getArgOperand(0);
1466 constexpr size_t ResValsSize = 16;
1467 static constexpr float ResVals[ResValsSize] = {
1468 0.0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375,
1469 -0.5, -0.4375, -0.375, -0.3125, -0.25, -0.1875, -0.125, -0.0625};
1471 ConstantFP::get(Ty, ResVals[CArg->
getZExtValue() & (ResValsSize - 1)]);
1474 case Intrinsic::amdgcn_ubfe:
1475 case Intrinsic::amdgcn_sbfe: {
1477 Value *Src =
II.getArgOperand(0);
1484 unsigned IntSize = Ty->getIntegerBitWidth();
1489 if ((Width & (IntSize - 1)) == 0) {
1494 if (Width >= IntSize) {
1496 II, 2, ConstantInt::get(CWidth->
getType(), Width & (IntSize - 1)));
1507 ConstantInt::get(COffset->
getType(),
Offset & (IntSize - 1)));
1511 bool Signed = IID == Intrinsic::amdgcn_sbfe;
1513 if (!CWidth || !COffset)
1523 if (
Offset + Width < IntSize) {
1527 RightShift->takeName(&
II);
1534 RightShift->takeName(&
II);
1537 case Intrinsic::amdgcn_exp:
1538 case Intrinsic::amdgcn_exp_row:
1539 case Intrinsic::amdgcn_exp_compr: {
1545 bool IsCompr = IID == Intrinsic::amdgcn_exp_compr;
1547 for (
int I = 0;
I < (IsCompr ? 2 : 4); ++
I) {
1548 if ((!IsCompr && (EnBits & (1 <<
I)) == 0) ||
1549 (IsCompr && ((EnBits & (0x3 << (2 *
I))) == 0))) {
1550 Value *Src =
II.getArgOperand(
I + 2);
1564 case Intrinsic::amdgcn_fmed3: {
1565 Value *Src0 =
II.getArgOperand(0);
1566 Value *Src1 =
II.getArgOperand(1);
1567 Value *Src2 =
II.getArgOperand(2);
1569 for (
Value *Src : {Src0, Src1, Src2}) {
1574 if (
II.isStrictFP())
1611 const APFloat *ConstSrc0 =
nullptr;
1612 const APFloat *ConstSrc1 =
nullptr;
1613 const APFloat *ConstSrc2 =
nullptr;
1618 const bool IsPosInfinity = ConstSrc0 && ConstSrc0->
isPosInfinity();
1638 const bool IsPosInfinity = ConstSrc1 && ConstSrc1->
isPosInfinity();
1661 auto *Quieted = ConstantFP::get(
II.getType(), ConstSrc2->
makeQuiet());
1681 CI->copyFastMathFlags(&
II);
1707 II.setArgOperand(0, Src0);
1708 II.setArgOperand(1, Src1);
1709 II.setArgOperand(2, Src2);
1719 ConstantFP::get(
II.getType(), Result));
1724 if (!ST->hasMed3_16())
1733 IID, {
X->getType()}, {
X,
Y, Z}, &
II,
II.getName());
1741 case Intrinsic::amdgcn_mbcnt_hi:
1746 case Intrinsic::amdgcn_mbcnt_lo: {
1759 if (std::optional<ConstantRange> ExistingRange =
II.getRange()) {
1760 ComputedRange = ComputedRange.
intersectWith(*ExistingRange);
1761 if (ComputedRange == *ExistingRange)
1765 II.addRangeRetAttr(ComputedRange);
1768 case Intrinsic::amdgcn_ballot: {
1769 Value *Arg =
II.getArgOperand(0);
1774 if (Src->isZero()) {
1779 if (ST->isWave32() &&
II.getType()->getIntegerBitWidth() == 64) {
1786 {IC.Builder.getInt32Ty()},
1787 {II.getArgOperand(0)}),
1794 case Intrinsic::amdgcn_wavefrontsize: {
1795 if (ST->isWaveSizeKnown())
1797 II, ConstantInt::get(
II.getType(), ST->getWavefrontSize()));
1800 case Intrinsic::amdgcn_wqm_vote: {
1807 case Intrinsic::amdgcn_kill: {
1809 if (!
C || !
C->getZExtValue())
1815 case Intrinsic::amdgcn_s_sendmsg:
1816 case Intrinsic::amdgcn_s_sendmsghalt: {
1822 Value *M0Val =
II.getArgOperand(1);
1827 uint16_t MsgId, OpId, StreamId;
1828 decodeMsg(MsgImm->getZExtValue(), MsgId, OpId, StreamId, *ST);
1830 if (!msgDoesNotUseM0(MsgId, *ST))
1834 II.dropUBImplyingAttrsAndMetadata();
1838 case Intrinsic::amdgcn_update_dpp: {
1839 Value *Old =
II.getArgOperand(0);
1844 if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
1851 case Intrinsic::amdgcn_permlane16:
1852 case Intrinsic::amdgcn_permlane16_var:
1853 case Intrinsic::amdgcn_permlanex16:
1854 case Intrinsic::amdgcn_permlanex16_var: {
1856 Value *VDstIn =
II.getArgOperand(0);
1861 unsigned int FiIdx = (IID == Intrinsic::amdgcn_permlane16 ||
1862 IID == Intrinsic::amdgcn_permlanex16)
1869 unsigned int BcIdx = FiIdx + 1;
1878 case Intrinsic::amdgcn_wave_shuffle:
1880 case Intrinsic::amdgcn_permlane64:
1881 case Intrinsic::amdgcn_readfirstlane:
1882 case Intrinsic::amdgcn_readlane:
1883 case Intrinsic::amdgcn_ds_bpermute: {
1885 unsigned SrcIdx = IID == Intrinsic::amdgcn_ds_bpermute ? 1 : 0;
1886 const Use &Src =
II.getArgOperandUse(SrcIdx);
1890 if (IID == Intrinsic::amdgcn_readlane &&
1897 if (IID == Intrinsic::amdgcn_ds_bpermute) {
1898 const Use &Lane =
II.getArgOperandUse(0);
1902 II.getModule(), Intrinsic::amdgcn_readlane,
II.getType());
1903 II.setCalledFunction(NewDecl);
1904 II.setOperand(0, Src);
1905 II.setOperand(1, NewLane);
1910 if (IID == Intrinsic::amdgcn_ds_bpermute)
1916 return std::nullopt;
1918 case Intrinsic::amdgcn_wave_match_b32: {
1919 const Use &Src0 =
II.getArgOperandUse(0);
1920 const Use &Src1 =
II.getArgOperandUse(1);
1923 II.getModule(), Intrinsic::amdgcn_ballot,
II.getType());
1930 case Intrinsic::amdgcn_writelane: {
1934 return std::nullopt;
1936 case Intrinsic::amdgcn_trig_preop: {
1939 if (!
II.getType()->isDoubleTy())
1942 Value *Src =
II.getArgOperand(0);
1943 Value *Segment =
II.getArgOperand(1);
1952 if (StrippedSign != Src)
1955 if (
II.isStrictFP())
1977 unsigned Shift = SegmentVal * 53;
1982 static const uint32_t TwoByPi[] = {
1983 0xa2f9836e, 0x4e441529, 0xfc2757d1, 0xf534ddc0, 0xdb629599, 0x3c439041,
1984 0xfe5163ab, 0xdebbc561, 0xb7246e3a, 0x424dd2e0, 0x06492eea, 0x09d1921c,
1985 0xfe1deb1c, 0xb129a73e, 0xe88235f5, 0x2ebb4484, 0xe99c7026, 0xb45f7e41,
1986 0x3991d639, 0x835339f4, 0x9c845f8b, 0xbdf9283b, 0x1ff897ff, 0xde05980f,
1987 0xef2f118b, 0x5a0a6d1f, 0x6d367ecf, 0x27cb09b7, 0x4f463f66, 0x9e5fea2d,
1988 0x7527bac7, 0xebe5f17b, 0x3d0739f7, 0x8a5292ea, 0x6bfb5fb1, 0x1f8d5d08,
1992 unsigned Idx = Shift >> 5;
1993 if (Idx + 2 >= std::size(TwoByPi)) {
1998 unsigned BShift = Shift & 0x1f;
1999 uint64_t Thi =
Make_64(TwoByPi[Idx], TwoByPi[Idx + 1]);
2000 uint64_t Tlo =
Make_64(TwoByPi[Idx + 2], 0);
2002 Thi = (Thi << BShift) | (Tlo >> (64 - BShift));
2006 int Scale = -53 - Shift;
2013 case Intrinsic::amdgcn_sdot2:
2014 case Intrinsic::amdgcn_udot2:
2015 case Intrinsic::amdgcn_sdot4:
2016 case Intrinsic::amdgcn_udot4:
2017 case Intrinsic::amdgcn_sdot8:
2018 case Intrinsic::amdgcn_udot8: {
2019 Value *Src0 =
II.getArgOperand(0);
2020 Value *Src1 =
II.getArgOperand(1);
2024 II.setArgOperand(0, Src1);
2025 II.setArgOperand(1, Src0);
2037 case Intrinsic::amdgcn_sudot4:
2038 case Intrinsic::amdgcn_sudot8: {
2039 Value *Src0 =
II.getArgOperand(1);
2040 Value *Src1 =
II.getArgOperand(3);
2045 Value *Sign0 =
II.getArgOperand(0);
2046 Value *Sign1 =
II.getArgOperand(2);
2047 II.setArgOperand(0, Sign1);
2048 II.setArgOperand(1, Src1);
2049 II.setArgOperand(2, Sign0);
2050 II.setArgOperand(3, Src0);
2062 case Intrinsic::amdgcn_fmul_legacy: {
2063 Value *Op0 =
II.getArgOperand(0);
2064 Value *Op1 =
II.getArgOperand(1);
2066 for (
Value *Src : {Op0, Op1}) {
2087 case Intrinsic::amdgcn_fma_legacy: {
2088 Value *Op0 =
II.getArgOperand(0);
2089 Value *Op1 =
II.getArgOperand(1);
2090 Value *Op2 =
II.getArgOperand(2);
2092 for (
Value *Src : {Op0, Op1, Op2}) {
2114 II.getModule(), Intrinsic::fma,
II.getType()));
2119 case Intrinsic::amdgcn_is_shared:
2120 case Intrinsic::amdgcn_is_private: {
2121 Value *Src =
II.getArgOperand(0);
2131 case Intrinsic::amdgcn_make_buffer_rsrc: {
2132 Value *Src =
II.getArgOperand(0);
2137 std::optional<unsigned> Width = ST->getBufferResourceNumRecordsWidth();
2139 return std::nullopt;
2141 if (
II.getArgOperand(2)->getType() == NumRecordsTy)
2142 return std::nullopt;
2146 Intrinsic::amdgcn_make_buffer_rsrc,
2147 {
II.getType(), Src->getType(), NumRecordsTy}, Args);
2153 II.getAttributes().removeParamAttributes(
II.getContext(), 2));
2157 case Intrinsic::amdgcn_raw_buffer_store_format:
2158 case Intrinsic::amdgcn_struct_buffer_store_format:
2159 case Intrinsic::amdgcn_raw_tbuffer_store:
2160 case Intrinsic::amdgcn_struct_tbuffer_store:
2161 case Intrinsic::amdgcn_image_store_1d:
2162 case Intrinsic::amdgcn_image_store_1darray:
2163 case Intrinsic::amdgcn_image_store_2d:
2164 case Intrinsic::amdgcn_image_store_2darray:
2165 case Intrinsic::amdgcn_image_store_2darraymsaa:
2166 case Intrinsic::amdgcn_image_store_2dmsaa:
2167 case Intrinsic::amdgcn_image_store_3d:
2168 case Intrinsic::amdgcn_image_store_cube:
2169 case Intrinsic::amdgcn_image_store_mip_1d:
2170 case Intrinsic::amdgcn_image_store_mip_1darray:
2171 case Intrinsic::amdgcn_image_store_mip_2d:
2172 case Intrinsic::amdgcn_image_store_mip_2darray:
2173 case Intrinsic::amdgcn_image_store_mip_3d:
2174 case Intrinsic::amdgcn_image_store_mip_cube: {
2179 if (ST->hasDefaultComponentBroadcast())
2181 else if (ST->hasDefaultComponentZero())
2186 int DMaskIdx = getAMDGPUImageDMaskIntrinsic(
II.getIntrinsicID()) ? 1 : -1;
2194 case Intrinsic::amdgcn_prng_b32: {
2195 auto *Src =
II.getArgOperand(0);
2199 return std::nullopt;
2201 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
2202 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
2203 Value *Src0 =
II.getArgOperand(0);
2204 Value *Src1 =
II.getArgOperand(1);
2210 auto getFormatNumRegs = [](
unsigned FormatVal) {
2211 switch (FormatVal) {
2225 bool MadeChange =
false;
2226 unsigned Src0NumElts = getFormatNumRegs(CBSZ);
2227 unsigned Src1NumElts = getFormatNumRegs(BLGP);
2231 if (Src0Ty->getNumElements() > Src0NumElts) {
2238 if (Src1Ty->getNumElements() > Src1NumElts) {
2246 return std::nullopt;
2257 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
2258 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
2259 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
2260 Value *Src0 =
II.getArgOperand(1);
2261 Value *Src1 =
II.getArgOperand(3);
2267 bool MadeChange =
false;
2273 if (Src0Ty->getNumElements() > Src0NumElts) {
2280 if (Src1Ty->getNumElements() > Src1NumElts) {
2288 return std::nullopt;
2305 return std::nullopt;
2318 int DMaskIdx,
bool IsLoad) {
2321 :
II.getOperand(0)->getType());
2322 unsigned VWidth = IIVTy->getNumElements();
2325 Type *EltTy = IIVTy->getElementType();
2337 const unsigned UnusedComponentsAtFront = DemandedElts.
countr_zero();
2342 DemandedElts = (1 << ActiveBits) - 1;
2344 if (UnusedComponentsAtFront > 0) {
2345 static const unsigned InvalidOffsetIdx = 0xf;
2348 switch (
II.getIntrinsicID()) {
2349 case Intrinsic::amdgcn_raw_buffer_load:
2350 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2353 case Intrinsic::amdgcn_s_buffer_load:
2354 case Intrinsic::amdgcn_ptr_s_buffer_load:
2358 if (ActiveBits == 4 && UnusedComponentsAtFront == 1)
2359 OffsetIdx = InvalidOffsetIdx;
2363 case Intrinsic::amdgcn_struct_buffer_load:
2364 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2369 OffsetIdx = InvalidOffsetIdx;
2373 if (OffsetIdx != InvalidOffsetIdx) {
2375 DemandedElts &= ~((1 << UnusedComponentsAtFront) - 1);
2376 auto *
Offset = Args[OffsetIdx];
2377 unsigned SingleComponentSizeInBits =
2379 unsigned OffsetAdd =
2380 UnusedComponentsAtFront * SingleComponentSizeInBits / 8;
2381 auto *OffsetAddVal = ConstantInt::get(
Offset->getType(), OffsetAdd);
2401 unsigned NewDMaskVal = 0;
2402 unsigned OrigLdStIdx = 0;
2403 for (
unsigned SrcIdx = 0; SrcIdx < 4; ++SrcIdx) {
2404 const unsigned Bit = 1 << SrcIdx;
2405 if (!!(DMaskVal & Bit)) {
2406 if (!!DemandedElts[OrigLdStIdx])
2412 if (DMaskVal != NewDMaskVal)
2413 Args[DMaskIdx] = ConstantInt::get(DMask->
getType(), NewDMaskVal);
2416 unsigned NewNumElts = DemandedElts.
popcount();
2420 if (NewNumElts >= VWidth && DemandedElts.
isMask()) {
2422 II.setArgOperand(DMaskIdx, Args[DMaskIdx]);
2434 OverloadTys[0] = NewTy;
2438 for (
unsigned OrigStoreIdx = 0; OrigStoreIdx < VWidth; ++OrigStoreIdx)
2439 if (DemandedElts[OrigStoreIdx])
2442 if (NewNumElts == 1)
2449 II.getIntrinsicID(), OverloadTys, Args);
2456 if (NewNumElts == 1) {
2462 unsigned NewLoadIdx = 0;
2463 for (
unsigned OrigLoadIdx = 0; OrigLoadIdx < VWidth; ++OrigLoadIdx) {
2464 if (!!DemandedElts[OrigLoadIdx])
2480 APInt &UndefElts)
const {
2485 const unsigned FirstElt = DemandedElts.
countr_zero();
2487 const unsigned MaskLen = LastElt - FirstElt + 1;
2489 unsigned OldNumElts = VT->getNumElements();
2490 if (MaskLen == OldNumElts && MaskLen != 1)
2493 Type *EltTy = VT->getElementType();
2501 Value *Src =
II.getArgOperand(0);
2506 II.getOperandBundlesAsDefs(OpBundles);
2523 for (
unsigned I = 0;
I != MaskLen; ++
I) {
2524 if (DemandedElts[FirstElt +
I])
2525 ExtractMask[
I] = FirstElt +
I;
2534 for (
unsigned I = 0;
I != MaskLen; ++
I) {
2535 if (DemandedElts[FirstElt +
I])
2536 InsertMask[FirstElt +
I] =
I;
2548 SimplifyAndSetOp)
const {
2549 switch (
II.getIntrinsicID()) {
2550 case Intrinsic::amdgcn_readfirstlane:
2551 SimplifyAndSetOp(&
II, 0, DemandedElts, UndefElts);
2553 case Intrinsic::amdgcn_raw_buffer_load:
2554 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2555 case Intrinsic::amdgcn_raw_buffer_load_format:
2556 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
2557 case Intrinsic::amdgcn_raw_tbuffer_load:
2558 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
2559 case Intrinsic::amdgcn_s_buffer_load:
2560 case Intrinsic::amdgcn_ptr_s_buffer_load:
2561 case Intrinsic::amdgcn_struct_buffer_load:
2562 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2563 case Intrinsic::amdgcn_struct_buffer_load_format:
2564 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
2565 case Intrinsic::amdgcn_struct_tbuffer_load:
2566 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
2569 if (getAMDGPUImageDMaskIntrinsic(
II.getIntrinsicID())) {
2575 return std::nullopt;
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Value * createPermlane16(IRBuilderBase &B, Value *Val, uint32_t Lo, uint32_t Hi)
Emit v_permlane16 with the precomputed lane-select halves.
static std::optional< unsigned > matchRowSharePattern(ArrayRef< uint8_t > Ids)
Match a row-share pattern: all 16 lanes of each row read the same source lane.
static bool matchMirrorPattern(ArrayRef< uint8_t > Ids)
Match an N-lane reversal (mirror) pattern.
static bool canSafelyConvertTo16Bit(Value &V, bool IsFloat, bool AllowI16SExt=false)
static bool tryBuildShuffleMap(Value *Index, const GCNSubtarget &ST, SmallVectorImpl< uint8_t > &Ids, const DataLayout &DL)
Build the per-lane shuffle map by evaluating Index for every lane in the wave.
static std::optional< unsigned > matchQuadPermPattern(ArrayRef< uint8_t > Ids)
Match a 4-lane (quad) permutation, encoded as the v_mov_b32_dpp QUAD_PERM control word: bits[1:0]=Ids...
static std::optional< unsigned > matchDsSwizzleRotatePattern(ArrayRef< uint8_t > Ids)
Match a GFX9+ DS_SWIZZLE rotate-mode permutation: a cyclic left-rotation of all 32 lanes within each ...
static std::optional< unsigned > matchHalfRowPermPattern(ArrayRef< uint8_t > Ids)
Match an 8-lane arbitrary permutation, encoded as the v_mov_b32_dpp8 24-bit selector (three bits per ...
static std::optional< unsigned > matchRowXMaskPattern(ArrayRef< uint8_t > Ids)
Match an XOR mask pattern within each 16-lane row: Ids[J] == Mask ^ J, with Mask in [1,...
static constexpr auto matchHalfRowMirrorPattern
static Value * createPermlaneX16(IRBuilderBase &B, Value *Val, uint32_t Lo, uint32_t Hi)
Emit v_permlanex16 with the precomputed lane-select halves.
static bool isRowPattern(ArrayRef< uint8_t > Ids)
Match an N-lane row pattern: each lane in [0, N) reads from a source lane in the same N-lane row,...
static bool canContractSqrtToRsq(const FPMathOperator *SqrtOp)
Return true if it's legal to contract llvm.amdgcn.rcp(llvm.sqrt)
static bool isTriviallyUniform(const Use &U)
Return true if we can easily prove that use U is uniform.
static CallInst * rewriteCall(IRBuilderBase &B, CallInst &Old, Function &NewCallee, ArrayRef< Value * > Ops)
static Value * convertTo16Bit(Value &V, InstCombiner::BuilderTy &Builder)
static constexpr auto isFullRowPattern
static constexpr auto isQuadPattern
static APInt trimTrailingZerosInVector(InstCombiner &IC, Value *UseV, Instruction *I)
static uint64_t computePermlane16Masks(ArrayRef< uint8_t > Ids)
Pack a 16-lane permutation into a single 64-bit value: four bits per output lane, lane J in bits [J*4...
static bool matchHalfWaveSwapPattern(ArrayRef< uint8_t > Ids)
Match a half-wave swap: lane J reads from lane J ^ 32.
static bool hasPeriodicLayout(ArrayRef< uint8_t > Ids)
Lanes are partitioned into groups of Period; each group is a translated copy of the first: Ids[I] = I...
static std::optional< Instruction * > tryOptimizeShufflePattern(InstCombiner &IC, IntrinsicInst &II, const GCNSubtarget &ST)
Try to fold a wave_shuffle/ds_bpermute whose lane index is a constant function of the lane ID into a ...
static constexpr auto isHalfRowPattern
static APInt defaultComponentBroadcast(Value *V)
static std::optional< unsigned > matchDsSwizzleBitmaskPattern(ArrayRef< uint8_t > Ids)
Match a DS_SWIZZLE bitmask-mode permutation: dst_lane = ((src_lane & AND) | OR) ^ XOR with each mask ...
static Value * createDsSwizzle(IRBuilderBase &B, Value *Val, unsigned Offset, const DataLayout &DL)
Emit ds_swizzle with the given immediate, bitcasting/converting between pointer/float types and i32 a...
static std::optional< Instruction * > modifyIntrinsicCall(IntrinsicInst &OldIntr, Instruction &InstToReplace, unsigned NewIntr, InstCombiner &IC, std::function< void(SmallVectorImpl< Value * > &, SmallVectorImpl< Type * > &)> Func)
Applies Func(OldIntr.Args, OldIntr.ArgTys), creates intrinsic call with modified arguments (based on ...
static Value * matchShuffleToHWIntrinsic(IRBuilderBase &B, Value *Src, ArrayRef< uint8_t > Ids, const GCNSubtarget &ST, const DataLayout &DL)
Given a shuffle map, try to emit the best hardware intrinsic.
static std::optional< unsigned > matchRowRotatePattern(ArrayRef< uint8_t > Ids)
Match a 16-lane cyclic rotation; returns the rotation amount in [1, 15].
static bool isCrossRowPattern(ArrayRef< uint8_t > Ids)
Match a cross-row permutation suitable for v_permlanex16: every lane in the low 16-lane half reads fr...
static bool isThreadID(const GCNSubtarget &ST, Value *V)
static Value * createUpdateDpp(IRBuilderBase &B, Value *Val, unsigned Ctrl)
Emit v_mov_b32_dpp with the given control word, row/bank masks 0xF, and bound_ctrl=1 so out-of-bounds...
static APFloat fmed3AMDGCN(const APFloat &Src0, const APFloat &Src1, const APFloat &Src2)
static Value * simplifyAMDGCNMemoryIntrinsicDemanded(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, int DMaskIdx=-1, bool IsLoad=true)
Implement SimplifyDemandedVectorElts for amdgcn buffer and image intrinsics.
static std::optional< Instruction * > simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr, IntrinsicInst &II, InstCombiner &IC)
static Instruction * foldConstantIntoDotAccumulator(IntrinsicInst &II, unsigned AccIdx, unsigned ClampIdx, InstCombiner &IC)
Try to fold a constant addition into the accumulator when saturation is disabled.
static Value * createMovDpp8(IRBuilderBase &B, Value *Val, unsigned Selector)
Emit v_mov_b32_dpp8 with the given 24-bit lane selector.
static Value * matchFPExtFromF16(Value *Arg)
Match an fpext from half to float, or a constant we can convert.
static constexpr auto matchFullRowMirrorPattern
static std::optional< unsigned > evalLaneExpr(Value *V, unsigned Lane, const GCNSubtarget &ST, const DataLayout &DL, unsigned Depth=0)
Evaluate V as a function of the lane ID and return its value on Lane, or std::nullopt if V is not a c...
static Value * createPermlane64(IRBuilderBase &B, Value *Val)
Emit v_permlane64 (swap of the two 32-lane halves of a wave64).
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
This file provides the interface for the instcombine pass implementation.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
bool bitwiseIsEqual(const APFloat &RHS) const
bool isPosInfinity() const
APFloat makeQuiet() const
Assuming this is an IEEE-754 NaN value, quiet its signaling bit.
APInt bitcastToAPInt() const
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
void clearBit(unsigned BitPosition)
Set a given bit to 0.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isMask(unsigned numBits) const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
size_t size() const
Get the array size.
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool isTypeLegal(Type *Ty) const override
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
void setAttributes(AttributeList A)
Set the attributes for this call.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantFP * getNaN(Type *Ty, bool Negative=false, uint64_t Payload=0)
static LLVM_ABI ConstantFP * getInfinity(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
This class represents a range of values.
LLVM_ABI ConstantRange add(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an addition of a value in this ran...
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Tagged union holding either a T or a Error.
This class represents an extension of floating point types.
Utility class for floating point operations which can have information about relaxed accuracy require...
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
bool hasApproxFunc() const
Test if this operation allows approximations of math library functions or intrinsics.
LLVM_ABI float getFPAccuracy() const
Get the maximum error permitted by this operation in ULPs.
Convenience struct for specifying and reasoning about fast-math flags.
bool allowContract() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
bool simplifyDemandedLaneMaskArg(InstCombiner &IC, IntrinsicInst &II, unsigned LaneAgIdx) const
Simplify a lane index operand (e.g.
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
Instruction * hoistLaneIntrinsicThroughOperand(InstCombiner &IC, IntrinsicInst &II) const
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
KnownIEEEMode fpenvIEEEMode(const Instruction &I) const
Return KnownIEEEMode::On if we know if the use context can assume "amdgpu-ieee"="true" and KnownIEEEM...
Value * simplifyAMDGCNLaneIntrinsicDemanded(InstCombiner &IC, IntrinsicInst &II, const APInt &DemandedElts, APInt &UndefElts) const
bool canSimplifyLegacyMulToMul(const Instruction &I, const Value *Op0, const Value *Op1, InstCombiner &IC) const
Common base class shared among various IRBuilders.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, const Twine &Name="")
Create a call to the vector.extract intrinsic.
BasicBlock * GetInsertBlock() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateMaxNum(Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create call to the maxnum intrinsic.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateMaximumNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the maximum intrinsic.
Value * CreateMinNum(Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create call to the minnum intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateFAddFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMinimumNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the minimumnum intrinsic.
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
The core instruction combiner logic.
const DataLayout & getDataLayout() const
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
DominatorTree & getDominatorTree() const
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
virtual bool SimplifyDemandedBits(Instruction *I, unsigned OpNo, const APInt &DemandedMask, KnownBits &Known, const SimplifyQuery &Q, unsigned Depth=0)=0
IRBuilder< TargetFolder, IRBuilderInstCombineInserter > BuilderTy
An IRBuilder that automatically inserts new instructions into the worklist.
static Value * stripSignOnlyFPOps(Value *Val)
Ignore all operations which only change the sign of a value, returning the underlying magnitude value...
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
const SimplifyQuery & getSimplifyQuery() const
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void copyFastMathFlags(FastMathFlags FMF)
Convenience function for transferring all fast-math flag values to this instruction,...
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_READONLY const MIMGOffsetMappingInfo * getMIMGOffsetMappingInfo(unsigned Offset)
uint8_t wmmaScaleF8F6F4FormatToNumRegs(unsigned Fmt)
const ImageDimIntrinsicInfo * getImageDimIntrinsicByBaseOpcode(unsigned BaseOpcode, unsigned Dim)
LLVM_READONLY const MIMGMIPMappingInfo * getMIMGMIPMappingInfo(unsigned MIP)
bool isArgPassedInSGPR(const Argument *A)
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY const MIMGBiasMappingInfo * getMIMGBiasMappingInfo(unsigned Bias)
std::optional< APFloat > evaluateRcp(const APFloat &Val)
Evaluate the constant-folded result of v_rcp for Val, accounting for the hardware's denormal flushing...
LLVM_READONLY const MIMGLZMappingInfo * getMIMGLZMappingInfo(unsigned L)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT, SmallVectorImpl< Type * > &OverloadTys, raw_ostream &OS=nulls())
Returns true if FT is a valid function type for intrinsic ID.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()
Match a floating-point negative zero or positive zero.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
ap_match< APFloat > m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
auto m_Value()
Match an arbitrary value and ignore it.
CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_ConstantFP()
Match an arbitrary ConstantFP and ignore it.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM)
Equivalent of C standard library function.
auto dyn_cast_or_null(const Y &Val)
LLVM_READONLY APFloat maxnum(const APFloat &A, const APFloat &B)
Implements IEEE-754 2008 maxNum semantics.
constexpr unsigned MaxAnalysisRecursionDepth
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM)
Returns: X * 2^Exp for integral exponents.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
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...
constexpr int PoisonMaskElem
LLVM_ABI Value * findScalarElement(Value *V, unsigned EltNo)
Given a vector and an element number, see if the scalar value is already around as a register,...
@ NearestTiesToEven
roundTiesToEven.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI Constant * ConstantFoldInstOperands(const Instruction *I, ArrayRef< Constant * > Ops, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
ConstantFoldInstOperands - Attempt to constant fold an instruction with the specified operands.
constexpr uint64_t Make_64(uint32_t High, uint32_t Low)
Make a 64-bit integer from a high / low pair of 32-bit integers.
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, const SimplifyQuery &SQ, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Represent subnormal handling kind for floating point instruction inputs and outputs.
bool isKnownNeverInfOrNaN() const
Return true if it's known this can never be an infinity or nan.
LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a zero.
SimplifyQuery getWithInstruction(const Instruction *I) const
LLVM_ABI bool isUndefValue(Value *V) const
If CanUseUndef is true, returns whether V is undef.