45#define DEBUG_TYPE "vector-combine"
51STATISTIC(NumVecLoad,
"Number of vector loads formed");
52STATISTIC(NumVecCmp,
"Number of vector compares formed");
53STATISTIC(NumVecBO,
"Number of vector binops formed");
54STATISTIC(NumVecCmpBO,
"Number of vector compare + binop formed");
55STATISTIC(NumShufOfBitcast,
"Number of shuffles moved after bitcast");
56STATISTIC(NumScalarOps,
"Number of scalar unary + binary ops formed");
57STATISTIC(NumScalarCmp,
"Number of scalar compares formed");
58STATISTIC(NumScalarIntrinsic,
"Number of scalar intrinsic calls formed");
62 cl::desc(
"Disable all vector combine transforms"));
66 cl::desc(
"Disable binop extract to shuffle transforms"));
70 cl::desc(
"Max number of instructions to scan for vector combining."));
72static const unsigned InvalidIndex = std::numeric_limits<unsigned>::max();
80 bool TryEarlyFoldsOnly)
83 SQ(*
DL, nullptr, &DT, &AC),
84 TryEarlyFoldsOnly(TryEarlyFoldsOnly) {}
91 const TargetTransformInfo &TTI;
92 const DominatorTree &DT;
96 const SimplifyQuery SQ;
100 bool TryEarlyFoldsOnly;
102 InstructionWorklist Worklist;
111 bool vectorizeLoadInsert(Instruction &
I);
112 bool widenSubvectorLoad(Instruction &
I);
113 ExtractElementInst *getShuffleExtract(ExtractElementInst *Ext0,
114 ExtractElementInst *Ext1,
115 unsigned PreferredExtractIndex)
const;
116 bool isExtractExtractCheap(ExtractElementInst *Ext0, ExtractElementInst *Ext1,
117 const Instruction &
I,
118 ExtractElementInst *&ConvertToShuffle,
119 unsigned PreferredExtractIndex);
122 bool foldExtractExtract(Instruction &
I);
123 bool foldInsExtFNeg(Instruction &
I);
124 bool foldInsExtBinop(Instruction &
I);
125 bool foldInsExtVectorToShuffle(Instruction &
I);
126 bool foldBitOpOfCastops(Instruction &
I);
127 bool foldBitOpOfCastConstant(Instruction &
I);
128 bool foldBitcastShuffle(Instruction &
I);
129 bool scalarizeOpOrCmp(Instruction &
I);
130 bool scalarizeVPIntrinsic(Instruction &
I);
131 bool foldExtractedCmps(Instruction &
I);
132 bool foldSelectsFromBitcast(Instruction &
I);
133 bool foldBinopOfReductions(Instruction &
I);
134 bool foldSingleElementStore(Instruction &
I);
135 bool scalarizeLoad(Instruction &
I);
136 bool scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
Value *Ptr);
137 bool scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
Value *Ptr);
138 bool scalarizeExtExtract(Instruction &
I);
139 bool foldConcatOfBoolMasks(Instruction &
I);
140 bool foldPermuteOfBinops(Instruction &
I);
141 bool foldShuffleOfBinops(Instruction &
I);
142 bool foldShuffleOfSelects(Instruction &
I);
143 bool foldShuffleOfCastops(Instruction &
I);
144 bool foldShuffleOfShuffles(Instruction &
I);
145 bool foldPermuteOfIntrinsic(Instruction &
I);
146 bool foldShufflesOfLengthChangingShuffles(Instruction &
I);
147 bool foldShuffleOfIntrinsics(Instruction &
I);
148 bool foldShuffleToIdentity(Instruction &
I);
149 bool foldShuffleFromReductions(Instruction &
I);
150 bool foldShuffleChainsToReduce(Instruction &
I);
151 bool foldCastFromReductions(Instruction &
I);
152 bool foldSignBitReductionCmp(Instruction &
I);
153 bool foldReductionZeroTest(Instruction &
I);
154 bool foldICmpEqZeroVectorReduce(Instruction &
I);
155 bool foldEquivalentReductionCmp(Instruction &
I);
156 bool foldReduceAddCmpZero(Instruction &
I);
157 bool foldSelectShuffle(Instruction &
I,
bool FromReduction =
false);
158 bool foldInterleaveIntrinsics(Instruction &
I);
159 bool foldDeinterleaveIntrinsics(Instruction &
I);
160 bool foldBitcastOfVPLoad(Instruction &
I);
161 bool foldBitOrderReverseAndSwap(Instruction &
I);
162 bool shrinkType(Instruction &
I);
163 bool shrinkLoadForShuffles(Instruction &
I);
164 bool shrinkPhiOfShuffles(Instruction &
I);
166 void replaceValue(Instruction &Old,
Value &New,
bool Erase =
true) {
172 Worklist.pushUsersToWorkList(*NewI);
173 Worklist.pushValue(NewI);
190 SmallPtrSet<Value *, 4> Visited;
195 OpI,
nullptr,
nullptr, [&](
Value *V) {
200 NextInst = NextInst->getNextNode();
205 Worklist.pushUsersToWorkList(*OpI);
206 Worklist.pushValue(OpI);
224 return X->getType() ==
Y->getType() &&
233 Load->getFunction()->hasFnAttribute(Attribute::SanitizeMemTag) ||
239 Type *ScalarTy =
Load->getType()->getScalarType();
241 unsigned MinVectorSize =
TTI.getMinVectorRegisterBitWidth();
242 if (!ScalarSize || !MinVectorSize || MinVectorSize % ScalarSize != 0 ||
249bool VectorCombine::vectorizeLoadInsert(
Instruction &
I) {
275 Value *SrcPtr =
Load->getPointerOperand()->stripPointerCasts();
278 unsigned MinVecNumElts = MinVectorSize / ScalarSize;
279 auto *MinVecTy = VectorType::get(ScalarTy, MinVecNumElts,
false);
280 unsigned OffsetEltIndex = 0;
288 unsigned OffsetBitWidth =
DL->getIndexTypeSizeInBits(SrcPtr->
getType());
289 APInt
Offset(OffsetBitWidth, 0);
299 uint64_t ScalarSizeInBytes = ScalarSize / 8;
300 if (
Offset.urem(ScalarSizeInBytes) != 0)
304 APInt OffsetEltIndexAP =
Offset.udiv(ScalarSizeInBytes);
305 if (OffsetEltIndexAP.
uge(MinVecNumElts))
323 unsigned AS =
Load->getPointerAddressSpace();
342 unsigned OutputNumElts = Ty->getNumElements();
344 assert(OffsetEltIndex < MinVecNumElts &&
"Address offset too big");
345 Mask[0] = OffsetEltIndex;
352 if (OldCost < NewCost || !NewCost.
isValid())
363 replaceValue(
I, *VecLd);
371bool VectorCombine::widenSubvectorLoad(Instruction &
I) {
374 if (!Shuf->isIdentityWithPadding())
380 unsigned OpIndex =
any_of(Shuf->getShuffleMask(), [&NumOpElts](
int M) {
381 return M >= (int)(NumOpElts);
401 unsigned AS =
Load->getPointerAddressSpace();
416 if (OldCost < NewCost || !NewCost.
isValid())
423 replaceValue(
I, *VecLd);
430ExtractElementInst *VectorCombine::getShuffleExtract(
431 ExtractElementInst *Ext0, ExtractElementInst *Ext1,
435 assert(Index0C && Index1C &&
"Expected constant extract indexes");
437 unsigned Index0 = Index0C->getZExtValue();
438 unsigned Index1 = Index1C->getZExtValue();
441 if (Index0 == Index1)
465 if (PreferredExtractIndex == Index0)
467 if (PreferredExtractIndex == Index1)
471 return Index0 > Index1 ? Ext0 : Ext1;
479bool VectorCombine::isExtractExtractCheap(ExtractElementInst *Ext0,
480 ExtractElementInst *Ext1,
481 const Instruction &
I,
482 ExtractElementInst *&ConvertToShuffle,
483 unsigned PreferredExtractIndex) {
486 assert(Ext0IndexC && Ext1IndexC &&
"Expected constant extract indexes");
488 unsigned Opcode =
I.getOpcode();
501 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
502 "Expected a compare");
512 unsigned Ext0Index = Ext0IndexC->getZExtValue();
513 unsigned Ext1Index = Ext1IndexC->getZExtValue();
527 unsigned BestExtIndex = Extract0Cost > Extract1Cost ? Ext0Index : Ext1Index;
528 unsigned BestInsIndex = Extract0Cost > Extract1Cost ? Ext1Index : Ext0Index;
529 InstructionCost CheapExtractCost = std::min(Extract0Cost, Extract1Cost);
534 if (Ext0Src == Ext1Src && Ext0Index == Ext1Index) {
539 bool HasUseTax = Ext0 == Ext1 ? !Ext0->
hasNUses(2)
541 OldCost = CheapExtractCost + ScalarOpCost;
542 NewCost = VectorOpCost + CheapExtractCost + HasUseTax * CheapExtractCost;
546 OldCost = Extract0Cost + Extract1Cost + ScalarOpCost;
547 NewCost = VectorOpCost + CheapExtractCost +
552 ConvertToShuffle = getShuffleExtract(Ext0, Ext1, PreferredExtractIndex);
553 if (ConvertToShuffle) {
565 SmallVector<int> ShuffleMask(FixedVecTy->getNumElements(),
567 ShuffleMask[BestInsIndex] = BestExtIndex;
569 VecTy, VecTy, ShuffleMask,
CostKind, 0,
570 nullptr, {ConvertToShuffle});
573 VecTy, VecTy, {},
CostKind, 0,
nullptr,
578 LLVM_DEBUG(
dbgs() <<
"Found a binop of extractions: " <<
I <<
"\n OldCost: "
579 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
584 return OldCost < NewCost;
596 ShufMask[NewIndex] = OldIndex;
597 return Builder.CreateShuffleVector(Vec, ShufMask,
"shift");
649 V1,
"foldExtExtBinop");
654 VecBOInst->copyIRFlags(&
I);
660bool VectorCombine::foldExtractExtract(Instruction &
I) {
681 unsigned NumElts = FixedVecTy->getNumElements();
682 if (C0 >= NumElts || C1 >= NumElts)
698 ExtractElementInst *ExtractToChange;
699 if (isExtractExtractCheap(Ext0, Ext1,
I, ExtractToChange, InsertIndex))
705 if (ExtractToChange) {
706 unsigned CheapExtractIdx = ExtractToChange == Ext0 ? C1 : C0;
711 if (ExtractToChange == Ext0)
720 ? foldExtExtCmp(ExtOp0, ExtOp1, ExtIndex,
I)
721 : foldExtExtBinop(ExtOp0, ExtOp1, ExtIndex,
I);
724 replaceValue(
I, *NewExt);
730bool VectorCombine::foldInsExtFNeg(Instruction &
I) {
733 uint64_t ExtIdx, InsIdx;
748 auto *DstVecScalarTy = DstVecTy->getScalarType();
750 if (!SrcVecTy || DstVecScalarTy != SrcVecTy->getScalarType())
755 unsigned NumDstElts = DstVecTy->getNumElements();
756 unsigned NumSrcElts = SrcVecTy->getNumElements();
757 if (ExtIdx > NumSrcElts || InsIdx >= NumDstElts || NumDstElts == 1)
763 SmallVector<int>
Mask(NumDstElts);
764 std::iota(
Mask.begin(),
Mask.end(), 0);
765 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
781 bool NeedLenChg = SrcVecTy->getNumElements() != NumDstElts;
784 SmallVector<int> SrcMask;
787 SrcMask[ExtIdx % NumDstElts] = ExtIdx;
789 DstVecTy, SrcVecTy, SrcMask,
CostKind);
793 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
795 if (NewCost > OldCost)
798 Value *NewShuf, *LenChgShuf =
nullptr;
812 replaceValue(
I, *NewShuf);
818bool VectorCombine::foldInsExtBinop(Instruction &
I) {
819 BinaryOperator *VecBinOp, *SclBinOp;
851 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
853 if (NewCost > OldCost)
864 NewInst->copyIRFlags(VecBinOp);
865 NewInst->andIRFlags(SclBinOp);
870 replaceValue(
I, *NewBO);
876bool VectorCombine::foldBitOpOfCastops(Instruction &
I) {
879 if (!BinOp || !BinOp->isBitwiseLogicOp())
885 if (!LHSCast || !RHSCast) {
886 LLVM_DEBUG(
dbgs() <<
" One or both operands are not cast instructions\n");
892 if (CastOpcode != RHSCast->getOpcode())
896 switch (CastOpcode) {
897 case Instruction::BitCast:
898 case Instruction::Trunc:
899 case Instruction::SExt:
900 case Instruction::ZExt:
906 Value *LHSSrc = LHSCast->getOperand(0);
907 Value *RHSSrc = RHSCast->getOperand(0);
913 auto *SrcTy = LHSSrc->
getType();
914 auto *DstTy =
I.getType();
917 if (CastOpcode != Instruction::BitCast &&
922 if (!SrcTy->getScalarType()->isIntegerTy() ||
923 !DstTy->getScalarType()->isIntegerTy())
938 LHSCastCost + RHSCastCost;
949 if (!LHSCast->hasOneUse())
950 NewCost += LHSCastCost;
951 if (!RHSCast->hasOneUse())
952 NewCost += RHSCastCost;
955 <<
" NewCost=" << NewCost <<
"\n");
957 if (NewCost > OldCost)
962 BinOp->getName() +
".inner");
964 NewBinOp->copyIRFlags(BinOp);
978 replaceValue(
I, *Result);
987bool VectorCombine::foldBitOpOfCastConstant(Instruction &
I) {
1003 switch (CastOpcode) {
1004 case Instruction::BitCast:
1005 case Instruction::ZExt:
1006 case Instruction::SExt:
1007 case Instruction::Trunc:
1013 Value *LHSSrc = LHSCast->getOperand(0);
1015 auto *SrcTy = LHSSrc->
getType();
1016 auto *DstTy =
I.getType();
1019 if (CastOpcode != Instruction::BitCast &&
1024 if (!SrcTy->getScalarType()->isIntegerTy() ||
1025 !DstTy->getScalarType()->isIntegerTy())
1029 PreservedCastFlags RHSFlags;
1054 if (!LHSCast->hasOneUse())
1055 NewCost += LHSCastCost;
1057 LLVM_DEBUG(
dbgs() <<
"foldBitOpOfCastConstant: OldCost=" << OldCost
1058 <<
" NewCost=" << NewCost <<
"\n");
1060 if (NewCost > OldCost)
1065 LHSSrc, InvC,
I.getName() +
".inner");
1067 NewBinOp->copyIRFlags(&
I);
1087 replaceValue(
I, *Result);
1094bool VectorCombine::foldBitcastShuffle(Instruction &
I) {
1108 if (!DestTy || !SrcTy)
1111 unsigned DestEltSize = DestTy->getScalarSizeInBits();
1112 unsigned SrcEltSize = SrcTy->getScalarSizeInBits();
1113 if (SrcTy->getPrimitiveSizeInBits() % DestEltSize != 0)
1123 if (!(BCTy0 && BCTy0->getElementType() == DestTy->getElementType()) &&
1124 !(BCTy1 && BCTy1->getElementType() == DestTy->getElementType()))
1128 SmallVector<int, 16> NewMask;
1129 if (DestEltSize <= SrcEltSize) {
1132 if (SrcEltSize % DestEltSize != 0)
1134 unsigned ScaleFactor = SrcEltSize / DestEltSize;
1139 if (DestEltSize % SrcEltSize != 0)
1141 unsigned ScaleFactor = DestEltSize / SrcEltSize;
1148 unsigned NumSrcElts = SrcTy->getPrimitiveSizeInBits() / DestEltSize;
1149 auto *NewShuffleTy =
1151 auto *OldShuffleTy =
1153 unsigned NumOps = IsUnary ? 1 : 2;
1163 TargetTransformInfo::CastContextHint::None,
1168 TargetTransformInfo::CastContextHint::None,
1171 LLVM_DEBUG(
dbgs() <<
"Found a bitcasted shuffle: " <<
I <<
"\n OldCost: "
1172 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
1174 if (NewCost > OldCost || !NewCost.
isValid())
1182 replaceValue(
I, *Shuf);
1189bool VectorCombine::scalarizeVPIntrinsic(Instruction &
I) {
1203 if (!ScalarOp0 || !ScalarOp1)
1211 auto IsAllTrueMask = [](
Value *MaskVal) {
1214 return ConstValue->isAllOnesValue();
1228 SmallVector<int>
Mask;
1230 Mask.resize(FVTy->getNumElements(), 0);
1239 Args.push_back(
V->getType());
1240 IntrinsicCostAttributes
Attrs(IntrID, VecTy, Args);
1245 std::optional<unsigned> FunctionalOpcode =
1247 std::optional<Intrinsic::ID> ScalarIntrID = std::nullopt;
1248 if (!FunctionalOpcode) {
1257 IntrinsicCostAttributes
Attrs(*ScalarIntrID, VecTy->getScalarType(), Args);
1267 InstructionCost NewCost = ScalarOpCost + SplatCost + CostToKeepSplats;
1269 LLVM_DEBUG(
dbgs() <<
"Found a VP Intrinsic to scalarize: " << VPI
1272 <<
", Cost of scalarizing:" << NewCost <<
"\n");
1275 if (OldCost < NewCost || !NewCost.
isValid())
1286 bool SafeToSpeculate;
1292 *FunctionalOpcode, &VPI,
nullptr, SQ.
AC, SQ.
DT);
1293 if (!SafeToSpeculate &&
1300 {ScalarOp0, ScalarOp1})
1302 ScalarOp0, ScalarOp1);
1311bool VectorCombine::scalarizeOpOrCmp(Instruction &
I) {
1316 if (!UO && !BO && !CI && !
II)
1324 if (Arg->getType() !=
II->getType() &&
1334 for (User *U :
I.users())
1341 std::optional<uint64_t>
Index;
1343 auto Ops =
II ?
II->args() :
I.operands();
1347 uint64_t InsIdx = 0;
1352 if (OpTy->getElementCount().getKnownMinValue() <= InsIdx)
1358 else if (InsIdx != *Index)
1375 if (!
Index.has_value())
1379 Type *ScalarTy = VecTy->getScalarType();
1380 assert(VecTy->isVectorTy() &&
1383 "Unexpected types for insert element into binop or cmp");
1385 unsigned Opcode =
I.getOpcode();
1393 }
else if (UO || BO) {
1397 IntrinsicCostAttributes ScalarICA(
1398 II->getIntrinsicID(), ScalarTy,
1401 IntrinsicCostAttributes VectorICA(
1402 II->getIntrinsicID(), VecTy,
1409 Value *NewVecC =
nullptr;
1411 NewVecC =
simplifyCmpInst(CI->getPredicate(), VecCs[0], VecCs[1], SQ);
1414 simplifyUnOp(UO->getOpcode(), VecCs[0], UO->getFastMathFlags(), SQ);
1416 NewVecC =
simplifyBinOp(BO->getOpcode(), VecCs[0], VecCs[1], SQ);
1430 for (
auto [Idx,
Op, VecC, Scalar] :
enumerate(
Ops, VecCs, ScalarOps)) {
1432 II->getIntrinsicID(), Idx, &
TTI)))
1435 Instruction::InsertElement, VecTy,
CostKind, *Index, VecC, Scalar);
1436 OldCost += InsertCost;
1437 NewCost += !
Op->hasOneUse() * InsertCost;
1441 if (OldCost < NewCost || !NewCost.
isValid())
1451 ++NumScalarIntrinsic;
1454 for (
auto [OpIdx, Scalar, VecC] :
enumerate(ScalarOps, VecCs))
1461 Scalar = Builder.
CreateCmp(CI->getPredicate(), ScalarOps[0], ScalarOps[1]);
1467 Scalar->setName(
I.getName() +
".scalar");
1472 ScalarInst->copyIRFlags(&
I);
1475 replaceValue(
I, *Insert);
1482bool VectorCombine::foldExtractedCmps(Instruction &
I) {
1487 if (!BI || !
I.getType()->isIntegerTy(1))
1492 Value *
B0 =
I.getOperand(0), *
B1 =
I.getOperand(1);
1495 CmpPredicate
P0,
P1;
1507 uint64_t Index0, Index1;
1514 ExtractElementInst *ConvertToShuf = getShuffleExtract(Ext0, Ext1,
CostKind);
1517 assert((ConvertToShuf == Ext0 || ConvertToShuf == Ext1) &&
1518 "Unknown ExtractElementInst");
1523 unsigned CmpOpcode =
1529 if (Index0 >= VecTy->getNumElements() || Index1 >= VecTy->getNumElements())
1541 Ext0Cost + Ext1Cost + CmpCost * 2 +
1547 int CheapIndex = ConvertToShuf == Ext0 ? Index1 : Index0;
1548 int ExpensiveIndex = ConvertToShuf == Ext0 ? Index0 : Index1;
1553 ShufMask[CheapIndex] = ExpensiveIndex;
1558 NewCost += Ext0->
hasOneUse() ? 0 : Ext0Cost;
1559 NewCost += Ext1->
hasOneUse() ? 0 : Ext1Cost;
1564 if (OldCost < NewCost || !NewCost.
isValid())
1574 Value *
LHS = ConvertToShuf == Ext0 ? Shuf : VCmp;
1575 Value *
RHS = ConvertToShuf == Ext0 ? VCmp : Shuf;
1578 replaceValue(
I, *NewExt);
1605bool VectorCombine::foldSelectsFromBitcast(Instruction &
I) {
1612 if (!SrcVecTy || !DstVecTy)
1622 if (SrcEltBits != 32 && SrcEltBits != 64)
1625 if (!DstEltTy->
isIntegerTy() || DstEltBits >= SrcEltBits)
1642 if (!ScalarSelCost.
isValid() || ScalarSelCost == 0)
1645 unsigned MinSelects = (VecSelCost.
getValue() / ScalarSelCost.
getValue()) + 1;
1648 if (!BC->hasNUsesOrMore(MinSelects))
1653 DenseMap<Value *, SmallVector<SelectInst *, 8>> CondToSelects;
1655 for (User *U : BC->users()) {
1660 for (User *ExtUser : Ext->users()) {
1664 Cond->getType()->isIntegerTy(1))
1669 if (CondToSelects.
empty())
1672 bool MadeChange =
false;
1673 Value *SrcVec = BC->getOperand(0);
1676 for (
auto [
Cond, Selects] : CondToSelects) {
1678 if (Selects.size() < MinSelects) {
1679 LLVM_DEBUG(
dbgs() <<
"VectorCombine: foldSelectsFromBitcast not "
1680 <<
"profitable (VecCost=" << VecSelCost
1681 <<
", ScalarCost=" << ScalarSelCost
1682 <<
", NumSelects=" << Selects.size() <<
")\n");
1687 auto InsertPt = std::next(BC->getIterator());
1691 InsertPt = std::next(CondInst->getIterator());
1699 for (SelectInst *Sel : Selects) {
1701 Value *Idx = Ext->getIndexOperand();
1705 replaceValue(*Sel, *NewExt);
1710 <<
" selects into vector select\n");
1724 unsigned ReductionOpc =
1730 CostBeforeReduction =
1731 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, ExtType,
1733 CostAfterReduction =
1734 TTI.getExtendedReductionCost(ReductionOpc, IsUnsigned,
II.getType(),
1738 if (RedOp &&
II.getIntrinsicID() == Intrinsic::vector_reduce_add &&
1744 (Op0->
getOpcode() == RedOp->getOpcode() || Op0 == Op1)) {
1751 TTI.getCastInstrCost(Op0->
getOpcode(), MulType, ExtType,
1754 TTI.getArithmeticInstrCost(Instruction::Mul, MulType,
CostKind);
1756 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, MulType,
1759 CostBeforeReduction = ExtCost * 2 + MulCost + Ext2Cost;
1760 CostAfterReduction =
TTI.getMulAccReductionCost(
1761 IsUnsigned, ReductionOpc,
II.getType(), ExtType,
CostKind);
1764 CostAfterReduction =
TTI.getArithmeticReductionCost(ReductionOpc, VecRedTy,
1768bool VectorCombine::foldBinopOfReductions(Instruction &
I) {
1771 if (BinOpOpc == Instruction::Sub)
1772 ReductionIID = Intrinsic::vector_reduce_add;
1776 if (ReductionIID == Intrinsic::vector_reduce_fadd ||
1777 ReductionIID == Intrinsic::vector_reduce_fmul)
1780 auto checkIntrinsicAndGetItsArgument = [](
Value *
V,
1785 if (
II->getIntrinsicID() == IID &&
II->hasOneUse())
1786 return II->getArgOperand(0);
1790 Value *V0 = checkIntrinsicAndGetItsArgument(
I.getOperand(0), ReductionIID);
1793 Value *
V1 = checkIntrinsicAndGetItsArgument(
I.getOperand(1), ReductionIID);
1798 if (
V1->getType() != VTy)
1802 unsigned ReductionOpc =
1815 CostOfRedOperand0 + CostOfRedOperand1 +
1818 if (NewCost >= OldCost || !NewCost.
isValid())
1822 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
1825 if (BinOpOpc == Instruction::Or)
1832 replaceValue(
I, *Rdx);
1840 unsigned NumScanned = 0;
1841 return std::any_of(Begin, End, [&](
const Instruction &Instr) {
1850class ScalarizationResult {
1851 enum class StatusTy { Unsafe, Safe, SafeWithFreeze };
1856 ScalarizationResult(StatusTy Status,
Value *ToFreeze =
nullptr)
1857 : Status(Status), ToFreeze(ToFreeze) {}
1860 ScalarizationResult(
const ScalarizationResult &
Other) =
default;
1861 ~ScalarizationResult() {
1862 assert(!ToFreeze &&
"freeze() not called with ToFreeze being set");
1865 static ScalarizationResult unsafe() {
return {StatusTy::Unsafe}; }
1866 static ScalarizationResult safe() {
return {StatusTy::Safe}; }
1867 static ScalarizationResult safeWithFreeze(
Value *ToFreeze) {
1868 return {StatusTy::SafeWithFreeze, ToFreeze};
1872 bool isSafe()
const {
return Status == StatusTy::Safe; }
1874 bool isUnsafe()
const {
return Status == StatusTy::Unsafe; }
1877 bool isSafeWithFreeze()
const {
return Status == StatusTy::SafeWithFreeze; }
1882 Status = StatusTy::Unsafe;
1886 void freeze(IRBuilderBase &Builder, Instruction &UserI) {
1887 assert(isSafeWithFreeze() &&
1888 "should only be used when freezing is required");
1890 "UserI must be a user of ToFreeze");
1891 IRBuilder<>::InsertPointGuard Guard(Builder);
1896 if (
U.get() == ToFreeze)
1911 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1915 if (
C->getValue().ult(NumElements))
1916 return ScalarizationResult::safe();
1917 return ScalarizationResult::unsafe();
1922 return ScalarizationResult::unsafe();
1924 APInt Zero(IntWidth, 0);
1925 APInt MaxElts(IntWidth, NumElements);
1932 return ScalarizationResult::safe();
1933 return ScalarizationResult::unsafe();
1946 if (ValidIndices.
contains(IdxRange))
1947 return ScalarizationResult::safeWithFreeze(IdxBase);
1948 return ScalarizationResult::unsafe();
1960 C->getZExtValue() *
DL.getTypeStoreSize(ScalarType));
1972bool VectorCombine::foldSingleElementStore(Instruction &
I) {
1984 if (!
match(
SI->getValueOperand(),
1991 Value *SrcAddr =
Load->getPointerOperand()->stripPointerCasts();
1994 if (!
Load->isSimple() ||
Load->getParent() !=
SI->getParent() ||
1995 !
DL->typeSizeEqualsStoreSize(
Load->getType()->getScalarType()) ||
1996 SrcAddr !=
SI->getPointerOperand()->stripPointerCasts())
2002 auto ScalarizableIdx =
2004 if (ScalarizableIdx.isUnsafe())
2011 if (ScalarizableIdx.isSafeWithFreeze())
2014 SI->getValueOperand()->getType(),
SI->getPointerOperand(),
2015 {ConstantInt::get(Idx->getType(), 0), Idx});
2020 NSI->
setMetadata(LLVMContext::MD_invariant_group,
nullptr);
2022 std::max(
SI->getAlign(),
Load->getAlign()), NewElement->
getType(), Idx,
2025 replaceValue(
I, *NSI);
2035bool VectorCombine::scalarizeLoad(Instruction &
I) {
2045 if (!LI->isSimple() || !
DL->typeSizeEqualsStoreSize(VecTy->getScalarType()))
2048 bool AllExtracts =
true;
2049 bool AllBitcasts =
true;
2051 unsigned NumInstChecked = 0;
2056 for (User *U : LI->users()) {
2058 if (!UI || UI->getParent() != LI->getParent())
2063 if (UI->use_empty())
2067 AllExtracts =
false;
2069 AllBitcasts =
false;
2073 for (Instruction &
I :
2074 make_range(std::next(LI->getIterator()), UI->getIterator())) {
2081 LastCheckedInst = UI;
2086 return scalarizeLoadExtract(LI, VecTy, Ptr);
2088 return scalarizeLoadBitcast(LI, VecTy, Ptr);
2093bool VectorCombine::scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
2098 DenseMap<ExtractElementInst *, ScalarizationResult> NeedFreeze;
2101 for (
auto &Pair : NeedFreeze)
2102 Pair.second.discard();
2110 for (User *U : LI->
users()) {
2115 if (ScalarIdx.isUnsafe())
2117 if (ScalarIdx.isSafeWithFreeze()) {
2118 NeedFreeze.try_emplace(UI, ScalarIdx);
2119 ScalarIdx.discard();
2125 Index ?
Index->getZExtValue() : -1);
2133 LLVM_DEBUG(
dbgs() <<
"Found all extractions of a vector load: " << *LI
2134 <<
"\n LoadExtractCost: " << OriginalCost
2135 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2137 if (ScalarizedCost >= OriginalCost)
2144 Type *ElemType = VecTy->getElementType();
2147 for (User *U : LI->
users()) {
2149 Value *Idx = EI->getIndexOperand();
2152 auto It = NeedFreeze.find(EI);
2153 if (It != NeedFreeze.end())
2160 Builder.
CreateLoad(ElemType,
GEP, EI->getName() +
".scalar"));
2162 Align ScalarOpAlignment =
2164 NewLoad->setAlignment(ScalarOpAlignment);
2167 size_t Offset = ConstIdx->getZExtValue() *
DL->getTypeStoreSize(ElemType);
2172 replaceValue(*EI, *NewLoad,
false);
2175 FailureGuard.release();
2180bool VectorCombine::scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
2186 Type *TargetScalarType =
nullptr;
2187 unsigned VecBitWidth =
DL->getTypeSizeInBits(VecTy);
2189 for (User *U : LI->
users()) {
2192 Type *DestTy = BC->getDestTy();
2196 unsigned DestBitWidth =
DL->getTypeSizeInBits(DestTy);
2197 if (DestBitWidth != VecBitWidth)
2201 if (!TargetScalarType)
2202 TargetScalarType = DestTy;
2203 else if (TargetScalarType != DestTy)
2211 if (!TargetScalarType)
2219 LLVM_DEBUG(
dbgs() <<
"Found vector load feeding only bitcasts: " << *LI
2220 <<
"\n OriginalCost: " << OriginalCost
2221 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2223 if (ScalarizedCost >= OriginalCost)
2234 ScalarLoad->copyMetadata(*LI);
2237 for (User *U : LI->
users()) {
2239 replaceValue(*BC, *ScalarLoad,
false);
2245bool VectorCombine::scalarizeExtExtract(Instruction &
I) {
2260 Type *ScalarDstTy = DstTy->getElementType();
2261 if (
DL->getTypeSizeInBits(SrcTy) !=
DL->getTypeSizeInBits(ScalarDstTy))
2267 unsigned ExtCnt = 0;
2268 bool ExtLane0 =
false;
2269 for (User *U : Ext->users()) {
2283 Instruction::And, ScalarDstTy,
CostKind,
2286 (ExtCnt - ExtLane0) *
2288 Instruction::LShr, ScalarDstTy,
CostKind,
2291 if (ScalarCost > VectorCost)
2294 Value *ScalarV = Ext->getOperand(0);
2301 SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
2302 bool AllExtractsTriggerUB =
true;
2303 ExtractElementInst *LastExtract =
nullptr;
2305 for (User *U : Ext->users()) {
2308 AllExtractsTriggerUB =
false;
2312 if (!LastExtract || LastExtract->
comesBefore(Extract))
2313 LastExtract = Extract;
2315 if (ExtractedLanes.
size() != DstTy->getNumElements() ||
2316 !AllExtractsTriggerUB ||
2324 uint64_t SrcEltSizeInBits =
DL->getTypeSizeInBits(SrcTy->getElementType());
2325 uint64_t TotalBits =
DL->getTypeSizeInBits(SrcTy);
2328 Value *
Mask = ConstantInt::get(PackedTy, EltBitMask);
2329 for (User *U : Ext->users()) {
2335 ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits)
2336 : (Idx * SrcEltSizeInBits);
2339 U->replaceAllUsesWith(
And);
2347bool VectorCombine::foldConcatOfBoolMasks(Instruction &
I) {
2348 Type *Ty =
I.getType();
2353 if (
DL->isBigEndian())
2364 uint64_t ShAmtX = 0;
2372 uint64_t ShAmtY = 0;
2380 if (ShAmtX > ShAmtY) {
2388 uint64_t ShAmtDiff = ShAmtY - ShAmtX;
2389 unsigned NumSHL = (ShAmtX > 0) + (ShAmtY > 0);
2394 MaskTy->getNumElements() != ShAmtDiff ||
2395 MaskTy->getNumElements() > (
BitWidth / 2))
2400 Type::getIntNTy(Ty->
getContext(), ConcatTy->getNumElements());
2401 auto *MaskIntTy = Type::getIntNTy(Ty->
getContext(), ShAmtDiff);
2404 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2421 if (Ty != ConcatIntTy)
2427 LLVM_DEBUG(
dbgs() <<
"Found a concatenation of bitcasted bool masks: " <<
I
2428 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2431 if (NewCost > OldCost)
2441 if (Ty != ConcatIntTy) {
2451 replaceValue(
I, *Result);
2457bool VectorCombine::foldPermuteOfBinops(Instruction &
I) {
2458 BinaryOperator *BinOp;
2459 ArrayRef<int> OuterMask;
2467 Value *Op00, *Op01, *Op10, *Op11;
2468 ArrayRef<int> Mask0, Mask1;
2473 if (!Match0 && !Match1)
2486 if (!ShuffleDstTy || !BinOpTy || !Op0Ty || !Op1Ty)
2489 unsigned NumSrcElts = BinOpTy->getNumElements();
2494 any_of(OuterMask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
2498 SmallVector<int> NewMask0, NewMask1;
2499 for (
int M : OuterMask) {
2500 if (M < 0 || M >= (
int)NumSrcElts) {
2504 NewMask0.
push_back(Match0 ? Mask0[M] : M);
2505 NewMask1.
push_back(Match1 ? Mask1[M] : M);
2509 unsigned NumOpElts = Op0Ty->getNumElements();
2510 bool IsIdentity0 = ShuffleDstTy == Op0Ty &&
2511 all_of(NewMask0, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2513 bool IsIdentity1 = ShuffleDstTy == Op1Ty &&
2514 all_of(NewMask1, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2523 ShuffleDstTy, BinOpTy, OuterMask,
CostKind,
2524 0,
nullptr, {BinOp}, &
I);
2526 NewCost += BinOpCost;
2532 OldCost += Shuf0Cost;
2534 NewCost += Shuf0Cost;
2540 OldCost += Shuf1Cost;
2542 NewCost += Shuf1Cost;
2550 Op0Ty, NewMask0,
CostKind, 0,
nullptr, {Op00, Op01});
2554 Op1Ty, NewMask1,
CostKind, 0,
nullptr, {Op10, Op11});
2556 LLVM_DEBUG(
dbgs() <<
"Found a shuffle feeding a shuffled binop: " <<
I
2557 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2561 if (NewCost > OldCost)
2572 NewInst->copyIRFlags(BinOp);
2576 replaceValue(
I, *NewBO);
2582bool VectorCombine::foldShuffleOfBinops(Instruction &
I) {
2583 ArrayRef<int> OldMask;
2590 if (
LHS->getOpcode() !=
RHS->getOpcode())
2594 bool IsCommutative =
false;
2603 IsCommutative = BinaryOperator::isCommutative(BO->getOpcode());
2614 if (!ShuffleDstTy || !BinResTy || !BinOpTy ||
X->getType() !=
Z->getType())
2617 bool SameBinOp =
LHS ==
RHS;
2618 unsigned NumSrcElts = BinOpTy->getNumElements();
2621 if (IsCommutative &&
X != Z &&
Y != W && (
X == W ||
Y == Z))
2624 auto ConvertToUnary = [NumSrcElts](
int &
M) {
2625 if (M >= (
int)NumSrcElts)
2629 SmallVector<int> NewMask0(OldMask);
2638 SmallVector<int> NewMask1(OldMask);
2657 ShuffleDstTy, BinResTy, OldMask,
CostKind, 0,
2667 ArrayRef<int> InnerMask;
2669 m_Mask(InnerMask)))) &&
2672 [NumSrcElts](
int M) {
return M < (int)NumSrcElts; })) {
2684 bool ReducedInstCount =
false;
2685 ReducedInstCount |= MergeInner(
X, 0, NewMask0,
CostKind);
2686 ReducedInstCount |= MergeInner(
Y, 0, NewMask1,
CostKind);
2687 ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0,
CostKind);
2688 ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1,
CostKind);
2689 bool SingleSrcBinOp = (
X ==
Y) && (Z == W) && (NewMask0 == NewMask1);
2701 I.getType()->getScalarType()->isIntegerTy(1) &&
2705 auto *ShuffleCmpTy =
2708 SK0, ShuffleCmpTy, BinOpTy, NewMask0,
CostKind, 0,
nullptr, {
X,
Z});
2709 if (!SingleSrcBinOp)
2719 PredLHS,
CostKind, Op0Info, Op1Info);
2729 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2736 if (ReducedInstCount ? (NewCost > OldCost) : (NewCost >= OldCost))
2745 : Builder.
CreateCmp(PredLHS, Shuf0, Shuf1);
2749 NewInst->copyIRFlags(
LHS);
2750 NewInst->andIRFlags(
RHS);
2755 replaceValue(
I, *NewBO);
2762bool VectorCombine::foldShuffleOfSelects(Instruction &
I) {
2764 Value *C1, *
T1, *F1, *C2, *T2, *F2;
2775 if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2781 if (((SI0FOp ==
nullptr) != (SI1FOp ==
nullptr)) ||
2782 ((SI0FOp !=
nullptr) &&
2783 (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())))
2789 auto SelOp = Instruction::Select;
2797 CostSel1 + CostSel2 +
2799 {
I.getOperand(0),
I.getOperand(1)}, &
I);
2803 Mask,
CostKind, 0,
nullptr, {C1, C2});
2813 if (!Sel1->hasOneUse())
2814 NewCost += CostSel1;
2815 if (!Sel2->hasOneUse())
2816 NewCost += CostSel2;
2819 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2821 if (NewCost > OldCost)
2830 NewSel = Builder.
CreateSelectFMF(ShuffleCmp, ShuffleTrue, ShuffleFalse,
2831 SI0FOp->getFastMathFlags());
2833 NewSel = Builder.
CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
2838 replaceValue(
I, *NewSel);
2844bool VectorCombine::foldShuffleOfCastops(Instruction &
I) {
2846 ArrayRef<int> OldMask;
2855 if (!C0 || (IsBinaryShuffle && !C1))
2862 if (!IsBinaryShuffle && Opcode == Instruction::BitCast)
2865 if (IsBinaryShuffle) {
2866 if (C0->getSrcTy() != C1->getSrcTy())
2869 if (Opcode != C1->getOpcode()) {
2871 Opcode = Instruction::SExt;
2880 if (!ShuffleDstTy || !CastDstTy || !CastSrcTy)
2883 unsigned NumSrcElts = CastSrcTy->getNumElements();
2884 unsigned NumDstElts = CastDstTy->getNumElements();
2885 assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) &&
2886 "Only bitcasts expected to alter src/dst element counts");
2890 if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 &&
2891 (NumDstElts % NumSrcElts) != 0)
2894 SmallVector<int, 16> NewMask;
2895 if (NumSrcElts >= NumDstElts) {
2898 assert(NumSrcElts % NumDstElts == 0 &&
"Unexpected shuffle mask");
2899 unsigned ScaleFactor = NumSrcElts / NumDstElts;
2904 assert(NumDstElts % NumSrcElts == 0 &&
"Unexpected shuffle mask");
2905 unsigned ScaleFactor = NumDstElts / NumSrcElts;
2910 auto *NewShuffleDstTy =
2919 if (IsBinaryShuffle)
2934 if (IsBinaryShuffle) {
2944 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2946 if (NewCost > OldCost)
2950 if (IsBinaryShuffle)
2960 NewInst->copyIRFlags(C0);
2961 if (IsBinaryShuffle)
2962 NewInst->andIRFlags(C1);
2966 replaceValue(
I, *Cast);
2976bool VectorCombine::foldShuffleOfShuffles(Instruction &
I) {
2977 ArrayRef<int> OuterMask;
2978 Value *OuterV0, *OuterV1;
2983 ArrayRef<int> InnerMask0, InnerMask1;
2984 Value *X0, *X1, *Y0, *Y1;
2989 if (!Match0 && !Match1)
2994 SmallVector<int, 16> PoisonMask1;
2999 InnerMask1 = PoisonMask1;
3003 X0 = Match0 ? X0 : OuterV0;
3004 Y0 = Match0 ? Y0 : OuterV0;
3005 X1 = Match1 ? X1 : OuterV1;
3006 Y1 = Match1 ? Y1 : OuterV1;
3010 if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy ||
3014 unsigned NumSrcElts = ShuffleSrcTy->getNumElements();
3015 unsigned NumImmElts = ShuffleImmTy->getNumElements();
3020 SmallVector<int, 16> NewMask(OuterMask);
3021 Value *NewX =
nullptr, *NewY =
nullptr;
3022 for (
int &M : NewMask) {
3023 Value *Src =
nullptr;
3024 if (0 <= M && M < (
int)NumImmElts) {
3028 Src =
M >= (int)NumSrcElts ? Y0 : X0;
3029 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3031 }
else if (M >= (
int)NumImmElts) {
3036 Src =
M >= (int)NumSrcElts ? Y1 : X1;
3037 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3041 assert(0 <= M && M < (
int)NumSrcElts &&
"Unexpected shuffle mask index");
3050 if (!NewX || NewX == Src) {
3054 if (!NewY || NewY == Src) {
3073 replaceValue(
I, *NewX);
3090 bool IsUnary =
all_of(NewMask, [&](
int M) {
return M < (int)NumSrcElts; });
3096 nullptr, {NewX, NewY});
3098 NewCost += InnerCost0;
3100 NewCost += InnerCost1;
3103 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3105 if (NewCost > OldCost)
3109 replaceValue(
I, *Shuf);
3125bool VectorCombine::foldShufflesOfLengthChangingShuffles(Instruction &
I) {
3130 unsigned ChainLength = 0;
3131 SmallVector<int>
Mask;
3132 SmallVector<int> YMask;
3142 ArrayRef<int> OuterMask;
3143 Value *OuterV0, *OuterV1;
3144 if (ChainLength != 0 && !Trunk->
hasOneUse())
3147 m_Mask(OuterMask))))
3149 if (OuterV0->
getType() != TrunkType) {
3155 ArrayRef<int> InnerMask0, InnerMask1;
3161 bool Match0Leaf = Match0 && A0->
getType() !=
I.getType();
3162 bool Match1Leaf = Match1 && A1->
getType() !=
I.getType();
3163 if (Match0Leaf == Match1Leaf) {
3169 SmallVector<int> CommutedOuterMask;
3176 for (
int &M : CommutedOuterMask) {
3179 if (M < (
int)NumTrunkElts)
3184 OuterMask = CommutedOuterMask;
3203 int NumLeafElts = YType->getNumElements();
3204 SmallVector<int> LocalYMask(InnerMask1);
3205 for (
int &M : LocalYMask) {
3206 if (M >= NumLeafElts)
3216 Mask.assign(OuterMask);
3217 YMask.
assign(LocalYMask);
3218 OldCost = NewCost = LocalOldCost;
3225 SmallVector<int> NewYMask(YMask);
3227 for (
auto [CombinedM, LeafM] :
llvm::zip(NewYMask, LocalYMask)) {
3228 if (LeafM == -1 || CombinedM == LeafM)
3230 if (CombinedM == -1) {
3240 SmallVector<int> NewMask;
3241 NewMask.
reserve(NumTrunkElts);
3242 for (
int M : Mask) {
3243 if (M < 0 || M >=
static_cast<int>(NumTrunkElts))
3258 if (LocalNewCost >= NewCost && LocalOldCost < LocalNewCost - NewCost)
3262 if (ChainLength == 1) {
3263 dbgs() <<
"Found chain of shuffles fed by length-changing shuffles: "
3266 dbgs() <<
" next chain link: " << *Trunk <<
'\n'
3267 <<
" old cost: " << (OldCost + LocalOldCost)
3268 <<
" new cost: " << LocalNewCost <<
'\n';
3273 OldCost += LocalOldCost;
3274 NewCost = LocalNewCost;
3278 if (ChainLength <= 1)
3286 return M < 0 || M >=
static_cast<int>(NumTrunkElts);
3289 for (
int &M : Mask) {
3290 if (M >=
static_cast<int>(NumTrunkElts))
3291 M = YMask[
M - NumTrunkElts];
3295 replaceValue(
I, *Root);
3302 replaceValue(
I, *Root);
3308bool VectorCombine::foldShuffleOfIntrinsics(Instruction &
I) {
3310 ArrayRef<int> OldMask;
3320 if (IID != II1->getIntrinsicID())
3329 if (!ShuffleDstTy || !II0Ty)
3335 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3336 Value *Arg0 = II0->getArgOperand(
I);
3337 Value *Arg1 = II1->getArgOperand(
I);
3354 II0Ty, OldMask,
CostKind, 0,
nullptr, {II0, II1}, &
I);
3358 SmallDenseSet<std::pair<Value *, Value *>> SeenOperandPairs;
3359 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3361 NewArgsTy.
push_back(II0->getArgOperand(
I)->getType());
3365 ShuffleDstTy->getNumElements());
3367 std::pair<Value *, Value *> OperandPair =
3368 std::make_pair(II0->getArgOperand(
I), II1->getArgOperand(
I));
3369 if (!SeenOperandPairs.
insert(OperandPair).second) {
3375 CostKind, 0,
nullptr, {II0->getArgOperand(
I), II1->getArgOperand(
I)});
3378 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3381 if (!II0->hasOneUse())
3383 if (II1 != II0 && !II1->hasOneUse())
3387 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3390 if (NewCost > OldCost)
3394 SmallDenseMap<std::pair<Value *, Value *>,
Value *> ShuffleCache;
3395 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I)
3399 std::pair<Value *, Value *> OperandPair =
3400 std::make_pair(II0->getArgOperand(
I), II1->getArgOperand(
I));
3401 auto It = ShuffleCache.
find(OperandPair);
3402 if (It != ShuffleCache.
end()) {
3408 II1->getArgOperand(
I), OldMask);
3409 ShuffleCache[OperandPair] = Shuf;
3417 NewInst->copyIRFlags(II0);
3418 NewInst->andIRFlags(II1);
3421 replaceValue(
I, *NewIntrinsic);
3427bool VectorCombine::foldPermuteOfIntrinsic(Instruction &
I) {
3439 if (!ShuffleDstTy || !IntrinsicSrcTy)
3443 unsigned NumSrcElts = IntrinsicSrcTy->getNumElements();
3444 if (
any_of(Mask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
3457 IntrinsicSrcTy, Mask,
CostKind, 0,
nullptr, {V0}, &
I);
3461 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3463 NewArgsTy.
push_back(II0->getArgOperand(
I)->getType());
3467 ShuffleDstTy->getNumElements());
3470 ArgTy, VecTy, Mask,
CostKind, 0,
nullptr,
3471 {II0->getArgOperand(
I)});
3474 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3479 if (!II0->hasOneUse())
3482 LLVM_DEBUG(
dbgs() <<
"Found a permute of intrinsic: " <<
I <<
"\n OldCost: "
3483 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
3485 if (NewCost > OldCost)
3490 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3503 NewInst->copyIRFlags(II0);
3505 replaceValue(
I, *NewIntrinsic);
3515 int M = SV->getMaskValue(Lane);
3518 if (
static_cast<unsigned>(M) < NumElts) {
3519 V = SV->getOperand(0);
3522 V = SV->getOperand(1);
3533 auto [U, Lane] = IL;
3546 unsigned NumElts = Ty->getNumElements();
3547 if (Item.
size() == NumElts || NumElts == 1 || Item.
size() % NumElts != 0)
3553 std::iota(ConcatMask.
begin(), ConcatMask.
end(), 0);
3559 unsigned NumSlices = Item.
size() / NumElts;
3564 for (
unsigned Slice = 0; Slice < NumSlices; ++Slice) {
3565 Value *SliceV = Item[Slice * NumElts].first;
3566 if (!SliceV || SliceV->
getType() != Ty)
3568 for (
unsigned Elt = 0; Elt < NumElts; ++Elt) {
3569 auto [V, Lane] = Item[Slice * NumElts + Elt];
3570 if (Lane !=
static_cast<int>(Elt) || SliceV != V)
3579 const DenseSet<std::pair<Value *, Use *>> &IdentityLeafs,
3580 const DenseSet<std::pair<Value *, Use *>> &SplatLeafs,
3581 const DenseSet<std::pair<Value *, Use *>> &ConcatLeafs,
3584 auto [FrontV, FrontLane] = Item.
front();
3586 if (IdentityLeafs.contains(std::make_pair(FrontV, From))) {
3589 if (SplatLeafs.contains(std::make_pair(FrontV, From))) {
3591 return Builder.CreateShuffleVector(FrontV, Mask);
3593 if (ConcatLeafs.contains(std::make_pair(FrontV, From))) {
3597 for (
unsigned S = 0; S <
Values.size(); ++S)
3598 Values[S] = Item[S * NumElts].first;
3600 while (
Values.size() > 1) {
3603 std::iota(Mask.begin(), Mask.end(), 0);
3605 for (
unsigned S = 0; S < NewValues.
size(); ++S)
3607 Builder.CreateShuffleVector(
Values[S * 2],
Values[S * 2 + 1], Mask);
3621 if (BCDstTy && BCSrcTy &&
3622 BCDstTy->getElementCount() != BCSrcTy->getElementCount()) {
3623 unsigned DstElts = BCDstTy->getNumElements();
3624 unsigned SrcElts = BCSrcTy->getNumElements();
3626 if (DstElts > SrcElts) {
3628 unsigned R = DstElts / SrcElts;
3629 if (Item.
size() % R != 0)
3631 for (
unsigned Idx = 0,
E = Item.
size(); Idx <
E; Idx += R) {
3632 auto [V, Lane] = Item[Idx];
3642 unsigned R = SrcElts / DstElts;
3643 for (
auto [V, Lane] : Item) {
3649 for (
unsigned J = 0; J < R; ++J)
3654 IdentityLeafs, SplatLeafs, ConcatLeafs,
3655 Builder, WorkList,
TTI);
3657 return Builder.CreateBitCast(
3662 unsigned NumOps =
I->getNumOperands() - (
II ? 1 : 0);
3664 for (
unsigned Idx = 0; Idx <
NumOps; Idx++) {
3667 Ops[Idx] =
II->getOperand(Idx);
3672 IdentityLeafs, SplatLeafs, ConcatLeafs, Builder, WorkList,
TTI);
3682 for (
const auto &Lane : Item)
3695 auto *
Value = Builder.CreateCmp(CI->getPredicate(),
Ops[0],
Ops[1]);
3705 auto *
Value = Builder.CreateCast(CI->getOpcode(),
Ops[0], DstTy);
3710 auto *
Value = Builder.CreateIntrinsic(DstTy,
II->getIntrinsicID(),
Ops);
3724bool VectorCombine::foldShuffleToIdentity(Instruction &
I) {
3726 if (!Ty ||
I.use_empty())
3730 for (
unsigned M = 0,
E = Ty->getNumElements(); M <
E; ++M)
3734 Candidates.
push_back(std::make_pair(Start, &*
I.use_begin()));
3735 DenseSet<std::pair<Value *, Use *>> IdentityLeafs, SplatLeafs, ConcatLeafs;
3736 unsigned NumVisited = 0;
3737 bool TraversedElCountChangingBitcast =
false;
3739 while (!Candidates.
empty()) {
3744 auto Item = ItemFrom.first;
3745 auto From = ItemFrom.second;
3746 auto [FrontV, FrontLane] = Item.front();
3753 if (FrontLane == 0 &&
3757 Value *FrontV = Item.front().first;
3759 E.value().second == (int)
E.index());
3761 IdentityLeafs.
insert(std::make_pair(FrontV, From));
3766 C &&
C->getSplatValue() &&
3768 Value *FrontV = Item.front().first;
3774 SplatLeafs.
insert(std::make_pair(FrontV, From));
3779 auto [FrontV, FrontLane] = Item.front();
3780 auto [
V, Lane] = IL;
3781 return !
V || (
V == FrontV && Lane == FrontLane);
3783 SplatLeafs.
insert(std::make_pair(FrontV, From));
3789 auto CheckLaneIsEquivalentToFirst = [Item](
InstLane IL) {
3790 Value *FrontV = Item.front().first;
3799 if (CI->getPredicate() !=
cast<CmpInst>(FrontV)->getPredicate())
3802 if (CI->getSrcTy()->getScalarType() !=
3807 SI->getOperand(0)->getType() !=
3814 II->getIntrinsicID() ==
3816 !
II->hasOperandBundles());
3823 BO && BO->isIntDivRem())
3830 }
else if (
isa<UnaryOperator, TruncInst, ZExtInst, SExtInst, FPToSIInst,
3831 FPToUIInst, SIToFPInst, UIToFPInst>(FrontV)) {
3838 if (BCDstTy && BCSrcTy) {
3839 ElementCount DstEC = BCDstTy->getElementCount();
3840 ElementCount SrcEC = BCSrcTy->getElementCount();
3841 if (DstEC == SrcEC) {
3844 &BitCast->getOperandUse(0));
3849 if (DstElts > SrcElts && DstElts % SrcElts == 0) {
3853 unsigned R = DstElts / SrcElts;
3855 bool Valid = Item.size() %
R == 0;
3856 for (
unsigned Idx = 0,
E = Item.size(); Valid && Idx <
E;
3858 auto [V0, L0] = Item[Idx];
3861 [](
InstLane IL) {
return IL.first !=
nullptr; })) {
3872 for (
unsigned J = 1; J <
R; ++J) {
3873 auto [VJ, LJ] = Item[Idx + J];
3874 if (!VJ || VJ != V0 || LJ != L0 + (
int)J) {
3885 TraversedElCountChangingBitcast =
true;
3886 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
3889 }
else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
3892 unsigned R = SrcElts / DstElts;
3894 for (
auto [V, Lane] : Item) {
3900 for (
unsigned J = 0; J <
R; ++J)
3903 TraversedElCountChangingBitcast =
true;
3904 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
3910 &Sel->getOperandUse(0));
3912 &Sel->getOperandUse(1));
3914 &Sel->getOperandUse(2));
3918 !
II->hasOperandBundles()) {
3919 for (
unsigned Op = 0,
E =
II->getNumOperands() - 1;
Op <
E;
Op++) {
3923 Value *FrontV = Item.front().first;
3940 ConcatLeafs.
insert(std::make_pair(FrontV, From));
3947 if (NumVisited <= 1)
3953 if (NumVisited == 2 && TraversedElCountChangingBitcast)
3956 LLVM_DEBUG(
dbgs() <<
"Found a superfluous identity shuffle: " <<
I <<
"\n");
3963 ConcatLeafs, Builder, Worklist, &
TTI);
3964 replaceValue(
I, *V);
3971bool VectorCombine::foldShuffleFromReductions(Instruction &
I) {
3975 switch (
II->getIntrinsicID()) {
3976 case Intrinsic::vector_reduce_add:
3977 case Intrinsic::vector_reduce_mul:
3978 case Intrinsic::vector_reduce_and:
3979 case Intrinsic::vector_reduce_or:
3980 case Intrinsic::vector_reduce_xor:
3981 case Intrinsic::vector_reduce_smin:
3982 case Intrinsic::vector_reduce_smax:
3983 case Intrinsic::vector_reduce_umin:
3984 case Intrinsic::vector_reduce_umax:
3993 std::queue<Value *> Worklist;
3994 SmallPtrSet<Value *, 4> Visited;
3995 ShuffleVectorInst *Shuffle =
nullptr;
3999 while (!Worklist.empty()) {
4000 Value *CV = Worklist.front();
4012 if (CI->isBinaryOp()) {
4013 for (
auto *
Op : CI->operand_values())
4017 if (Shuffle && Shuffle != SV)
4034 for (
auto *V : Visited)
4035 for (
auto *U :
V->users())
4036 if (!Visited.contains(U) && U != &
I)
4039 FixedVectorType *VecType =
4043 FixedVectorType *ShuffleInputType =
4045 if (!ShuffleInputType)
4051 SmallVector<int> ConcatMask;
4053 sort(ConcatMask, [](
int X,
int Y) {
return (
unsigned)
X < (unsigned)
Y; });
4054 bool UsesSecondVec =
4055 any_of(ConcatMask, [&](
int M) {
return M >= (int)NumInputElts; });
4062 ShuffleInputType, ConcatMask,
CostKind);
4064 LLVM_DEBUG(
dbgs() <<
"Found a reduction feeding from a shuffle: " << *Shuffle
4066 LLVM_DEBUG(
dbgs() <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
4068 bool MadeChanges =
false;
4069 if (NewCost < OldCost) {
4073 LLVM_DEBUG(
dbgs() <<
"Created new shuffle: " << *NewShuffle <<
"\n");
4074 replaceValue(*Shuffle, *NewShuffle);
4080 MadeChanges |= foldSelectShuffle(*Shuffle,
true);
4101bool VectorCombine::foldShuffleChainsToReduce(Instruction &
I) {
4110 if (FVT->getNumElements() < 2)
4113 std::optional<Instruction::BinaryOps> CommonBinOp;
4114 std::optional<Intrinsic::ID> CommonCallOp;
4119 CommonBinOp = BO->getOpcode();
4121 CommonCallOp = MMI->getIntrinsicID();
4127 FastMathFlags CommonFMF;
4128 bool IsFloatReduction =
false;
4132 auto IsChainNode = [&](
Value *
V) {
4134 return CommonBinOp && BO->getOpcode() == *CommonBinOp;
4136 return CommonCallOp && MMI->getIntrinsicID() == *CommonCallOp;
4144 constexpr unsigned MaxChainNodes = 32;
4145 SmallSetVector<Value *, 16> Nodes;
4146 SmallSetVector<Value *, 4> Sources;
4147 unsigned NumVisited = 0;
4148 auto AddSource = [&](
Value *
V) {
4154 auto Walk = [&](
Value *
V,
auto &&Walk) ->
bool {
4157 if (++NumVisited > MaxChainNodes)
4159 if (!IsChainNode(V))
4160 return AddSource(V);
4165 if (!Walk(
U->getOperand(
I), Walk))
4174 return AddSource(V);
4176 if (!Walk(VecOpEE, Walk) || Nodes.
empty())
4183 for (
Value *V : Nodes) {
4189 if (!IsFloatReduction) {
4191 IsFloatReduction =
true;
4205 DenseMap<Value *, Demand> Demands;
4206 auto DemandOf = [&](
Value *
V) -> Demand & {
4208 Demand &
D = Demands[
V];
4209 if (
D.Lanes.getBitWidth() !=
N)
4213 DemandOf(VecOpEE).Lanes.setBit(0);
4215 Demand DV = Demands.
lookup(V);
4216 if (DV.Lanes.isZero())
4219 ArrayRef<int>
Mask = SVI->getShuffleMask();
4220 Demand &
DS = DemandOf(SVI->getOperand(0));
4221 for (
unsigned I = 0,
E =
Mask.size();
I !=
E; ++
I) {
4223 if (!DV.Lanes[
I] || Mask[
I] < 0 ||
4224 (
unsigned)Mask[
I] >=
DS.Lanes.getBitWidth())
4226 if (
DS.Lanes[Mask[
I]] || DV.Duplicates[
I])
4227 DS.Duplicates.setBit(Mask[
I]);
4228 DS.Lanes.setBit(Mask[
I]);
4232 for (
Value *
Op : {
U->getOperand(0),
U->getOperand(1)}) {
4233 Demand &DOp = DemandOf(
Op);
4235 DOp.Duplicates |= DV.Duplicates | (DOp.Lanes & DV.Lanes);
4236 DOp.Lanes |= DV.Lanes;
4243 auto CoversChain = [&](
Value *
V) {
4244 SmallVector<Value *, 8> Worklist(1, VecOpEE);
4245 SmallPtrSet<Value *, 8> Seen;
4247 while (!Worklist.empty()) {
4250 for (
unsigned I = 0;
I !=
NumOps; ++
I) {
4254 if (!Nodes.contains(
Op))
4256 Worklist.push_back(
Op);
4264 struct ReductionCut {
4268 std::optional<ReductionCut> Cut;
4269 for (
Value *S : Sources) {
4270 auto It = Demands.
find(S);
4271 if (It == Demands.
end() || It->second.Lanes.isZero())
4273 if (!IsIdempotent && !It->second.Duplicates.isZero()) {
4278 Cut = ReductionCut{S, It->second.Lanes};
4285 if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
4289 Cut->Elts |= It->second.Lanes;
4292 for (
Value *V : Nodes) {
4295 auto It = Demands.
find(V);
4296 if (It == Demands.
end() || !It->second.Lanes.isAllOnes())
4298 if (!IsIdempotent && !It->second.Duplicates.isZero())
4300 if (!CoversChain(V))
4302 Cut = ReductionCut{
V, It->second.Lanes};
4307 if (!Cut || Cut->Elts.popcount() < 2)
4317 for (
Value *V : Nodes)
4321 bool IsPartialReduction = !Cut->Elts.isAllOnes();
4322 FixedVectorType *ReduceVecTy =
4327 SmallVector<int> ExtractMask;
4329 if (IsPartialReduction) {
4330 for (
unsigned I = 0,
E = Cut->Elts.getBitWidth();
I !=
E; ++
I)
4332 ExtractMask.push_back(
I);
4333 unsigned SubIdx = 0, SubLen;
4334 auto SK = Cut->Elts.isShiftedMask(SubIdx, SubLen)
4338 SubIdx, ReduceVecTy);
4341 IntrinsicCostAttributes ICA(
4342 ReducedOp, ReduceVecTy->getElementType(),
4346 IsFloatReduction ? CommonFMF : FastMathFlags());
4349 LLVM_DEBUG(
dbgs() <<
"Found reduction shuffle chain: " <<
I <<
"\n OldCost : "
4350 << OrigCost <<
" vs NewCost: " << NewCost <<
"\n");
4355 if (VecOpEE->
hasOneUse() ? (NewCost > OrigCost) : (NewCost >= OrigCost))
4358 Value *ReduceInput = Cut->Src;
4359 if (IsPartialReduction)
4362 Value *ReducedResult;
4363 if (IsFloatReduction) {
4365 *CommonBinOp, ReduceVecTy->getElementType(),
false,
4368 {Identity, ReduceInput}, CommonFMF);
4373 replaceValue(
I, *ReducedResult);
4382bool VectorCombine::foldCastFromReductions(Instruction &
I) {
4387 bool TruncOnly =
false;
4390 case Intrinsic::vector_reduce_add:
4391 case Intrinsic::vector_reduce_mul:
4394 case Intrinsic::vector_reduce_and:
4395 case Intrinsic::vector_reduce_or:
4396 case Intrinsic::vector_reduce_xor:
4403 Value *ReductionSrc =
I.getOperand(0);
4415 Type *ResultTy =
I.getType();
4418 ReductionOpc, ReductionSrcTy, std::nullopt,
CostKind);
4428 if (OldCost <= NewCost || !NewCost.
isValid())
4432 II->getIntrinsicID(), {Src});
4434 replaceValue(
I, *NewCast);
4462bool VectorCombine::foldSignBitReductionCmp(Instruction &
I) {
4464 IntrinsicInst *ReduceOp;
4465 const APInt *CmpVal;
4472 case Intrinsic::vector_reduce_or:
4473 case Intrinsic::vector_reduce_umax:
4474 case Intrinsic::vector_reduce_and:
4475 case Intrinsic::vector_reduce_umin:
4476 case Intrinsic::vector_reduce_add:
4487 unsigned BitWidth = VecTy->getScalarSizeInBits();
4491 unsigned NumElts = VecTy->getNumElements();
4500 case Intrinsic::vector_reduce_or:
4501 case Intrinsic::vector_reduce_umax:
4502 TreeOpcode = Instruction::Or;
4504 case Intrinsic::vector_reduce_and:
4505 case Intrinsic::vector_reduce_umin:
4506 TreeOpcode = Instruction::And;
4508 case Intrinsic::vector_reduce_add:
4509 TreeOpcode = Instruction::Add;
4517 SmallVector<Value *, 8> Worklist;
4518 SmallVector<Value *, 8> Sources;
4520 std::optional<bool> IsAShr;
4521 constexpr unsigned MaxSources = 8;
4526 while (!Worklist.
empty() && Worklist.
size() <= MaxSources &&
4527 Sources.
size() <= MaxSources) {
4536 bool ThisIsAShr = Shr->getOpcode() == Instruction::AShr;
4538 IsAShr = ThisIsAShr;
4539 else if (*IsAShr != ThisIsAShr)
4565 if (Sources.
empty() || Sources.
size() > MaxSources ||
4566 Worklist.
size() > MaxSources || !IsAShr)
4569 unsigned NumSources = Sources.
size();
4573 if (OrigIID == Intrinsic::vector_reduce_add &&
4581 (OrigIID == Intrinsic::vector_reduce_add) ? NumSources * NumElts : 1;
4584 NegativeVal.negate();
4616 TestsNegative =
false;
4617 }
else if (*CmpVal == NegativeVal) {
4618 TestsNegative =
true;
4622 IsEq = Pred == ICmpInst::ICMP_EQ;
4623 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeHigh) {
4625 TestsNegative = (RangeHigh == NegativeVal);
4626 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeHigh - 1) {
4628 TestsNegative = (RangeHigh == NegativeVal);
4629 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeLow) {
4631 TestsNegative = (RangeLow == NegativeVal);
4632 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeLow + 1) {
4634 TestsNegative = (RangeLow == NegativeVal);
4677 enum CheckKind :
unsigned {
4684 auto RequiresOr = [](CheckKind
C) ->
bool {
return C & 0b100; };
4686 auto IsNegativeCheck = [](CheckKind
C) ->
bool {
return C & 0b010; };
4688 auto Invert = [](CheckKind
C) {
return CheckKind(
C ^ 0b011); };
4692 case Intrinsic::vector_reduce_or:
4693 case Intrinsic::vector_reduce_umax:
4694 Base = TestsNegative ? AnyNeg : AllNonNeg;
4696 case Intrinsic::vector_reduce_and:
4697 case Intrinsic::vector_reduce_umin:
4698 Base = TestsNegative ? AllNeg : AnyNonNeg;
4700 case Intrinsic::vector_reduce_add:
4701 Base = TestsNegative ? AllNeg : AllNonNeg;
4716 return ArithCost <= MinMaxCost ? std::make_pair(Arith, ArithCost)
4717 : std::make_pair(MinMax, MinMaxCost);
4721 auto [NewIID, NewCost] = RequiresOr(
Check)
4722 ? PickCheaper(Intrinsic::vector_reduce_or,
4723 Intrinsic::vector_reduce_umax)
4724 : PickCheaper(
Intrinsic::vector_reduce_and,
4728 if (NumSources > 1) {
4729 unsigned CombineOpc =
4730 RequiresOr(
Check) ? Instruction::Or : Instruction::And;
4735 LLVM_DEBUG(
dbgs() <<
"Found sign-bit reduction cmp: " <<
I <<
"\n OldCost: "
4736 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4738 if (NewCost > OldCost)
4743 Type *ScalarTy = VecTy->getScalarType();
4746 if (NumSources == 1) {
4757 replaceValue(
I, *NewCmp);
4788bool VectorCombine::foldReductionZeroTest(Instruction &
I) {
4797 if (!
II || !
II->hasOneUse())
4800 auto ReduceID =
II->getIntrinsicID();
4801 if (ReduceID != Intrinsic::vector_reduce_or &&
4802 ReduceID != Intrinsic::vector_reduce_umax)
4805 Value *Vec =
II->getArgOperand(0);
4807 if (!VecTy || !VecTy->getElementType()->isIntegerTy())
4812 ? Intrinsic::vector_reduce_or
4827 LLVM_DEBUG(
dbgs() <<
"Found a reduction zero test: " <<
I <<
"\n OldCost: "
4828 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4830 if (!OldCost.
isValid() || !NewCost.
isValid() || NewCost > OldCost)
4836 replaceValue(
I, *NewReduce);
4861bool VectorCombine::foldICmpEqZeroVectorReduce(Instruction &
I) {
4872 switch (
II->getIntrinsicID()) {
4873 case Intrinsic::vector_reduce_add:
4874 case Intrinsic::vector_reduce_or:
4875 case Intrinsic::vector_reduce_umin:
4876 case Intrinsic::vector_reduce_umax:
4877 case Intrinsic::vector_reduce_smin:
4878 case Intrinsic::vector_reduce_smax:
4884 Value *InnerOp =
II->getArgOperand(0);
4927 switch (
II->getIntrinsicID()) {
4928 case Intrinsic::vector_reduce_add: {
4933 unsigned NumElems = XTy->getNumElements();
4939 if (LeadingZerosX <= LostBits || LeadingZerosFX <= LostBits)
4947 case Intrinsic::vector_reduce_smin:
4948 case Intrinsic::vector_reduce_smax:
4958 LLVM_DEBUG(
dbgs() <<
"Found a reduction to 0 comparison with removable op: "
4974 case Intrinsic::vector_reduce_add:
4975 case Intrinsic::vector_reduce_or:
4981 case Intrinsic::vector_reduce_umin:
4982 case Intrinsic::vector_reduce_umax:
4983 case Intrinsic::vector_reduce_smin:
4984 case Intrinsic::vector_reduce_smax:
4996 NewReduceCost + (InnerOp->
hasOneUse() ? 0 : ExtCost);
4998 LLVM_DEBUG(
dbgs() <<
"Found a removable extension before reduction: "
4999 << *InnerOp <<
"\n OldCost: " << OldCost
5000 <<
" vs NewCost: " << NewCost <<
"\n");
5006 if (NewCost > OldCost)
5015 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::getNullValue(Ty));
5016 replaceValue(
I, *NewCmp);
5047bool VectorCombine::foldEquivalentReductionCmp(Instruction &
I) {
5050 const APInt *CmpVal;
5055 if (!
II || !
II->hasOneUse())
5058 const auto IsValidOrUmaxCmp = [&]() {
5067 bool IsPositive = CmpVal->
isAllOnes() && Pred == ICmpInst::ICMP_SGT;
5069 bool IsNegative = (CmpVal->
isZero() || CmpVal->
isOne() || *CmpVal == 2) &&
5070 Pred == ICmpInst::ICMP_SLT;
5071 return IsEquality || IsPositive || IsNegative;
5074 const auto IsValidAndUminCmp = [&]() {
5079 const auto LeadingOnes = CmpVal->
countl_one();
5086 bool IsNegative = CmpVal->
isZero() && Pred == ICmpInst::ICMP_SLT;
5095 ((*CmpVal)[0] || (*CmpVal)[1]) && Pred == ICmpInst::ICMP_SGT;
5096 return IsEquality || IsNegative || IsPositive;
5104 switch (OriginalIID) {
5105 case Intrinsic::vector_reduce_or:
5106 if (!IsValidOrUmaxCmp())
5108 AlternativeIID = Intrinsic::vector_reduce_umax;
5110 case Intrinsic::vector_reduce_umax:
5111 if (!IsValidOrUmaxCmp())
5113 AlternativeIID = Intrinsic::vector_reduce_or;
5115 case Intrinsic::vector_reduce_and:
5116 if (!IsValidAndUminCmp())
5118 AlternativeIID = Intrinsic::vector_reduce_umin;
5120 case Intrinsic::vector_reduce_umin:
5121 if (!IsValidAndUminCmp())
5123 AlternativeIID = Intrinsic::vector_reduce_and;
5136 if (ReductionOpc != Instruction::ICmp)
5147 <<
"\n OrigCost: " << OrigCost
5148 <<
" vs AltCost: " << AltCost <<
"\n");
5150 if (AltCost >= OrigCost)
5154 Type *ScalarTy = VecTy->getScalarType();
5157 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::get(ScalarTy, *CmpVal));
5159 replaceValue(
I, *NewCmp);
5173 unsigned Depth = 0) {
5174 constexpr unsigned MaxLocalDepth = 2;
5175 if (
Depth > MaxLocalDepth)
5178 auto NumSignBits = [&](
const Value *
X) {
5181 if (NumSignBits(V) == V->getType()->getScalarSizeInBits())
5186 return NumSignBits(
A) >= 2 && NumSignBits(
B) >= 2 &&
5197bool VectorCombine::foldReduceAddCmpZero(Instruction &
I) {
5207 if (!VecTy || VecTy->getNumElements() < 2)
5213 if (!IsNonNegative && !IsNonPositive)
5218 unsigned NumElts = VecTy->getNumElements();
5220 if (
Log2_32(NumElts) >= NumSignBits)
5223 ICmpInst::Predicate NewPred;
5225 case ICmpInst::ICMP_EQ:
5226 case ICmpInst::ICMP_ULE:
5227 case ICmpInst::ICMP_SLE:
5228 case ICmpInst::ICMP_SGE:
5229 NewPred = ICmpInst::ICMP_EQ;
5231 case ICmpInst::ICMP_NE:
5232 case ICmpInst::ICMP_UGT:
5233 case ICmpInst::ICMP_SGT:
5234 case ICmpInst::ICMP_SLT:
5235 NewPred = ICmpInst::ICMP_NE;
5245 if (!IsNonNegative &&
5246 (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE))
5248 if (!IsNonPositive &&
5249 (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE))
5251 if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE ||
5252 Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) &&
5253 Log2_32(NumElts) >= NumSignBits - 1)
5257 Instruction::Add, VecTy, std::nullopt,
CostKind);
5259 Instruction::Or, VecTy, std::nullopt,
CostKind);
5261 Intrinsic::umax, VecTy, FastMathFlags(),
CostKind);
5264 bool UseOr = OrCost.
isValid() && (!UmaxCost.
isValid() || OrCost <= UmaxCost);
5266 if (AltCost > OrigCost)
5272 Intrinsic::vector_reduce_umax, {VecTy}, {Vec});
5273 Worklist.pushValue(NewReduce);
5275 NewPred, NewReduce, ConstantInt::getNullValue(VecTy->getScalarType()));
5276 replaceValue(
I, *NewCmp);
5285 constexpr unsigned MaxVisited = 32;
5288 bool FoundReduction =
false;
5291 while (!WorkList.
empty()) {
5293 for (
User *U :
I->users()) {
5295 if (!UI || !Visited.
insert(UI).second)
5297 if (Visited.
size() > MaxVisited)
5303 switch (
II->getIntrinsicID()) {
5304 case Intrinsic::vector_reduce_add:
5305 case Intrinsic::vector_reduce_mul:
5306 case Intrinsic::vector_reduce_and:
5307 case Intrinsic::vector_reduce_or:
5308 case Intrinsic::vector_reduce_xor:
5309 case Intrinsic::vector_reduce_smin:
5310 case Intrinsic::vector_reduce_smax:
5311 case Intrinsic::vector_reduce_umin:
5312 case Intrinsic::vector_reduce_umax:
5313 FoundReduction =
true;
5326 return FoundReduction;
5339bool VectorCombine::foldSelectShuffle(Instruction &
I,
bool FromReduction) {
5344 if (!Op0 || !Op1 || Op0 == Op1 || !Op0->isBinaryOp() || !Op1->isBinaryOp() ||
5352 SmallPtrSet<Instruction *, 4> InputShuffles({SVI0A, SVI0B, SVI1A, SVI1B});
5354 if (!
I ||
I->getOperand(0)->getType() != VT)
5356 return any_of(
I->users(), [&](User *U) {
5357 return U != Op0 && U != Op1 &&
5358 !(isa<ShuffleVectorInst>(U) &&
5359 (InputShuffles.contains(cast<Instruction>(U)) ||
5360 isInstructionTriviallyDead(cast<Instruction>(U))));
5363 if (checkSVNonOpUses(SVI0A) || checkSVNonOpUses(SVI0B) ||
5364 checkSVNonOpUses(SVI1A) || checkSVNonOpUses(SVI1B))
5372 for (
auto *U :
I->users()) {
5374 if (!SV || SV->getType() != VT)
5376 if ((SV->getOperand(0) != Op0 && SV->getOperand(0) != Op1) ||
5377 (SV->getOperand(1) != Op0 && SV->getOperand(1) != Op1))
5384 if (!collectShuffles(Op0) || !collectShuffles(Op1))
5388 if (FromReduction && Shuffles.
size() > 1)
5393 if (!FromReduction) {
5394 for (
size_t Idx = 0,
E = Shuffles.
size(); Idx !=
E; ++Idx) {
5395 for (
auto *U : Shuffles[Idx]->
users()) {
5410 int MaxV1Elt = 0, MaxV2Elt = 0;
5411 unsigned NumElts = VT->getNumElements();
5412 for (ShuffleVectorInst *SVN : Shuffles) {
5413 SmallVector<int>
Mask;
5414 SVN->getShuffleMask(Mask);
5418 Value *SVOp0 = SVN->getOperand(0);
5419 Value *SVOp1 = SVN->getOperand(1);
5424 for (
int &Elem : Mask) {
5430 if (SVOp0 == Op1 && SVOp1 == Op0) {
5434 if (SVOp0 != Op0 || SVOp1 != Op1)
5440 SmallVector<int> ReconstructMask;
5441 for (
unsigned I = 0;
I <
Mask.size();
I++) {
5444 }
else if (Mask[
I] <
static_cast<int>(NumElts)) {
5445 MaxV1Elt = std::max(MaxV1Elt, Mask[
I]);
5446 auto It =
find_if(
V1, [&](
const std::pair<int, int> &
A) {
5447 return Mask[
I] ==
A.first;
5453 V1.emplace_back(Mask[
I],
V1.size());
5456 MaxV2Elt = std::max<int>(MaxV2Elt, Mask[
I] - NumElts);
5457 auto It =
find_if(V2, [&](
const std::pair<int, int> &
A) {
5458 return Mask[
I] -
static_cast<int>(NumElts) ==
A.first;
5472 sort(ReconstructMask);
5473 OrigReconstructMasks.
push_back(std::move(ReconstructMask));
5480 if (
V1.empty() || V2.
empty() ||
5481 (MaxV1Elt ==
static_cast<int>(
V1.size()) - 1 &&
5482 MaxV2Elt ==
static_cast<int>(V2.
size()) - 1))
5494 if (InputShuffles.contains(SSV))
5496 return SV->getMaskValue(M);
5504 std::pair<int, int>
Y) {
5505 int MXA = GetBaseMaskValue(
A,
X.first);
5506 int MYA = GetBaseMaskValue(
A,
Y.first);
5510 return SortBase(SVI0A,
A,
B);
5512 stable_sort(V2, [&](std::pair<int, int>
A, std::pair<int, int>
B) {
5513 return SortBase(SVI1A,
A,
B);
5518 for (
const auto &Mask : OrigReconstructMasks) {
5519 SmallVector<int> ReconstructMask;
5520 for (
int M : Mask) {
5522 auto It =
find_if(V, [M](
auto A) {
return A.second ==
M; });
5523 assert(It !=
V.end() &&
"Expected all entries in Mask");
5524 return std::distance(
V.begin(), It);
5528 else if (M <
static_cast<int>(NumElts)) {
5531 ReconstructMask.
push_back(NumElts + FindIndex(V2, M));
5534 ReconstructMasks.
push_back(std::move(ReconstructMask));
5539 SmallVector<int> V1A, V1B, V2A, V2B;
5540 for (
unsigned I = 0;
I <
V1.size();
I++) {
5544 for (
unsigned I = 0;
I < V2.
size();
I++) {
5545 V2A.
push_back(GetBaseMaskValue(SVI1A, V2[
I].first));
5546 V2B.
push_back(GetBaseMaskValue(SVI1B, V2[
I].first));
5548 while (V1A.
size() < NumElts) {
5552 while (V2A.
size() < NumElts) {
5564 VT, VT, SV->getShuffleMask(),
CostKind);
5571 unsigned ElementSize = VT->getElementType()->getPrimitiveSizeInBits();
5572 unsigned MaxVectorSize =
5574 unsigned MaxElementsInVector = MaxVectorSize / ElementSize;
5575 if (MaxElementsInVector == 0)
5584 std::set<SmallVector<int, 4>> UniqueShuffles;
5589 unsigned NumFullVectors =
Mask.size() / MaxElementsInVector;
5590 if (NumFullVectors < 2)
5591 return C + ShuffleCost;
5592 SmallVector<int, 4> SubShuffle(MaxElementsInVector);
5593 unsigned NumUniqueGroups = 0;
5594 unsigned NumGroups =
Mask.size() / MaxElementsInVector;
5597 for (
unsigned I = 0;
I < NumFullVectors; ++
I) {
5598 for (
unsigned J = 0; J < MaxElementsInVector; ++J)
5599 SubShuffle[J] = Mask[MaxElementsInVector *
I + J];
5600 if (UniqueShuffles.insert(SubShuffle).second)
5601 NumUniqueGroups += 1;
5603 return C + ShuffleCost * NumUniqueGroups / NumGroups;
5609 SmallVector<int, 16>
Mask;
5610 SV->getShuffleMask(Mask);
5611 return AddShuffleMaskAdjustedCost(
C, Mask);
5614 auto AllShufflesHaveSameOperands =
5615 [](SmallPtrSetImpl<Instruction *> &InputShuffles) {
5616 if (InputShuffles.size() < 2)
5618 ShuffleVectorInst *FirstSV =
5625 std::next(InputShuffles.begin()), InputShuffles.end(),
5626 [&](Instruction *
I) {
5627 ShuffleVectorInst *SV = dyn_cast<ShuffleVectorInst>(I);
5628 return SV && SV->getOperand(0) == In0 && SV->getOperand(1) == In1;
5637 CostBefore += std::accumulate(Shuffles.begin(), Shuffles.end(),
5639 if (AllShufflesHaveSameOperands(InputShuffles)) {
5640 UniqueShuffles.clear();
5641 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5644 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5650 FixedVectorType *Op0SmallVT =
5652 FixedVectorType *Op1SmallVT =
5657 UniqueShuffles.clear();
5658 CostAfter += std::accumulate(ReconstructMasks.begin(), ReconstructMasks.end(),
5660 std::set<SmallVector<int>> OutputShuffleMasks({V1A, V1B, V2A, V2B});
5662 std::accumulate(OutputShuffleMasks.begin(), OutputShuffleMasks.end(),
5665 LLVM_DEBUG(
dbgs() <<
"Found a binop select shuffle pattern: " <<
I <<
"\n");
5667 <<
" vs CostAfter: " << CostAfter <<
"\n");
5668 if (CostBefore < CostAfter ||
5679 if (InputShuffles.contains(SSV))
5681 return SV->getOperand(
Op);
5685 GetShuffleOperand(SVI0A, 1), V1A);
5688 GetShuffleOperand(SVI0B, 1), V1B);
5691 GetShuffleOperand(SVI1A, 1), V2A);
5694 GetShuffleOperand(SVI1B, 1), V2B);
5699 I->copyIRFlags(Op0,
true);
5704 I->copyIRFlags(Op1,
true);
5706 for (
int S = 0,
E = ReconstructMasks.size(); S !=
E; S++) {
5709 replaceValue(*Shuffles[S], *NSV,
false);
5712 Worklist.pushValue(NSV0A);
5713 Worklist.pushValue(NSV0B);
5714 Worklist.pushValue(NSV1A);
5715 Worklist.pushValue(NSV1B);
5725bool VectorCombine::shrinkType(Instruction &
I) {
5726 Value *ZExted, *OtherOperand;
5732 Value *ZExtOperand =
I.getOperand(
I.getOperand(0) == OtherOperand ? 1 : 0);
5736 unsigned BW = SmallTy->getElementType()->getPrimitiveSizeInBits();
5738 if (
I.getOpcode() == Instruction::LShr) {
5755 Instruction::ZExt, BigTy, SmallTy,
5756 TargetTransformInfo::CastContextHint::None,
CostKind);
5761 for (User *U : ZExtOperand->
users()) {
5768 ShrinkCost += ZExtCost;
5783 ShrinkCost += ZExtCost;
5790 Instruction::Trunc, SmallTy, BigTy,
5791 TargetTransformInfo::CastContextHint::None,
CostKind);
5796 if (ShrinkCost > CurrentCost)
5800 Value *Op0 = ZExted;
5803 if (
I.getOperand(0) == OtherOperand)
5810 replaceValue(
I, *NewZExtr);
5816bool VectorCombine::foldInsExtVectorToShuffle(Instruction &
I) {
5817 Value *DstVec, *SrcVec;
5818 uint64_t ExtIdx, InsIdx;
5828 if (!DstVecTy || !SrcVecTy ||
5834 if (InsIdx >= NumDstElts || ExtIdx >= NumSrcElts || NumDstElts == 1)
5841 bool NeedExpOrNarrow = NumSrcElts != NumDstElts;
5843 if (NeedDstSrcSwap) {
5845 Mask[InsIdx] = ExtIdx % NumDstElts;
5849 std::iota(
Mask.begin(),
Mask.end(), 0);
5850 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
5863 SmallVector<int> ExtToVecMask;
5864 if (!NeedExpOrNarrow) {
5869 nullptr, {DstVec, SrcVec});
5875 ExtToVecMask[ExtIdx % NumDstElts] = ExtIdx;
5878 DstVecTy, SrcVecTy, ExtToVecMask,
CostKind);
5882 if (!Ext->hasOneUse())
5885 LLVM_DEBUG(
dbgs() <<
"Found a insert/extract shuffle-like pair: " <<
I
5886 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
5889 if (OldCost < NewCost)
5892 if (NeedExpOrNarrow) {
5893 if (!NeedDstSrcSwap)
5906 replaceValue(
I, *Shuf);
5915bool VectorCombine::foldInterleaveIntrinsics(Instruction &
I) {
5916 const APInt *SplatVal0, *SplatVal1;
5926 auto *ExtVTy = VectorType::getExtendedElementVectorType(VTy);
5927 unsigned Width = VTy->getElementType()->getIntegerBitWidth();
5936 LLVM_DEBUG(
dbgs() <<
"VC: The cost to cast from " << *ExtVTy <<
" to "
5937 << *
I.getType() <<
" is too high.\n");
5941 APInt NewSplatVal = SplatVal1->
zext(Width * 2);
5942 NewSplatVal <<= Width;
5943 NewSplatVal |= SplatVal0->
zext(Width * 2);
5945 ExtVTy->getElementCount(), ConstantInt::get(
F.getContext(), NewSplatVal));
5980bool VectorCombine::foldDeinterleaveIntrinsics(Instruction &
I) {
5982 if (
DL->isBigEndian())
5985 using namespace PatternMatch;
5986 Value *DeinterleavedVal;
5997 unsigned HalfElementWidth = ElementWidth / 2;
6001 std::array<ExtractValueInst *, 2> OrigFields{};
6002 for (User *Usr :
I.users()) {
6005 if (!
E ||
E->getNumIndices() != 1)
6007 unsigned Idx = *
E->idx_begin();
6009 if (Idx >= 2 || OrigFields[Idx] || !
E->hasNUses(2))
6011 OrigFields[Idx] =
E;
6015 SmallVector<Instruction *, 2> MergeInsts;
6016 for (
auto *FieldUsr : OrigFields[0]->
users()) {
6024 auto MatchMerge = [&](void) ->
bool {
6027 return match(MergeInsts[0],
6031 match(MergeInsts[1],
6036 if (!MatchMerge()) {
6037 std::swap(MergeInsts[0], MergeInsts[1]);
6052 auto *NewFieldTy = VecTy->getWithNewBitWidth(HalfElementWidth);
6062 if (OldCost <= NewCost || !NewCost.
isValid()) {
6064 dbgs() <<
"VC: New deinterleave2 sequence cost (" << NewCost <<
")"
6065 <<
" is higher than that of the old one (" << OldCost <<
")\n");
6073 Intrinsic::vector_deinterleave2, {NewVecTy}, {NewVecCast});
6074 for (
auto [Idx, MergeInst] :
enumerate(MergeInsts)) {
6076 NewField = Builder.
CreateBitCast(NewField, MergeInst->getType());
6077 replaceValue(*MergeInst, *NewField);
6083bool VectorCombine::foldBitcastOfVPLoad(Instruction &
I) {
6084 const DataLayout &
DL =
I.getDataLayout();
6099 DL.getValueOrABITypeAlignment(
II->getPointerAlignment(), OrigVecTy);
6100 ElementCount OrigVecCnt = OrigVecTy->getElementCount();
6102 ElementCount NewVecCnt = NewVecTy->getElementCount();
6114 II->getMemoryPointerParam(),
false,
6120 {Intrinsic::vp_load, NewVecTy,
II->getMemoryPointerParam(),
false,
6124 <<
" NewCost=" << NewCost <<
"\n");
6125 if (NewCost > OldCost || !NewCost.
isValid())
6132 NewVecTy, Intrinsic::vp_load,
6133 {
II->getMemoryPointerParam(), NewMask, NewEVL});
6136 0, AttrBuilder(
II->getContext()).addAlignmentAttr(OrigAlign));
6137 replaceValue(*Cast, *NewVP);
6147bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &
I) {
6151 Type *Ty =
X->getType();
6152 Type *VecTy =
I.getOperand(0)->getType();
6166 if (CanUseBswap || CanUseFshl) {
6177 IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
6178 IntrinsicCostAttributes ICABFshl(Intrinsic::fshl, Ty, {
X,
X, HalfBW},
6180 IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
6185 if (!InnerCall->hasOneUse())
6188 else if (!InnerBitCast->hasOneUse())
6191 <<
"\n OldCost: " << OldCost
6192 <<
" vs NewCost: " << NewCost <<
"\n");
6193 if (NewCost.isValid() && NewCost < OldCost) {
6199 Worklist.pushValue(Swap);
6201 replaceValue(
I, *BRev);
6210 Type *Ty =
I.getType();
6212 TypeSize ElementSize =
DL->getTypeStoreSize(Ty);
6215 Type *NewVecTy = VectorType::get(I8Ty, NewVecCnt);
6228 IntrinsicCostAttributes ICANew(Intrinsic::bitreverse, NewVecTy, {NewVecTy});
6231 InstructionCost NewCost = CastToVecCost + NewIntrinsicCost + CastToOrigCost;
6232 if (!InnerII->hasOneUse())
6235 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6237 if (!NewCost.
isValid() || NewCost >= OldCost)
6245 replaceValue(
I, *CastToOrig);
6255 unsigned RawNumElements = MaxIdx + 1u;
6258 if (!
TTI.isTypeLegal(ElemTy))
6259 return RawNumElements;
6261 TypeSize ElemSize =
DL.getTypeSizeInBits(ElemTy);
6263 return RawNumElements;
6268 return RawNumElements;
6273 if (ElemsPerReg == 0 || RawNumElements <= ElemsPerReg)
6274 return RawNumElements;
6276 return alignTo(RawNumElements, ElemsPerReg);
6280bool VectorCombine::shrinkLoadForShuffles(Instruction &
I) {
6282 if (!OldLoad || !OldLoad->isSimple())
6289 unsigned const OldNumElements = OldLoadTy->getNumElements();
6295 using IndexRange = std::pair<int, int>;
6296 auto GetIndexRangeInShuffles = [&]() -> std::optional<IndexRange> {
6297 IndexRange OutputRange = IndexRange(OldNumElements, -1);
6298 for (llvm::Use &Use :
I.uses()) {
6300 User *Shuffle =
Use.getUser();
6305 return std::nullopt;
6312 for (
int Index : Mask) {
6313 if (Index >= 0 && Index <
static_cast<int>(OldNumElements)) {
6314 OutputRange.first = std::min(Index, OutputRange.first);
6315 OutputRange.second = std::max(Index, OutputRange.second);
6320 if (OutputRange.second < OutputRange.first)
6321 return std::nullopt;
6327 if (std::optional<IndexRange> Indices = GetIndexRangeInShuffles()) {
6328 unsigned const NewNumElements =
6333 if (NewNumElements < OldNumElements) {
6338 Type *ElemTy = OldLoadTy->getElementType();
6340 Value *PtrOp = OldLoad->getPointerOperand();
6343 Instruction::Load, OldLoad->getType(), OldLoad->getAlign(),
6344 OldLoad->getPointerAddressSpace(),
CostKind);
6347 OldLoad->getPointerAddressSpace(),
CostKind);
6349 using UseEntry = std::pair<ShuffleVectorInst *, std::vector<int>>;
6351 unsigned const MaxIndex = NewNumElements * 2u;
6353 for (llvm::Use &Use :
I.uses()) {
6360 ArrayRef<int> OldMask = Shuffle->getShuffleMask();
6366 for (
int Index : OldMask) {
6367 if (Index >=
static_cast<int>(MaxIndex))
6381 dbgs() <<
"Found a load used only by shufflevector instructions: "
6382 <<
I <<
"\n OldCost: " << OldCost
6383 <<
" vs NewCost: " << NewCost <<
"\n");
6385 if (OldCost < NewCost || !NewCost.
isValid())
6391 NewLoad->copyMetadata(
I);
6394 for (UseEntry &Use : NewUses) {
6395 ShuffleVectorInst *Shuffle =
Use.first;
6396 std::vector<int> &NewMask =
Use.second;
6403 replaceValue(*Shuffle, *NewShuffle,
false);
6416bool VectorCombine::shrinkPhiOfShuffles(Instruction &
I) {
6418 if (!Phi ||
Phi->getNumIncomingValues() != 2u)
6422 ArrayRef<int> Mask0;
6423 ArrayRef<int> Mask1;
6436 auto const InputNumElements = InputVT->getNumElements();
6438 if (InputNumElements >= ResultVT->getNumElements())
6443 SmallVector<int, 16> NewMask;
6446 for (
auto [
M0,
M1] :
zip(Mask0, Mask1)) {
6447 if (
M0 >= 0 &&
M1 >= 0)
6449 else if (
M0 == -1 &&
M1 == -1)
6462 int MaskOffset = NewMask[0
u];
6463 unsigned Index = (InputNumElements + MaskOffset) % InputNumElements;
6466 for (
unsigned I = 0u;
I < InputNumElements; ++
I) {
6480 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6483 if (NewCost > OldCost)
6495 auto *NewPhi = Builder.
CreatePHI(NewShuf0->getType(), 2u);
6497 NewPhi->addIncoming(
Op,
Phi->getIncomingBlock(1u));
6503 replaceValue(*Phi, *NewShuf1);
6509bool VectorCombine::run() {
6523 auto Opcode =
I.getOpcode();
6531 if (IsFixedVectorType) {
6533 case Instruction::InsertElement:
6534 if (vectorizeLoadInsert(
I))
6537 case Instruction::ShuffleVector:
6538 if (widenSubvectorLoad(
I))
6549 if (scalarizeOpOrCmp(
I))
6551 if (scalarizeLoad(
I))
6553 if (scalarizeExtExtract(
I))
6555 if (scalarizeVPIntrinsic(
I))
6557 if (foldInterleaveIntrinsics(
I))
6559 if (foldBitcastOfVPLoad(
I))
6563 if (foldDeinterleaveIntrinsics(
I))
6566 if (Opcode == Instruction::Store)
6567 if (foldSingleElementStore(
I))
6571 if (TryEarlyFoldsOnly)
6574 if (Opcode == Instruction::Call)
6575 if (foldBitOrderReverseAndSwap(
I))
6577 if (Opcode == Instruction::BitCast)
6578 if (foldBitOrderReverseAndSwap(
I))
6585 if (IsFixedVectorType) {
6587 case Instruction::InsertElement:
6588 if (foldInsExtFNeg(
I))
6590 if (foldInsExtBinop(
I))
6592 if (foldInsExtVectorToShuffle(
I))
6595 case Instruction::ShuffleVector:
6596 if (foldPermuteOfBinops(
I))
6598 if (foldShuffleOfBinops(
I))
6600 if (foldShuffleOfSelects(
I))
6602 if (foldShuffleOfCastops(
I))
6604 if (foldShuffleOfShuffles(
I))
6606 if (foldPermuteOfIntrinsic(
I))
6608 if (foldShufflesOfLengthChangingShuffles(
I))
6610 if (foldShuffleOfIntrinsics(
I))
6612 if (foldSelectShuffle(
I))
6614 if (foldShuffleToIdentity(
I))
6617 case Instruction::Load:
6618 if (shrinkLoadForShuffles(
I))
6621 case Instruction::BitCast:
6622 if (foldBitcastShuffle(
I))
6624 if (foldSelectsFromBitcast(
I))
6627 case Instruction::And:
6628 case Instruction::Or:
6629 case Instruction::Xor:
6630 if (foldBitOpOfCastops(
I))
6632 if (foldBitOpOfCastConstant(
I))
6635 case Instruction::PHI:
6636 if (shrinkPhiOfShuffles(
I))
6646 case Instruction::Call:
6647 if (foldShuffleFromReductions(
I))
6649 if (foldCastFromReductions(
I))
6652 case Instruction::ExtractElement:
6653 if (foldShuffleChainsToReduce(
I))
6656 case Instruction::ICmp:
6657 if (foldSignBitReductionCmp(
I))
6659 if (foldICmpEqZeroVectorReduce(
I))
6661 if (foldReductionZeroTest(
I))
6663 if (foldEquivalentReductionCmp(
I))
6665 if (foldReduceAddCmpZero(
I))
6668 case Instruction::FCmp:
6669 if (foldExtractExtract(
I))
6672 case Instruction::Or:
6673 if (foldConcatOfBoolMasks(
I))
6678 if (foldExtractExtract(
I))
6680 if (foldExtractedCmps(
I))
6682 if (foldBinopOfReductions(
I))
6691 bool MadeChange =
false;
6692 for (BasicBlock &BB :
F) {
6704 if (!
I->isDebugOrPseudoInst())
6705 MadeChange |= FoldInst(*
I);
6712 while (!Worklist.isEmpty()) {
6722 MadeChange |= FoldInst(*
I);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< unsigned > MaxInstrsToScan("aggressive-instcombine-max-scan-instrs", cl::init(64), cl::Hidden, cl::desc("Max number of instructions to scan for aggressive instcombine."))
This is the interface for LLVM's primary stateless and local alias analysis.
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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static cl::opt< IntrinsicCostStrategy > IntrinsicCost("intrinsic-cost-strategy", cl::desc("Costing strategy for intrinsic instructions"), cl::init(IntrinsicCostStrategy::InstructionCost), cl::values(clEnumValN(IntrinsicCostStrategy::InstructionCost, "instruction-cost", "Use TargetTransformInfo::getInstructionCost"), clEnumValN(IntrinsicCostStrategy::IntrinsicCost, "intrinsic-cost", "Use TargetTransformInfo::getIntrinsicInstrCost"), clEnumValN(IntrinsicCostStrategy::TypeBasedIntrinsicCost, "type-based-intrinsic-cost", "Calculate the intrinsic cost based only on argument types")))
This file defines the DenseMap class.
This is the interface for a simple mod/ref and alias analysis over globals.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
static bool isEquivBitcast(Value *X, Value *Y)
Helper to peek through bitcasts to the same value.
static bool isFreeConcat(ArrayRef< InstLane > Item, TTI::TargetCostKind CostKind, const TargetTransformInfo &TTI)
Detect concat of multiple values into a vector.
static void analyzeCostOfVecReduction(const IntrinsicInst &II, TTI::TargetCostKind CostKind, const TargetTransformInfo &TTI, InstructionCost &CostBeforeReduction, InstructionCost &CostAfterReduction)
static Value * generateNewInstTree(ArrayRef< InstLane > Item, Use *From, const DenseSet< std::pair< Value *, Use * > > &IdentityLeafs, const DenseSet< std::pair< Value *, Use * > > &SplatLeafs, const DenseSet< std::pair< Value *, Use * > > &ConcatLeafs, IRBuilderBase &Builder, InstructionWorklist &WorkList, const TargetTransformInfo *TTI)
static SmallVector< InstLane > generateInstLaneVectorFromOperand(ArrayRef< InstLane > Item, int Op)
static Value * createShiftShuffle(Value *Vec, unsigned OldIndex, unsigned NewIndex, IRBuilderBase &Builder)
Create a shuffle that translates (shifts) 1 element from the input vector to a new element location.
std::pair< Value *, int > InstLane
static bool isKnownNonPositive(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Used by foldReduceAddCmpZero to check if we can prove that a value is non-positive.
static Align computeAlignmentAfterScalarization(Align VectorAlignment, Type *ScalarType, Value *Idx, const DataLayout &DL)
The memory operation on a vector of ScalarType had alignment of VectorAlignment.
static bool feedsIntoVectorReduction(ShuffleVectorInst *SVI)
Returns true if this ShuffleVectorInst eventually feeds into a vector reduction intrinsic (e....
static cl::opt< bool > DisableVectorCombine("disable-vector-combine", cl::init(false), cl::Hidden, cl::desc("Disable all vector combine transforms"))
static bool canWidenLoad(LoadInst *Load, const TargetTransformInfo &TTI)
static const unsigned InvalidIndex
static Value * translateExtract(ExtractElementInst *ExtElt, unsigned NewIndex, IRBuilderBase &Builder)
Given an extract element instruction with constant index operand, shuffle the source vector (shift th...
static ScalarizationResult canScalarizeAccess(VectorType *VecTy, Value *Idx, const SimplifyQuery &SQ)
Check if it is legal to scalarize a memory access to VecTy at index Idx.
static cl::opt< unsigned > MaxInstrsToScan("vector-combine-max-scan-instrs", cl::init(30), cl::Hidden, cl::desc("Max number of instructions to scan for vector combining."))
static cl::opt< bool > DisableBinopExtractShuffle("disable-binop-extract-shuffle", cl::init(false), cl::Hidden, cl::desc("Disable binop extract to shuffle transforms"))
static unsigned getAlignedNumElements(unsigned MaxIdx, FixedVectorType *LoadTy, const TargetTransformInfo &TTI, const DataLayout &DL)
Given the maximum shuffle index and load vector type, compute the number of elements for the shrunk l...
static InstLane lookThroughShuffles(Value *V, int Lane)
static bool isMemModifiedBetween(BasicBlock::iterator Begin, BasicBlock::iterator End, const MemoryLocation &Loc, AAResults &AA)
static constexpr int Concat[]
A manager for alias analyses.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
uint64_t getZExtValue() const
Get zero extended value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
unsigned countl_one() const
Count the number of leading one bits.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
InstListType::iterator iterator
Instruction iterators...
BinaryOps getOpcode() const
Represents analyses that only rely on functions' control flow.
Value * getArgOperand(unsigned i) const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void addParamAttrs(unsigned ArgNo, const AttrBuilder &B)
Adds attributes to the indicated argument.
static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
bool isFPPredicate() const
static LLVM_ABI std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)
Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This class represents a range of values.
LLVM_ABI ConstantRange urem(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an unsigned remainder operation of...
LLVM_ABI ConstantRange binaryAnd(const ConstantRange &Other) const
Return a new range representing the possible values resulting from a binary-and of a value in this ra...
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
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.
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Convenience struct for specifying and reasoning about fast-math flags.
bool noSignedZeros() const
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static FixedVectorType * getDoubleElementsVectorType(FixedVectorType *VTy)
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
bool isEquality() const
Return true if this predicate is either EQ or NE.
Common base class shared among various IRBuilders.
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 * CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
LLVM_ABI Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
ConstantInt * getTrue()
Get the constant value for i1 true.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Value * CreateIsNotNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg > -1.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Value * CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Value * CreateIsNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg < 0.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI Value * CreateNAryOp(unsigned Opc, ArrayRef< Value * > Ops, const Twine &Name="", MDNode *FPMathTag=nullptr)
Create either a UnaryOperator or BinaryOperator depending on Opc.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreateAnd(Value *LHS, Value *RHS, 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.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 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 * CreateFNegFMF(Value *V, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
InstructionWorklist - This is the worklist management logic for InstCombine and other simplification ...
void push(Instruction *I)
Push the instruction onto the worklist stack.
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void copyIRFlags(const Value *V, bool IncludeWrapFlags=true)
Convenience method to copy supported exact, fast-math, and (optionally) wrapping flags from V to this...
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void setNonNeg(bool b=true)
Set or clear the nneg flag on this instruction, which must be a zext instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isIdempotent() const
Return true if the instruction is idempotent:
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI bool hasAllowReassoc() const LLVM_READONLY
Determine whether the allow-reassociation flag is set.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Type * getPointerOperandType() const
Align getAlign() const
Return the alignment of the access that is being performed.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
const SDValue & getOperand(unsigned Num) const
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This instruction constructs a fixed permutation of two input vectors.
int getMaskValue(unsigned Elt) const
Return the shuffle mask value of this instruction for the given element index.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static void commuteShuffleMask(MutableArrayRef< int > Mask, unsigned InVecNumElts)
Change values in a shuffle permute mask assuming the two vector operands of length InVecNumElts have ...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void setAlignment(Align Align)
Analysis pass providing the TargetTransformInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
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.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
static LLVM_ABI bool isVPBinOp(Intrinsic::ID ID)
std::optional< unsigned > getFunctionalIntrinsicID() const
std::optional< unsigned > getFunctionalOpcode() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
const Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const
This is a wrapper around stripAndAccumulateConstantOffsets with the in-bounds requirement set to fals...
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
unsigned getValueID() const
Return an ID for the concrete type of this object.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS.multiplyCoefficientBy(X) will result in a value whos...
constexpr ScalarTy getFixedValue() const
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS.multiplyCoefficientBy(X) will result in a value whose quantity matches ou...
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
match_combine_and< Ty... > m_CombineAnd(const Ty &...Ps)
Combine pattern matchers matching all of Ps patterns.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_BSwap(const Opnd0 &Op0)
auto m_Cmp()
Matches any compare instruction and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
auto m_BitReverse(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::URem > m_URem(const LHS &L, const RHS &R)
auto m_Poison()
Match an arbitrary poison constant.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
BinOpPred_match< LHS, RHS, is_right_shift_op > m_Shr(const LHS &L, const RHS &R)
Matches logical shift operations.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_Constant()
Match an arbitrary Constant and ignore it.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
cst_pred_ty< is_non_zero_int > m_NonZeroInt()
Match a non-zero integer or a vector with all non-zero elements.
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWShl(const LHS &L, const RHS &R)
auto m_AnyIntrinsic()
Matches any intrinsic call and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
BinOpPred_match< LHS, RHS, is_bitwiselogic_op, true > m_c_BitwiseLogic(const LHS &L, const RHS &R)
Matches bitwise logic operations in either order.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
match_combine_or< CastInst_match< OpTy, SExtInst >, NNegZExt_match< OpTy > > m_SExtLike(const OpTy &Op)
Match either "sext" or "zext nneg".
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_Deinterleave2(const Opnd &Op)
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
auto m_Undef()
Match an arbitrary undef constant.
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.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
void stable_sort(R &&Range)
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Intrinsic::ID getMinMaxReductionIntrinsicOp(Intrinsic::ID RdxID)
Returns the min/max intrinsic used when expanding a min/max reduction.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
RelativeUniformCounterPtr Values
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
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.
LLVM_ABI Value * simplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q)
Given operand for a UnaryOperator, fold the result or return null.
scope_exit(Callable) -> scope_exit< Callable >
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI unsigned getArithmeticReductionInstruction(Intrinsic::ID RdxID)
Returns the arithmetic instruction opcode used when expanding a reduction.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
LLVM_ABI Value * simplifyCall(CallBase *Call, Value *Callee, ArrayRef< Value * > Args, const SimplifyQuery &Q)
Given a callsite, callee, and arguments, fold the result or return null.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool mustSuppressSpeculation(const LoadInst &LI)
Return true if speculation of the given load must be suppressed to avoid ordering or interfering with...
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
unsigned M1(unsigned Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI bool programUndefinedIfPoison(const Instruction *Inst)
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, Instruction *ScanFrom, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
LLVM_ABI void propagateIRFlags(Value *I, ArrayRef< Value * > VL, Value *OpValue=nullptr, bool IncludeWrapFlags=true)
Get the intersection (logical and) of all of the potential IR flags of each scalar operation (VL) tha...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr int PoisonMaskElem
LLVM_ABI bool isSafeToSpeculativelyExecuteWithOpcode(unsigned Opcode, const Instruction *Inst, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
This returns the same result as isSafeToSpeculativelyExecute if Opcode is the actual opcode of Inst.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI Intrinsic::ID getReductionForBinop(Instruction::BinaryOps Opc)
Returns the reduction intrinsic id corresponding to the binary operation.
@ And
Bitwise or logical AND of integers.
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
constexpr unsigned BitWidth
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
LLVM_ABI Constant * getLosslessInvCast(Constant *C, Type *InvCastTo, unsigned CastOp, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)
Try to cast C to InvC losslessly, satisfying CastOp(InvC) equals C, or CastOp(InvC) is a refined valu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
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.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
LLVM_ABI bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
LLVM_ABI Intrinsic::ID getMinMaxReductionIntrinsicID(Intrinsic::ID IID)
Returns the llvm.vector.reduce min/max intrinsic that corresponds to the intrinsic op.
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.
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
SimplifyQuery getWithInstruction(const Instruction *I) const