47#define DEBUG_TYPE "vector-combine"
53STATISTIC(NumVecLoad,
"Number of vector loads formed");
54STATISTIC(NumVecCmp,
"Number of vector compares formed");
55STATISTIC(NumVecBO,
"Number of vector binops formed");
56STATISTIC(NumVecCmpBO,
"Number of vector compare + binop formed");
57STATISTIC(NumShufOfBitcast,
"Number of shuffles moved after bitcast");
58STATISTIC(NumScalarOps,
"Number of scalar unary + binary ops formed");
59STATISTIC(NumScalarCmp,
"Number of scalar compares formed");
60STATISTIC(NumScalarIntrinsic,
"Number of scalar intrinsic calls formed");
64 cl::desc(
"Disable all vector combine transforms"));
68 cl::desc(
"Disable binop extract to shuffle transforms"));
72 cl::desc(
"Max number of instructions to scan for vector combining."));
74static const unsigned InvalidIndex = std::numeric_limits<unsigned>::max();
82 bool TryEarlyFoldsOnly)
85 SQ(*
DL, nullptr, &DT, &AC),
86 TryEarlyFoldsOnly(TryEarlyFoldsOnly) {}
93 const TargetTransformInfo &TTI;
94 const DominatorTree &DT;
98 const SimplifyQuery SQ;
102 bool TryEarlyFoldsOnly;
104 InstructionWorklist Worklist;
113 bool vectorizeLoadInsert(Instruction &
I);
114 bool widenSubvectorLoad(Instruction &
I);
115 ExtractElementInst *getShuffleExtract(ExtractElementInst *Ext0,
116 ExtractElementInst *Ext1,
117 unsigned PreferredExtractIndex)
const;
118 bool isExtractExtractCheap(ExtractElementInst *Ext0, ExtractElementInst *Ext1,
119 const Instruction &
I,
120 ExtractElementInst *&ConvertToShuffle,
121 unsigned PreferredExtractIndex);
124 bool foldExtractExtract(Instruction &
I);
125 bool foldInsExtFNeg(Instruction &
I);
126 bool foldInsExtBinop(Instruction &
I);
127 bool foldInsExtVectorToShuffle(Instruction &
I);
128 bool foldBitOpOfCastops(Instruction &
I);
129 bool foldBitOpOfCastConstant(Instruction &
I);
130 bool foldBitcastShuffle(Instruction &
I);
131 bool scalarizeOpOrCmp(Instruction &
I);
132 bool foldExtractedCmps(Instruction &
I);
133 bool foldSelectsFromBitcast(Instruction &
I);
134 bool foldBinopOfReductions(Instruction &
I);
135 bool foldInsertElementsToStores(Instruction &
I);
136 bool scalarizeLoad(Instruction &
I);
137 bool scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
Value *Ptr);
138 bool scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
Value *Ptr);
139 bool scalarizeExtExtract(Instruction &
I);
140 bool foldConcatOfBoolMasks(Instruction &
I);
141 bool foldPermuteOfBinops(Instruction &
I);
142 bool foldShuffleOfBinops(Instruction &
I);
143 bool foldShuffleOfSelects(Instruction &
I);
144 bool foldShuffleOfCastops(Instruction &
I);
145 bool foldShuffleOfShuffles(Instruction &
I);
146 bool foldPermuteOfIntrinsic(Instruction &
I);
147 bool foldShufflesOfLengthChangingShuffles(Instruction &
I);
148 bool foldShuffleOfIntrinsics(Instruction &
I);
149 bool foldShuffleToIdentity(Instruction &
I);
150 bool foldShuffleFromReductions(Instruction &
I);
151 bool foldShuffleChainsToReduce(Instruction &
I);
152 bool foldCastFromReductions(Instruction &
I);
153 bool foldSignBitReductionCmp(Instruction &
I);
154 bool foldReductionZeroTest(Instruction &
I);
155 bool foldICmpEqZeroVectorReduce(Instruction &
I);
156 bool foldEquivalentReductionCmp(Instruction &
I);
157 bool foldReduceAddCmpZero(Instruction &
I);
158 bool foldSelectShuffle(Instruction &
I,
bool FromReduction =
false);
159 bool foldInterleaveIntrinsics(Instruction &
I);
160 bool foldDeinterleaveIntrinsics(Instruction &
I);
161 bool foldBitcastOfVPLoad(Instruction &
I);
162 bool foldBitOrderReverseAndSwap(Instruction &
I);
163 bool shrinkType(Instruction &
I);
164 bool shrinkLoadForShuffles(Instruction &
I);
165 bool shrinkPhiOfShuffles(Instruction &
I);
166 bool foldDeinterleaveInterleavePair(Instruction &
I);
168 void replaceValue(Instruction &Old,
Value &New,
bool Erase =
true) {
174 Worklist.pushUsersToWorkList(*NewI);
175 Worklist.pushValue(NewI);
192 SmallPtrSet<Value *, 4> Visited;
197 OpI,
nullptr,
nullptr, [&](
Value *V) {
202 NextInst = NextInst->getNextNode();
207 Worklist.pushUsersToWorkList(*OpI);
208 Worklist.pushValue(OpI);
226 return X->getType() ==
Y->getType() &&
235 Load->getFunction()->hasFnAttribute(Attribute::SanitizeMemTag) ||
241 Type *ScalarTy =
Load->getType()->getScalarType();
243 unsigned MinVectorSize =
TTI.getMinVectorRegisterBitWidth();
244 if (!ScalarSize || !MinVectorSize || MinVectorSize % ScalarSize != 0 ||
251bool VectorCombine::vectorizeLoadInsert(
Instruction &
I) {
277 Value *SrcPtr =
Load->getPointerOperand()->stripPointerCasts();
280 unsigned MinVecNumElts = MinVectorSize / ScalarSize;
281 auto *MinVecTy = VectorType::get(ScalarTy, MinVecNumElts,
false);
282 unsigned OffsetEltIndex = 0;
290 unsigned OffsetBitWidth =
DL->getIndexTypeSizeInBits(SrcPtr->
getType());
291 APInt
Offset(OffsetBitWidth, 0);
301 uint64_t ScalarSizeInBytes = ScalarSize / 8;
302 if (
Offset.urem(ScalarSizeInBytes) != 0)
306 APInt OffsetEltIndexAP =
Offset.udiv(ScalarSizeInBytes);
307 if (OffsetEltIndexAP.
uge(MinVecNumElts))
325 unsigned AS =
Load->getPointerAddressSpace();
344 unsigned OutputNumElts = Ty->getNumElements();
346 assert(OffsetEltIndex < MinVecNumElts &&
"Address offset too big");
347 Mask[0] = OffsetEltIndex;
354 if (OldCost < NewCost || !NewCost.
isValid())
365 replaceValue(
I, *VecLd);
373bool VectorCombine::widenSubvectorLoad(Instruction &
I) {
376 if (!Shuf->isIdentityWithPadding())
382 unsigned OpIndex =
any_of(Shuf->getShuffleMask(), [&NumOpElts](
int M) {
383 return M >= (int)(NumOpElts);
403 unsigned AS =
Load->getPointerAddressSpace();
418 if (OldCost < NewCost || !NewCost.
isValid())
425 replaceValue(
I, *VecLd);
432ExtractElementInst *VectorCombine::getShuffleExtract(
433 ExtractElementInst *Ext0, ExtractElementInst *Ext1,
437 assert(Index0C && Index1C &&
"Expected constant extract indexes");
439 unsigned Index0 = Index0C->getZExtValue();
440 unsigned Index1 = Index1C->getZExtValue();
443 if (Index0 == Index1)
467 if (PreferredExtractIndex == Index0)
469 if (PreferredExtractIndex == Index1)
473 return Index0 > Index1 ? Ext0 : Ext1;
481bool VectorCombine::isExtractExtractCheap(ExtractElementInst *Ext0,
482 ExtractElementInst *Ext1,
483 const Instruction &
I,
484 ExtractElementInst *&ConvertToShuffle,
485 unsigned PreferredExtractIndex) {
488 assert(Ext0IndexC && Ext1IndexC &&
"Expected constant extract indexes");
490 unsigned Opcode =
I.getOpcode();
503 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
504 "Expected a compare");
514 unsigned Ext0Index = Ext0IndexC->getZExtValue();
515 unsigned Ext1Index = Ext1IndexC->getZExtValue();
529 unsigned BestExtIndex = Extract0Cost > Extract1Cost ? Ext0Index : Ext1Index;
530 unsigned BestInsIndex = Extract0Cost > Extract1Cost ? Ext1Index : Ext0Index;
531 InstructionCost CheapExtractCost = std::min(Extract0Cost, Extract1Cost);
536 if (Ext0Src == Ext1Src && Ext0Index == Ext1Index) {
541 bool HasUseTax = Ext0 == Ext1 ? !Ext0->
hasNUses(2)
543 OldCost = CheapExtractCost + ScalarOpCost;
544 NewCost = VectorOpCost + CheapExtractCost + HasUseTax * CheapExtractCost;
548 OldCost = Extract0Cost + Extract1Cost + ScalarOpCost;
549 NewCost = VectorOpCost + CheapExtractCost +
554 ConvertToShuffle = getShuffleExtract(Ext0, Ext1, PreferredExtractIndex);
555 if (ConvertToShuffle) {
567 SmallVector<int> ShuffleMask(FixedVecTy->getNumElements(),
569 ShuffleMask[BestInsIndex] = BestExtIndex;
571 VecTy, VecTy,
CostKind, ShuffleMask, 0,
572 nullptr, {ConvertToShuffle});
575 VecTy, VecTy,
CostKind, {}, 0,
nullptr,
580 LLVM_DEBUG(
dbgs() <<
"Found a binop of extractions: " <<
I <<
"\n OldCost: "
581 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
586 return OldCost < NewCost;
598 ShufMask[NewIndex] = OldIndex;
599 return Builder.CreateShuffleVector(Vec, ShufMask,
"shift");
651 V1,
"foldExtExtBinop");
656 VecBOInst->copyIRFlags(&
I);
662bool VectorCombine::foldExtractExtract(Instruction &
I) {
678 V0->getType() !=
V1->getType())
683 unsigned NumElts = FixedVecTy->getNumElements();
684 if (C0 >= NumElts || C1 >= NumElts)
700 ExtractElementInst *ExtractToChange;
701 if (isExtractExtractCheap(Ext0, Ext1,
I, ExtractToChange, InsertIndex))
707 if (ExtractToChange) {
708 unsigned CheapExtractIdx = ExtractToChange == Ext0 ? C1 : C0;
713 if (ExtractToChange == Ext0)
722 ? foldExtExtCmp(ExtOp0, ExtOp1, ExtIndex,
I)
723 : foldExtExtBinop(ExtOp0, ExtOp1, ExtIndex,
I);
726 replaceValue(
I, *NewExt);
732bool VectorCombine::foldInsExtFNeg(Instruction &
I) {
750 auto *DstVecScalarTy = DstVecTy->getScalarType();
752 if (!SrcVecTy || DstVecScalarTy != SrcVecTy->getScalarType())
757 unsigned NumDstElts = DstVecTy->getNumElements();
758 unsigned NumSrcElts = SrcVecTy->getNumElements();
759 if (ExtIdx > NumSrcElts || InsIdx >= NumDstElts || NumDstElts == 1)
765 SmallVector<int>
Mask(NumDstElts);
766 std::iota(
Mask.begin(),
Mask.end(), 0);
767 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
783 bool NeedLenChg = SrcVecTy->getNumElements() != NumDstElts;
786 SmallVector<int> SrcMask;
789 SrcMask[ExtIdx % NumDstElts] = ExtIdx;
791 DstVecTy, SrcVecTy,
CostKind, SrcMask);
795 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
797 if (NewCost > OldCost)
800 Value *NewShuf, *LenChgShuf =
nullptr;
814 replaceValue(
I, *NewShuf);
820bool VectorCombine::foldInsExtBinop(Instruction &
I) {
821 BinaryOperator *VecBinOp, *SclBinOp;
853 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
855 if (NewCost > OldCost)
866 NewInst->copyIRFlags(VecBinOp);
867 NewInst->andIRFlags(SclBinOp);
872 replaceValue(
I, *NewBO);
878bool VectorCombine::foldBitOpOfCastops(Instruction &
I) {
881 if (!BinOp || !BinOp->isBitwiseLogicOp())
887 if (!LHSCast || !RHSCast) {
888 LLVM_DEBUG(
dbgs() <<
" One or both operands are not cast instructions\n");
894 if (CastOpcode != RHSCast->getOpcode())
898 switch (CastOpcode) {
899 case Instruction::BitCast:
900 case Instruction::Trunc:
901 case Instruction::SExt:
902 case Instruction::ZExt:
908 Value *LHSSrc = LHSCast->getOperand(0);
909 Value *RHSSrc = RHSCast->getOperand(0);
915 auto *SrcTy = LHSSrc->
getType();
916 auto *DstTy =
I.getType();
919 if (CastOpcode != Instruction::BitCast &&
924 if (!SrcTy->getScalarType()->isIntegerTy() ||
925 !DstTy->getScalarType()->isIntegerTy())
940 LHSCastCost + RHSCastCost;
951 if (!LHSCast->hasOneUse())
952 NewCost += LHSCastCost;
953 if (!RHSCast->hasOneUse())
954 NewCost += RHSCastCost;
957 <<
" NewCost=" << NewCost <<
"\n");
959 if (NewCost > OldCost)
964 BinOp->getName() +
".inner");
966 NewBinOp->copyIRFlags(BinOp);
980 replaceValue(
I, *Result);
989bool VectorCombine::foldBitOpOfCastConstant(Instruction &
I) {
1005 switch (CastOpcode) {
1006 case Instruction::BitCast:
1007 case Instruction::ZExt:
1008 case Instruction::SExt:
1009 case Instruction::Trunc:
1015 Value *LHSSrc = LHSCast->getOperand(0);
1017 auto *SrcTy = LHSSrc->
getType();
1018 auto *DstTy =
I.getType();
1021 if (CastOpcode != Instruction::BitCast &&
1026 if (!SrcTy->getScalarType()->isIntegerTy() ||
1027 !DstTy->getScalarType()->isIntegerTy())
1031 PreservedCastFlags RHSFlags;
1056 if (!LHSCast->hasOneUse())
1057 NewCost += LHSCastCost;
1059 LLVM_DEBUG(
dbgs() <<
"foldBitOpOfCastConstant: OldCost=" << OldCost
1060 <<
" NewCost=" << NewCost <<
"\n");
1062 if (NewCost > OldCost)
1067 LHSSrc, InvC,
I.getName() +
".inner");
1069 NewBinOp->copyIRFlags(&
I);
1089 replaceValue(
I, *Result);
1096bool VectorCombine::foldBitcastShuffle(Instruction &
I) {
1110 if (!DestTy || !SrcTy)
1113 unsigned DestEltSize = DestTy->getScalarSizeInBits();
1114 unsigned SrcEltSize = SrcTy->getScalarSizeInBits();
1115 if (SrcTy->getPrimitiveSizeInBits() % DestEltSize != 0)
1125 if (!(BCTy0 && BCTy0->getElementType() == DestTy->getElementType()) &&
1126 !(BCTy1 && BCTy1->getElementType() == DestTy->getElementType()))
1130 SmallVector<int, 16> NewMask;
1131 if (DestEltSize <= SrcEltSize) {
1134 if (SrcEltSize % DestEltSize != 0)
1136 unsigned ScaleFactor = SrcEltSize / DestEltSize;
1141 if (DestEltSize % SrcEltSize != 0)
1143 unsigned ScaleFactor = DestEltSize / SrcEltSize;
1150 unsigned NumSrcElts = SrcTy->getPrimitiveSizeInBits() / DestEltSize;
1151 auto *NewShuffleTy =
1153 auto *OldShuffleTy =
1155 unsigned NumOps = IsUnary ? 1 : 2;
1165 TargetTransformInfo::CastContextHint::None,
1170 TargetTransformInfo::CastContextHint::None,
1173 LLVM_DEBUG(
dbgs() <<
"Found a bitcasted shuffle: " <<
I <<
"\n OldCost: "
1174 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
1176 if (NewCost > OldCost || !NewCost.
isValid())
1184 replaceValue(
I, *Shuf);
1191bool VectorCombine::scalarizeOpOrCmp(Instruction &
I) {
1196 if (!UO && !BO && !CI && !
II)
1204 if (Arg->getType() !=
II->getType() &&
1214 for (User *U :
I.users())
1221 std::optional<uint64_t>
Index;
1223 auto Ops =
II ?
II->args() :
I.operands();
1232 if (OpTy->getElementCount().getKnownMinValue() <= InsIdx)
1238 else if (InsIdx != *Index)
1255 if (!
Index.has_value())
1259 Type *ScalarTy = VecTy->getScalarType();
1260 assert(VecTy->isVectorTy() &&
1263 "Unexpected types for insert element into binop or cmp");
1265 unsigned Opcode =
I.getOpcode();
1273 }
else if (UO || BO) {
1277 IntrinsicCostAttributes ScalarICA(
1278 II->getIntrinsicID(), ScalarTy,
1281 IntrinsicCostAttributes VectorICA(
1282 II->getIntrinsicID(), VecTy,
1289 Value *NewVecC =
nullptr;
1291 NewVecC =
simplifyCmpInst(CI->getPredicate(), VecCs[0], VecCs[1], SQ);
1294 simplifyUnOp(UO->getOpcode(), VecCs[0], UO->getFastMathFlags(), SQ);
1296 NewVecC =
simplifyBinOp(BO->getOpcode(), VecCs[0], VecCs[1], SQ);
1310 for (
auto [Idx,
Op, VecC, Scalar] :
enumerate(
Ops, VecCs, ScalarOps)) {
1312 II->getIntrinsicID(), Idx, &
TTI)))
1315 Instruction::InsertElement, VecTy,
CostKind, *Index, VecC, Scalar);
1316 OldCost += InsertCost;
1317 NewCost += !
Op->hasOneUse() * InsertCost;
1321 if (OldCost < NewCost || !NewCost.
isValid())
1331 ++NumScalarIntrinsic;
1334 for (
auto [OpIdx, Scalar, VecC] :
enumerate(ScalarOps, VecCs))
1346 ScalarOps[1], FPMO->getFastMathFlags(),
1347 CI->getName() +
".scalar");
1350 ScalarOps[1], CI->getName() +
".scalar");
1354 UO->getName() +
".scalar");
1356 if (OverflowingBinaryOperator *OBO =
1359 BO->getOpcode(), ScalarOps[0], ScalarOps[1], OBO->hasNoUnsignedWrap(),
1360 OBO->hasNoSignedWrap(), BO->getName() +
".scalar");
1363 BO->getName() +
".scalar", PDI->isDisjoint());
1364 }
else if (PossiblyExactOperator *PEO =
1368 PEO->isExact(), BO->getName() +
".scalar");
1371 ScalarOps[1], FPMO->getFastMathFlags(),
1372 BO->getName() +
".scalar");
1375 BO->getName() +
".scalar");
1380 FMF = FPMO->getFastMathFlags();
1382 FMF,
II->getName() +
".scalar");
1386 replaceValue(
I, *Insert);
1393bool VectorCombine::foldExtractedCmps(Instruction &
I) {
1398 if (!BI || !
I.getType()->isIntegerTy(1))
1403 Value *
B0 =
I.getOperand(0), *
B1 =
I.getOperand(1);
1406 CmpPredicate
P0,
P1;
1425 ExtractElementInst *ConvertToShuf = getShuffleExtract(Ext0, Ext1,
CostKind);
1428 assert((ConvertToShuf == Ext0 || ConvertToShuf == Ext1) &&
1429 "Unknown ExtractElementInst");
1434 unsigned CmpOpcode =
1440 if (Index0 >= VecTy->getNumElements() || Index1 >= VecTy->getNumElements())
1452 Ext0Cost + Ext1Cost + CmpCost * 2 +
1458 int CheapIndex = ConvertToShuf == Ext0 ? Index1 : Index0;
1459 int ExpensiveIndex = ConvertToShuf == Ext0 ? Index0 : Index1;
1464 ShufMask[CheapIndex] = ExpensiveIndex;
1469 NewCost += Ext0->
hasOneUse() ? 0 : Ext0Cost;
1470 NewCost += Ext1->
hasOneUse() ? 0 : Ext1Cost;
1475 if (OldCost < NewCost || !NewCost.
isValid())
1485 Value *
LHS = ConvertToShuf == Ext0 ? Shuf : VCmp;
1486 Value *
RHS = ConvertToShuf == Ext0 ? VCmp : Shuf;
1489 replaceValue(
I, *NewExt);
1516bool VectorCombine::foldSelectsFromBitcast(Instruction &
I) {
1523 if (!SrcVecTy || !DstVecTy)
1533 if (SrcEltBits != 32 && SrcEltBits != 64)
1536 if (!DstEltTy->
isIntegerTy() || DstEltBits >= SrcEltBits)
1553 if (!ScalarSelCost.
isValid() || ScalarSelCost == 0)
1556 unsigned MinSelects = (VecSelCost.
getValue() / ScalarSelCost.
getValue()) + 1;
1559 if (!BC->hasNUsesOrMore(MinSelects))
1564 DenseMap<Value *, SmallVector<SelectInst *, 8>> CondToSelects;
1566 for (User *U : BC->users()) {
1571 for (User *ExtUser : Ext->users()) {
1575 Cond->getType()->isIntegerTy(1))
1580 if (CondToSelects.
empty())
1583 bool MadeChange =
false;
1584 Value *SrcVec = BC->getOperand(0);
1587 for (
auto [
Cond, Selects] : CondToSelects) {
1589 if (Selects.size() < MinSelects) {
1590 LLVM_DEBUG(
dbgs() <<
"VectorCombine: foldSelectsFromBitcast not "
1591 <<
"profitable (VecCost=" << VecSelCost
1592 <<
", ScalarCost=" << ScalarSelCost
1593 <<
", NumSelects=" << Selects.size() <<
")\n");
1598 auto InsertPt = std::next(BC->getIterator());
1602 InsertPt = std::next(CondInst->getIterator());
1610 for (SelectInst *Sel : Selects) {
1612 Value *Idx = Ext->getIndexOperand();
1616 replaceValue(*Sel, *NewExt);
1621 <<
" selects into vector select\n");
1635 unsigned ReductionOpc =
1641 CostBeforeReduction =
1642 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, ExtType,
1644 CostAfterReduction =
1645 TTI.getExtendedReductionCost(ReductionOpc, IsUnsigned,
II.getType(),
1649 if (RedOp &&
II.getIntrinsicID() == Intrinsic::vector_reduce_add &&
1655 (Op0->
getOpcode() == RedOp->getOpcode() || Op0 == Op1)) {
1662 TTI.getCastInstrCost(Op0->
getOpcode(), MulType, ExtType,
1665 TTI.getArithmeticInstrCost(Instruction::Mul, MulType,
CostKind);
1667 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, MulType,
1670 CostBeforeReduction = ExtCost * 2 + MulCost + Ext2Cost;
1671 CostAfterReduction =
TTI.getMulAccReductionCost(
1672 IsUnsigned, ReductionOpc,
II.getType(), ExtType,
CostKind);
1675 CostAfterReduction =
TTI.getArithmeticReductionCost(ReductionOpc, VecRedTy,
1679bool VectorCombine::foldBinopOfReductions(Instruction &
I) {
1682 if (BinOpOpc == Instruction::Sub)
1683 ReductionIID = Intrinsic::vector_reduce_add;
1687 if (ReductionIID == Intrinsic::vector_reduce_fadd ||
1688 ReductionIID == Intrinsic::vector_reduce_fmul)
1691 auto checkIntrinsicAndGetItsArgument = [](
Value *
V,
1696 if (
II->getIntrinsicID() == IID &&
II->hasOneUse())
1697 return II->getArgOperand(0);
1701 Value *
V0 = checkIntrinsicAndGetItsArgument(
I.getOperand(0), ReductionIID);
1704 Value *
V1 = checkIntrinsicAndGetItsArgument(
I.getOperand(1), ReductionIID);
1709 if (
V1->getType() != VTy)
1713 unsigned ReductionOpc =
1726 CostOfRedOperand0 + CostOfRedOperand1 +
1729 if (NewCost >= OldCost || !NewCost.
isValid())
1733 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
1736 if (BinOpOpc == Instruction::Or)
1743 replaceValue(
I, *Rdx);
1752 unsigned NumScanned = 0;
1753 if (std::any_of(Begin, End, [&](
const Instruction &Instr) {
1767class ScalarizationResult {
1768 enum class StatusTy { Unsafe, Safe, SafeWithFreeze };
1773 ScalarizationResult(StatusTy Status,
Value *ToFreeze =
nullptr)
1774 : Status(Status), ToFreeze(ToFreeze) {}
1777 ScalarizationResult(
const ScalarizationResult &
Other) =
default;
1778 ~ScalarizationResult() {
1779 assert(!ToFreeze &&
"freeze() not called with ToFreeze being set");
1782 static ScalarizationResult unsafe() {
return {StatusTy::Unsafe}; }
1783 static ScalarizationResult safe() {
return {StatusTy::Safe}; }
1784 static ScalarizationResult safeWithFreeze(
Value *ToFreeze) {
1785 return {StatusTy::SafeWithFreeze, ToFreeze};
1789 bool isSafe()
const {
return Status == StatusTy::Safe; }
1791 bool isUnsafe()
const {
return Status == StatusTy::Unsafe; }
1794 bool isSafeWithFreeze()
const {
return Status == StatusTy::SafeWithFreeze; }
1799 Status = StatusTy::Unsafe;
1803 void freeze(IRBuilderBase &Builder, Instruction &UserI) {
1804 assert(isSafeWithFreeze() &&
1805 "should only be used when freezing is required");
1807 "UserI must be a user of ToFreeze");
1808 IRBuilder<>::InsertPointGuard Guard(Builder);
1813 if (
U.get() == ToFreeze)
1828 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1832 if (
C->getValue().ult(NumElements))
1833 return ScalarizationResult::safe();
1834 return ScalarizationResult::unsafe();
1839 return ScalarizationResult::unsafe();
1841 APInt Zero(IntWidth, 0);
1842 APInt MaxElts(IntWidth, NumElements);
1849 return ScalarizationResult::safe();
1850 return ScalarizationResult::unsafe();
1863 if (ValidIndices.
contains(IdxRange))
1864 return ScalarizationResult::safeWithFreeze(IdxBase);
1865 return ScalarizationResult::unsafe();
1885 unsigned GEPBits = GEPIndexTy->getBitWidth();
1886 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1888 uint64_t MaxLane = NumElements - 1;
1890 if (
C->getValue().uge(NumElements))
1892 MaxLane =
C->getZExtValue();
1896 if (!
DL.typeSizeEqualsStoreSize(
ElemTy))
1916 unsigned WideBits = std::max(GEPBits, 128u);
1917 APInt MaxLaneValue(WideBits, MaxLane);
1918 APInt ByteOffset = MaxLaneValue;
1923 if (ByteOffset.
ugt(MaxGEPOffset))
1936 if (SrcBits >= DstBits)
1939 return Builder.CreateZExt(Idx, GEPIndexTy, Idx->
getName() +
".gepidx");
1951 C->getZExtValue() *
DL.getTypeStoreSize(ScalarType));
1988bool VectorCombine::foldInsertElementsToStores(Instruction &
I) {
2003 if (!
Insert->hasOneUse())
2007 InsertElements.
push_back({InsertVal, Idx});
2011 if (InsertElements.
empty())
2016 std::reverse(InsertElements.
begin(), InsertElements.
end());
2025 if (InsertElements.
size() == FVT->getNumElements()) {
2026 Value *FirstVal = InsertElements.
front().first;
2027 if (
all_of(InsertElements,
2028 [FirstVal](
const auto &Elt) {
return Elt.first == FirstVal; }))
2032 Value *SrcAddr =
Load->getPointerOperand()->stripPointerCasts();
2037 if (!
Load->isSimple() ||
Load->getParent() !=
SI->getParent() ||
2038 !
DL->typeSizeEqualsStoreSize(
Load->getType()->getScalarType()) ||
2039 SrcAddr !=
SI->getPointerOperand()->stripPointerCasts())
2049 for (
auto [InsertVal, Idx] : InsertElements) {
2050 auto ScalarizableIdx =
2052 if (ScalarizableIdx.isUnsafe())
2058 ScalarizableIdx.discard();
2064 ScalarizableIdx.discard();
2068 Instruction::Store,
SI->getValueOperand()->getType(),
SI->getAlign(),
2071 if (
Load->hasOneUse())
2076 for (
auto [InsertVal, Idx] : InsertElements) {
2079 Index = CIdx->getZExtValue();
2090 for (
auto [InsertVal, Idx] : InsertElements) {
2093 const Value *GEPIndices[] = {ConstantInt::get(Idx->
getType(), 0), Idx};
2098 for (
auto [InsertVal, Idx] : InsertElements) {
2100 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2108 LLVM_DEBUG(
dbgs() <<
"Found an insert-elements vector store scalarization "
2111 <<
" NumInserts: " << InsertElements.size() <<
"\n"
2112 <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2115 if (OldCost <= NewCost)
2118 for (
auto [InsertVal, Idx] : InsertElements) {
2119 auto ScalarizableIdx =
2121 assert(!ScalarizableIdx.isUnsafe() &&
"already checked above");
2123 if (ScalarizableIdx.isSafeWithFreeze())
2128 StoreInst *LastStore =
nullptr;
2129 for (
auto [InsertVal, Idx] : InsertElements) {
2130 auto ScalarizableIdx =
2132 if (ScalarizableIdx.isUnsafe())
2135 IntegerType *GEPIndexTy =
2140 SI->getValueOperand()->getType(),
SI->getPointerOperand(),
2141 {ConstantInt::get(GEPIdx->getType(), 0), GEPIdx});
2148 LastStore->
setMetadata(LLVMContext::MD_invariant_group,
nullptr);
2150 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2155 replaceValue(
I, *LastStore);
2162bool VectorCombine::scalarizeLoad(Instruction &
I) {
2172 if (!LI->isSimple() || !
DL->typeSizeEqualsStoreSize(VecTy->getScalarType()))
2175 bool AllExtracts =
true;
2176 bool AllBitcasts =
true;
2178 unsigned NumInstChecked = 0;
2183 for (User *U : LI->users()) {
2185 if (!UI || UI->getParent() != LI->getParent())
2190 if (UI->use_empty())
2194 AllExtracts =
false;
2196 AllBitcasts =
false;
2200 for (Instruction &
I :
2201 make_range(std::next(LI->getIterator()), UI->getIterator())) {
2208 LastCheckedInst = UI;
2213 return scalarizeLoadExtract(LI, VecTy, Ptr);
2215 return scalarizeLoadBitcast(LI, VecTy, Ptr);
2220bool VectorCombine::scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
2225 DenseMap<ExtractElementInst *, ScalarizationResult> NeedFreeze;
2226 DenseMap<ExtractElementInst *, IntegerType *> GEPIndexInfos;
2229 for (
auto &Pair : NeedFreeze)
2230 Pair.second.discard();
2238 for (User *U : LI->
users()) {
2243 if (ScalarIdx.isUnsafe())
2249 ScalarIdx.discard();
2255 if (ScalarIdx.isSafeWithFreeze()) {
2256 NeedFreeze.try_emplace(UI, ScalarIdx);
2257 ScalarIdx.discard();
2263 Index ?
Index->getZExtValue() : -1);
2269 if (!Index && UI->getIndexOperand()->getType()->getIntegerBitWidth() <
2272 Instruction::ZExt, GEPIndex, UI->getIndexOperand()->getType(),
2276 LLVM_DEBUG(
dbgs() <<
"Found all extractions of a vector load: " << *LI
2277 <<
"\n LoadExtractCost: " << OriginalCost
2278 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2280 if (ScalarizedCost > OriginalCost)
2282 if (ScalarizedCost == OriginalCost && !LI->
hasOneUse())
2289 Type *ElemType = VecTy->getElementType();
2292 for (User *U : LI->
users()) {
2294 Value *Idx = EI->getIndexOperand();
2297 if (
auto It = NeedFreeze.find(EI); It != NeedFreeze.end())
2301 auto It = GEPIndexInfos.
find(EI);
2303 "Missing scalarized GEP index information");
2306 VecTy, Ptr, {ConstantInt::get(GEPIdx->
getType(), 0), GEPIdx});
2308 Builder.
CreateLoad(ElemType,
GEP, EI->getName() +
".scalar"));
2310 Align ScalarOpAlignment =
2312 NewLoad->setAlignment(ScalarOpAlignment);
2315 size_t Offset = ConstIdx->getZExtValue() *
DL->getTypeStoreSize(ElemType);
2320 replaceValue(*EI, *NewLoad,
false);
2323 FailureGuard.release();
2328bool VectorCombine::scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
2337 Type *TargetScalarType =
nullptr;
2338 unsigned VecBitWidth =
DL->getTypeSizeInBits(VecTy);
2340 for (User *U : LI->
users()) {
2343 Type *DestTy = BC->getDestTy();
2347 unsigned DestBitWidth =
DL->getTypeSizeInBits(DestTy);
2348 if (DestBitWidth != VecBitWidth)
2352 if (!TargetScalarType)
2353 TargetScalarType = DestTy;
2354 else if (TargetScalarType != DestTy)
2362 if (!TargetScalarType)
2370 LLVM_DEBUG(
dbgs() <<
"Found vector load feeding only bitcasts: " << *LI
2371 <<
"\n OriginalCost: " << OriginalCost
2372 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2374 if (ScalarizedCost >= OriginalCost)
2385 ScalarLoad->copyMetadata(*LI);
2388 for (User *U : LI->
users()) {
2390 replaceValue(*BC, *ScalarLoad,
false);
2396bool VectorCombine::scalarizeExtExtract(Instruction &
I) {
2411 Type *ScalarDstTy = DstTy->getElementType();
2412 if (
DL->getTypeSizeInBits(SrcTy) !=
DL->getTypeSizeInBits(ScalarDstTy))
2418 unsigned ExtCnt = 0;
2419 bool ExtLane0 =
false;
2420 for (User *U : Ext->users()) {
2426 if (Idx >= SrcTy->getNumElements())
2438 Instruction::And, ScalarDstTy,
CostKind,
2441 (ExtCnt - ExtLane0) *
2443 Instruction::LShr, ScalarDstTy,
CostKind,
2446 if (ScalarCost > VectorCost)
2449 Value *ScalarV = Ext->getOperand(0);
2456 SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
2457 bool AllExtractsTriggerUB =
true;
2458 ExtractElementInst *LastExtract =
nullptr;
2460 for (User *U : Ext->users()) {
2463 AllExtractsTriggerUB =
false;
2467 if (!LastExtract || LastExtract->
comesBefore(Extract))
2468 LastExtract = Extract;
2470 if (ExtractedLanes.
size() != DstTy->getNumElements() ||
2471 !AllExtractsTriggerUB ||
2479 uint64_t SrcEltSizeInBits =
DL->getTypeSizeInBits(SrcTy->getElementType());
2480 uint64_t TotalBits =
DL->getTypeSizeInBits(SrcTy);
2483 Value *
Mask = ConstantInt::get(PackedTy, EltBitMask);
2484 for (User *U : Ext->users()) {
2490 ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits)
2491 : (Idx * SrcEltSizeInBits);
2494 U->replaceAllUsesWith(
And);
2502bool VectorCombine::foldConcatOfBoolMasks(Instruction &
I) {
2503 Type *Ty =
I.getType();
2508 if (
DL->isBigEndian())
2535 if (ShAmtX > ShAmtY) {
2543 uint64_t ShAmtDiff = ShAmtY - ShAmtX;
2544 unsigned NumSHL = (ShAmtX > 0) + (ShAmtY > 0);
2549 MaskTy->getNumElements() != ShAmtDiff ||
2550 MaskTy->getNumElements() > (
BitWidth / 2))
2555 Type::getIntNTy(Ty->
getContext(), ConcatTy->getNumElements());
2556 auto *MaskIntTy = Type::getIntNTy(Ty->
getContext(), ShAmtDiff);
2559 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2576 if (Ty != ConcatIntTy)
2582 LLVM_DEBUG(
dbgs() <<
"Found a concatenation of bitcasted bool masks: " <<
I
2583 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2586 if (NewCost > OldCost)
2596 if (Ty != ConcatIntTy) {
2606 replaceValue(
I, *Result);
2612bool VectorCombine::foldPermuteOfBinops(Instruction &
I) {
2613 BinaryOperator *BinOp;
2614 ArrayRef<int> OuterMask;
2622 Value *Op00, *Op01, *Op10, *Op11;
2623 ArrayRef<int> Mask0, Mask1;
2628 if (!Match0 && !Match1)
2641 if (!ShuffleDstTy || !BinOpTy || !Op0Ty || !Op1Ty)
2644 unsigned NumSrcElts = BinOpTy->getNumElements();
2649 any_of(OuterMask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
2653 SmallVector<int> NewMask0, NewMask1;
2654 for (
int M : OuterMask) {
2655 if (M < 0 || M >= (
int)NumSrcElts) {
2659 NewMask0.
push_back(Match0 ? Mask0[M] : M);
2660 NewMask1.
push_back(Match1 ? Mask1[M] : M);
2664 unsigned NumOpElts = Op0Ty->getNumElements();
2665 bool IsIdentity0 = ShuffleDstTy == Op0Ty &&
2666 all_of(NewMask0, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2668 bool IsIdentity1 = ShuffleDstTy == Op1Ty &&
2669 all_of(NewMask1, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2678 ShuffleDstTy, BinOpTy,
CostKind, OuterMask,
2679 0,
nullptr, {BinOp}, &
I);
2681 NewCost += BinOpCost;
2687 OldCost += Shuf0Cost;
2689 NewCost += Shuf0Cost;
2695 OldCost += Shuf1Cost;
2697 NewCost += Shuf1Cost;
2705 Op0Ty,
CostKind, NewMask0, 0,
nullptr, {Op00, Op01});
2709 Op1Ty,
CostKind, NewMask1, 0,
nullptr, {Op10, Op11});
2711 LLVM_DEBUG(
dbgs() <<
"Found a shuffle feeding a shuffled binop: " <<
I
2712 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2716 if (NewCost > OldCost)
2727 NewInst->copyIRFlags(BinOp);
2731 replaceValue(
I, *NewBO);
2737bool VectorCombine::foldShuffleOfBinops(Instruction &
I) {
2738 ArrayRef<int> OldMask;
2745 if (
LHS->getOpcode() !=
RHS->getOpcode())
2749 bool IsCommutative =
false;
2758 IsCommutative = BinaryOperator::isCommutative(BO->getOpcode());
2769 if (!ShuffleDstTy || !BinResTy || !BinOpTy ||
X->getType() !=
Z->getType())
2772 bool SameBinOp =
LHS ==
RHS;
2773 unsigned NumSrcElts = BinOpTy->getNumElements();
2776 if (IsCommutative &&
X != Z &&
Y != W && (
X == W ||
Y == Z))
2779 auto ConvertToUnary = [NumSrcElts](
int &
M) {
2780 if (M >= (
int)NumSrcElts)
2784 SmallVector<int> NewMask0(OldMask);
2793 SmallVector<int> NewMask1(OldMask);
2812 ShuffleDstTy, BinResTy,
CostKind, OldMask, 0,
2822 ArrayRef<int> InnerMask;
2824 m_Mask(InnerMask)))) &&
2827 [NumSrcElts](
int M) {
return M < (int)NumSrcElts; })) {
2839 bool ReducedInstCount =
false;
2840 ReducedInstCount |= MergeInner(
X, 0, NewMask0,
CostKind);
2841 ReducedInstCount |= MergeInner(
Y, 0, NewMask1,
CostKind);
2842 ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0,
CostKind);
2843 ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1,
CostKind);
2844 bool SingleSrcBinOp = (
X ==
Y) && (Z == W) && (NewMask0 == NewMask1);
2856 I.getType()->getScalarType()->isIntegerTy(1) &&
2860 auto *ShuffleCmpTy =
2863 SK0, ShuffleCmpTy, BinOpTy,
CostKind, NewMask0, 0,
nullptr, {
X,
Z});
2864 if (!SingleSrcBinOp)
2866 NewMask1, 0,
nullptr, {
Y,
W});
2874 PredLHS,
CostKind, Op0Info, Op1Info);
2884 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2891 if (ReducedInstCount ? (NewCost > OldCost) : (NewCost >= OldCost))
2900 : Builder.
CreateCmp(PredLHS, Shuf0, Shuf1);
2904 NewInst->copyIRFlags(
LHS);
2905 NewInst->andIRFlags(
RHS);
2910 replaceValue(
I, *NewBO);
2917bool VectorCombine::foldShuffleOfSelects(Instruction &
I) {
2919 Value *C1, *
T1, *F1, *C2, *T2, *F2;
2930 if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2936 if (((SI0FOp ==
nullptr) != (SI1FOp ==
nullptr)) ||
2937 ((SI0FOp !=
nullptr) &&
2938 (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())))
2944 auto SelOp = Instruction::Select;
2952 CostSel1 + CostSel2 +
2954 {
I.getOperand(0),
I.getOperand(1)}, &
I);
2958 CostKind, Mask, 0,
nullptr, {C1, C2});
2968 if (!Sel1->hasOneUse())
2969 NewCost += CostSel1;
2970 if (!Sel2->hasOneUse())
2971 NewCost += CostSel2;
2974 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2976 if (NewCost > OldCost)
2985 NewSel = Builder.
CreateSelectFMF(ShuffleCmp, ShuffleTrue, ShuffleFalse,
2986 SI0FOp->getFastMathFlags());
2988 NewSel = Builder.
CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
2993 replaceValue(
I, *NewSel);
2999bool VectorCombine::foldShuffleOfCastops(Instruction &
I) {
3001 ArrayRef<int> OldMask;
3010 if (!C0 || (IsBinaryShuffle && !C1))
3017 if (!IsBinaryShuffle && Opcode == Instruction::BitCast)
3020 if (IsBinaryShuffle) {
3021 if (C0->getSrcTy() != C1->getSrcTy())
3024 if (Opcode != C1->getOpcode()) {
3026 Opcode = Instruction::SExt;
3035 if (!ShuffleDstTy || !CastDstTy || !CastSrcTy)
3038 unsigned NumSrcElts = CastSrcTy->getNumElements();
3039 unsigned NumDstElts = CastDstTy->getNumElements();
3040 assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) &&
3041 "Only bitcasts expected to alter src/dst element counts");
3045 if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 &&
3046 (NumDstElts % NumSrcElts) != 0)
3049 SmallVector<int, 16> NewMask;
3050 if (NumSrcElts >= NumDstElts) {
3053 assert(NumSrcElts % NumDstElts == 0 &&
"Unexpected shuffle mask");
3054 unsigned ScaleFactor = NumSrcElts / NumDstElts;
3059 assert(NumDstElts % NumSrcElts == 0 &&
"Unexpected shuffle mask");
3060 unsigned ScaleFactor = NumDstElts / NumSrcElts;
3065 auto *NewShuffleDstTy =
3074 if (IsBinaryShuffle)
3081 OldMask, 0,
nullptr, {}, &
I);
3089 if (IsBinaryShuffle) {
3099 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3101 if (NewCost > OldCost)
3105 if (IsBinaryShuffle)
3115 NewInst->copyIRFlags(C0);
3116 if (IsBinaryShuffle)
3117 NewInst->andIRFlags(C1);
3121 replaceValue(
I, *Cast);
3131bool VectorCombine::foldShuffleOfShuffles(Instruction &
I) {
3132 ArrayRef<int> OuterMask;
3133 Value *OuterV0, *OuterV1;
3138 ArrayRef<int> InnerMask0, InnerMask1;
3139 Value *X0, *X1, *Y0, *Y1;
3144 if (!Match0 && !Match1)
3149 SmallVector<int, 16> PoisonMask1;
3154 InnerMask1 = PoisonMask1;
3158 X0 = Match0 ? X0 : OuterV0;
3159 Y0 = Match0 ? Y0 : OuterV0;
3160 X1 = Match1 ? X1 : OuterV1;
3161 Y1 = Match1 ? Y1 : OuterV1;
3165 if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy ||
3169 unsigned NumSrcElts = ShuffleSrcTy->getNumElements();
3170 unsigned NumImmElts = ShuffleImmTy->getNumElements();
3175 SmallVector<int, 16> NewMask(OuterMask);
3176 Value *NewX =
nullptr, *NewY =
nullptr;
3177 for (
int &M : NewMask) {
3178 Value *Src =
nullptr;
3179 if (0 <= M && M < (
int)NumImmElts) {
3183 Src =
M >= (int)NumSrcElts ? Y0 : X0;
3184 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3186 }
else if (M >= (
int)NumImmElts) {
3191 Src =
M >= (int)NumSrcElts ? Y1 : X1;
3192 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3196 assert(0 <= M && M < (
int)NumSrcElts &&
"Unexpected shuffle mask index");
3205 if (!NewX || NewX == Src) {
3209 if (!NewY || NewY == Src) {
3228 replaceValue(
I, *NewX);
3245 bool IsUnary =
all_of(NewMask, [&](
int M) {
return M < (int)NumSrcElts; });
3251 nullptr, {NewX, NewY});
3253 NewCost += InnerCost0;
3255 NewCost += InnerCost1;
3258 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3260 if (NewCost > OldCost)
3264 replaceValue(
I, *Shuf);
3280bool VectorCombine::foldShufflesOfLengthChangingShuffles(Instruction &
I) {
3285 unsigned ChainLength = 0;
3286 SmallVector<int>
Mask;
3287 SmallVector<int> YMask;
3297 ArrayRef<int> OuterMask;
3298 Value *OuterV0, *OuterV1;
3299 if (ChainLength != 0 && !Trunk->
hasOneUse())
3302 m_Mask(OuterMask))))
3304 if (OuterV0->
getType() != TrunkType) {
3310 ArrayRef<int> InnerMask0, InnerMask1;
3316 bool Match0Leaf = Match0 && A0->
getType() !=
I.getType();
3317 bool Match1Leaf = Match1 && A1->
getType() !=
I.getType();
3318 if (Match0Leaf == Match1Leaf) {
3324 SmallVector<int> CommutedOuterMask;
3331 for (
int &M : CommutedOuterMask) {
3334 if (M < (
int)NumTrunkElts)
3339 OuterMask = CommutedOuterMask;
3358 int NumLeafElts = YType->getNumElements();
3359 SmallVector<int> LocalYMask(InnerMask1);
3360 for (
int &M : LocalYMask) {
3361 if (M >= NumLeafElts)
3371 Mask.assign(OuterMask);
3372 YMask.
assign(LocalYMask);
3373 OldCost = NewCost = LocalOldCost;
3380 SmallVector<int> NewYMask(YMask);
3382 for (
auto [CombinedM, LeafM] :
llvm::zip(NewYMask, LocalYMask)) {
3383 if (LeafM == -1 || CombinedM == LeafM)
3385 if (CombinedM == -1) {
3395 SmallVector<int> NewMask;
3396 NewMask.
reserve(NumTrunkElts);
3397 for (
int M : Mask) {
3398 if (M < 0 || M >=
static_cast<int>(NumTrunkElts))
3413 if (LocalNewCost >= NewCost && LocalOldCost < LocalNewCost - NewCost)
3417 if (ChainLength == 1) {
3418 dbgs() <<
"Found chain of shuffles fed by length-changing shuffles: "
3421 dbgs() <<
" next chain link: " << *Trunk <<
'\n'
3422 <<
" old cost: " << (OldCost + LocalOldCost)
3423 <<
" new cost: " << LocalNewCost <<
'\n';
3428 OldCost += LocalOldCost;
3429 NewCost = LocalNewCost;
3433 if (ChainLength <= 1)
3441 return M < 0 || M >=
static_cast<int>(NumTrunkElts);
3444 for (
int &M : Mask) {
3445 if (M >=
static_cast<int>(NumTrunkElts))
3446 M = YMask[
M - NumTrunkElts];
3450 replaceValue(
I, *Root);
3457 replaceValue(
I, *Root);
3463bool VectorCombine::foldShuffleOfIntrinsics(Instruction &
I) {
3465 ArrayRef<int> OldMask;
3475 if (IID != II1->getIntrinsicID())
3484 if (!ShuffleDstTy || !II0Ty)
3490 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3491 Value *Arg0 = II0->getArgOperand(Idx);
3492 Value *Arg1 = II1->getArgOperand(Idx);
3509 II0Ty,
CostKind, OldMask, 0,
nullptr, {II0, II1}, &
I);
3513 SmallDenseSet<std::pair<Value *, Value *>> SeenOperandPairs;
3514 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3516 NewArgsTy.
push_back(II0->getArgOperand(Idx)->getType());
3520 ShuffleDstTy->getNumElements());
3522 std::pair<Value *, Value *> OperandPair =
3523 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3524 if (!SeenOperandPairs.
insert(OperandPair).second) {
3530 OldMask, 0,
nullptr,
3531 {II0->getArgOperand(Idx), II1->getArgOperand(Idx)});
3534 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3537 if (!II0->hasOneUse())
3539 if (II1 != II0 && !II1->hasOneUse())
3543 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3546 if (NewCost > OldCost)
3550 SmallDenseMap<std::pair<Value *, Value *>,
Value *> ShuffleCache;
3551 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3553 NewArgs.
push_back(II0->getArgOperand(Idx));
3555 std::pair<Value *, Value *> OperandPair =
3556 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3557 auto It = ShuffleCache.
find(OperandPair);
3558 if (It != ShuffleCache.
end()) {
3564 II0->getArgOperand(Idx), II1->getArgOperand(Idx), OldMask);
3565 ShuffleCache[OperandPair] = Shuf;
3574 NewInst->copyIRFlags(II0);
3575 NewInst->andIRFlags(II1);
3578 replaceValue(
I, *NewIntrinsic);
3584bool VectorCombine::foldPermuteOfIntrinsic(Instruction &
I) {
3596 if (!ShuffleDstTy || !IntrinsicSrcTy)
3600 unsigned NumSrcElts = IntrinsicSrcTy->getNumElements();
3601 if (
any_of(Mask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
3614 IntrinsicSrcTy,
CostKind, Mask, 0,
nullptr, {
V0}, &
I);
3618 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3620 NewArgsTy.
push_back(II0->getArgOperand(
I)->getType());
3624 ShuffleDstTy->getNumElements());
3627 ArgTy, VecTy,
CostKind, Mask, 0,
nullptr,
3628 {II0->getArgOperand(
I)});
3631 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3636 if (!II0->hasOneUse())
3639 LLVM_DEBUG(
dbgs() <<
"Found a permute of intrinsic: " <<
I <<
"\n OldCost: "
3640 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
3642 if (NewCost > OldCost)
3647 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3660 NewInst->copyIRFlags(II0);
3662 replaceValue(
I, *NewIntrinsic);
3672 int M = SV->getMaskValue(Lane);
3675 if (
static_cast<unsigned>(M) < NumElts) {
3676 V = SV->getOperand(0);
3679 V = SV->getOperand(1);
3690 auto [U, Lane] = IL;
3703 unsigned NumElts = Ty->getNumElements();
3704 if (Item.
size() == NumElts || NumElts == 1 || Item.
size() % NumElts != 0)
3710 std::iota(ConcatMask.
begin(), ConcatMask.
end(), 0);
3716 unsigned NumSlices = Item.
size() / NumElts;
3721 for (
unsigned Slice = 0; Slice < NumSlices; ++Slice) {
3722 Value *SliceV = Item[Slice * NumElts].first;
3723 if (!SliceV || SliceV->
getType() != Ty)
3725 for (
unsigned Elt = 0; Elt < NumElts; ++Elt) {
3726 auto [V, Lane] = Item[Slice * NumElts + Elt];
3727 if (Lane !=
static_cast<int>(Elt) || SliceV != V)
3736 const DenseSet<std::pair<Value *, Use *>> &IdentityLeafs,
3737 const DenseSet<std::pair<Value *, Use *>> &SplatLeafs,
3738 const DenseSet<std::pair<Value *, Use *>> &ConcatLeafs,
3741 auto [FrontV, FrontLane] = Item.
front();
3743 if (IdentityLeafs.contains(std::make_pair(FrontV, From))) {
3746 if (SplatLeafs.contains(std::make_pair(FrontV, From))) {
3748 return Builder.CreateShuffleVector(FrontV, Mask);
3750 if (ConcatLeafs.contains(std::make_pair(FrontV, From))) {
3754 for (
unsigned S = 0; S <
Values.size(); ++S)
3755 Values[S] = Item[S * NumElts].first;
3757 while (
Values.size() > 1) {
3760 std::iota(Mask.begin(), Mask.end(), 0);
3762 for (
unsigned S = 0; S < NewValues.
size(); ++S)
3764 Builder.CreateShuffleVector(
Values[S * 2],
Values[S * 2 + 1], Mask);
3778 if (BCDstTy && BCSrcTy &&
3779 BCDstTy->getElementCount() != BCSrcTy->getElementCount()) {
3780 unsigned DstElts = BCDstTy->getNumElements();
3781 unsigned SrcElts = BCSrcTy->getNumElements();
3783 if (DstElts > SrcElts) {
3785 unsigned R = DstElts / SrcElts;
3786 if (Item.
size() % R != 0)
3788 for (
unsigned Idx = 0,
E = Item.
size(); Idx <
E; Idx += R) {
3789 auto [V, Lane] = Item[Idx];
3799 unsigned R = SrcElts / DstElts;
3800 for (
auto [V, Lane] : Item) {
3806 for (
unsigned J = 0; J < R; ++J)
3811 IdentityLeafs, SplatLeafs, ConcatLeafs,
3812 Builder, WorkList,
TTI);
3814 return Builder.CreateBitCast(
3819 unsigned NumOps =
I->getNumOperands() - (
II ? 1 : 0);
3821 for (
unsigned Idx = 0; Idx <
NumOps; Idx++) {
3824 Ops[Idx] =
II->getOperand(Idx);
3829 IdentityLeafs, SplatLeafs, ConcatLeafs, Builder, WorkList,
TTI);
3839 for (
const auto &Lane : Item)
3852 auto *
Value = Builder.CreateCmp(CI->getPredicate(),
Ops[0],
Ops[1]);
3862 auto *
Value = Builder.CreateCast(CI->getOpcode(),
Ops[0], DstTy);
3867 auto *
Value = Builder.CreateIntrinsic(DstTy,
II->getIntrinsicID(),
Ops);
3881bool VectorCombine::foldShuffleToIdentity(Instruction &
I) {
3883 if (!Ty ||
I.use_empty())
3887 for (
unsigned M = 0,
E = Ty->getNumElements(); M <
E; ++M)
3891 Candidates.
push_back(std::make_pair(Start, &*
I.use_begin()));
3892 DenseSet<std::pair<Value *, Use *>> IdentityLeafs, SplatLeafs, ConcatLeafs;
3893 unsigned NumVisited = 0;
3894 bool TraversedElCountChangingBitcast =
false;
3896 while (!Candidates.
empty()) {
3901 auto Item = ItemFrom.first;
3902 auto From = ItemFrom.second;
3903 auto [FrontV, FrontLane] = Item.front();
3910 if (FrontLane == 0 &&
3914 Value *FrontV = Item.front().first;
3916 E.value().second == (int)
E.index());
3918 IdentityLeafs.
insert(std::make_pair(FrontV, From));
3923 C &&
C->getSplatValue() &&
3925 Value *FrontV = Item.front().first;
3931 SplatLeafs.
insert(std::make_pair(FrontV, From));
3936 auto [FrontV, FrontLane] = Item.front();
3937 auto [
V, Lane] = IL;
3938 return !
V || (
V == FrontV && Lane == FrontLane);
3940 SplatLeafs.
insert(std::make_pair(FrontV, From));
3946 auto CheckLaneIsEquivalentToFirst = [Item](
InstLane IL) {
3947 Value *FrontV = Item.front().first;
3956 if (CI->getPredicate() !=
cast<CmpInst>(FrontV)->getPredicate())
3959 if (CI->getSrcTy()->getScalarType() !=
3964 SI->getOperand(0)->getType() !=
3971 II->getIntrinsicID() ==
3973 !
II->hasOperandBundles());
3980 BO && BO->isIntDivRem())
3987 }
else if (
isa<UnaryOperator, TruncInst, ZExtInst, SExtInst, FPToSIInst,
3988 FPToUIInst, SIToFPInst, UIToFPInst>(FrontV)) {
3995 if (BCDstTy && BCSrcTy) {
3996 ElementCount DstEC = BCDstTy->getElementCount();
3997 ElementCount SrcEC = BCSrcTy->getElementCount();
3998 if (DstEC == SrcEC) {
4001 &BitCast->getOperandUse(0));
4006 if (DstElts > SrcElts && DstElts % SrcElts == 0) {
4010 unsigned R = DstElts / SrcElts;
4012 bool Valid = Item.size() %
R == 0;
4013 for (
unsigned Idx = 0,
E = Item.size(); Valid && Idx <
E;
4015 auto [
V0, L0] = Item[Idx];
4018 [](
InstLane IL) {
return IL.first !=
nullptr; })) {
4029 for (
unsigned J = 1; J <
R; ++J) {
4030 auto [VJ, LJ] = Item[Idx + J];
4031 if (!VJ || VJ != V0 || LJ != L0 + (
int)J) {
4042 TraversedElCountChangingBitcast =
true;
4043 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4046 }
else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
4049 unsigned R = SrcElts / DstElts;
4051 for (
auto [V, Lane] : Item) {
4057 for (
unsigned J = 0; J <
R; ++J)
4060 TraversedElCountChangingBitcast =
true;
4061 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4067 &Sel->getOperandUse(0));
4069 &Sel->getOperandUse(1));
4071 &Sel->getOperandUse(2));
4075 !
II->hasOperandBundles()) {
4076 for (
unsigned Op = 0,
E =
II->getNumOperands() - 1;
Op <
E;
Op++) {
4080 Value *FrontV = Item.front().first;
4097 ConcatLeafs.
insert(std::make_pair(FrontV, From));
4104 if (NumVisited <= 1)
4110 if (NumVisited == 2 && TraversedElCountChangingBitcast)
4113 LLVM_DEBUG(
dbgs() <<
"Found a superfluous identity shuffle: " <<
I <<
"\n");
4120 ConcatLeafs, Builder, Worklist, &
TTI);
4121 replaceValue(
I, *V);
4128bool VectorCombine::foldShuffleFromReductions(Instruction &
I) {
4132 switch (
II->getIntrinsicID()) {
4133 case Intrinsic::vector_reduce_add:
4134 case Intrinsic::vector_reduce_mul:
4135 case Intrinsic::vector_reduce_and:
4136 case Intrinsic::vector_reduce_or:
4137 case Intrinsic::vector_reduce_xor:
4138 case Intrinsic::vector_reduce_smin:
4139 case Intrinsic::vector_reduce_smax:
4140 case Intrinsic::vector_reduce_umin:
4141 case Intrinsic::vector_reduce_umax:
4150 std::queue<Value *> Worklist;
4151 SmallPtrSet<Value *, 4> Visited;
4152 ShuffleVectorInst *Shuffle =
nullptr;
4156 while (!Worklist.empty()) {
4157 Value *CV = Worklist.front();
4169 if (CI->isBinaryOp()) {
4170 for (
auto *
Op : CI->operand_values())
4174 if (Shuffle && Shuffle != SV)
4191 for (
auto *V : Visited)
4192 for (
auto *U :
V->users())
4193 if (!Visited.contains(U) && U != &
I)
4196 FixedVectorType *VecType =
4200 FixedVectorType *ShuffleInputType =
4202 if (!ShuffleInputType)
4208 SmallVector<int> ConcatMask;
4210 sort(ConcatMask, [](
int X,
int Y) {
return (
unsigned)
X < (unsigned)
Y; });
4211 bool UsesSecondVec =
4212 any_of(ConcatMask, [&](
int M) {
return M >= (int)NumInputElts; });
4219 ShuffleInputType,
CostKind, ConcatMask);
4221 LLVM_DEBUG(
dbgs() <<
"Found a reduction feeding from a shuffle: " << *Shuffle
4223 LLVM_DEBUG(
dbgs() <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
4225 bool MadeChanges =
false;
4226 if (NewCost < OldCost) {
4230 LLVM_DEBUG(
dbgs() <<
"Created new shuffle: " << *NewShuffle <<
"\n");
4231 replaceValue(*Shuffle, *NewShuffle);
4237 MadeChanges |= foldSelectShuffle(*Shuffle,
true);
4258bool VectorCombine::foldShuffleChainsToReduce(Instruction &
I) {
4267 if (FVT->getNumElements() < 2)
4270 std::optional<Instruction::BinaryOps> CommonBinOp;
4271 std::optional<Intrinsic::ID> CommonCallOp;
4276 CommonBinOp = BO->getOpcode();
4278 CommonCallOp = MMI->getIntrinsicID();
4284 FastMathFlags CommonFMF;
4285 bool IsFloatReduction =
false;
4289 auto IsChainNode = [&](
Value *
V) {
4291 return CommonBinOp && BO->getOpcode() == *CommonBinOp;
4293 return CommonCallOp && MMI->getIntrinsicID() == *CommonCallOp;
4301 constexpr unsigned MaxChainNodes = 32;
4302 SmallSetVector<Value *, 16> Nodes;
4303 SmallSetVector<Value *, 4> Sources;
4304 unsigned NumVisited = 0;
4305 auto AddSource = [&](
Value *
V) {
4311 auto Walk = [&](
Value *
V,
auto &&Walk) ->
bool {
4314 if (++NumVisited > MaxChainNodes)
4316 if (!IsChainNode(V))
4317 return AddSource(V);
4322 if (!Walk(
U->getOperand(
I), Walk))
4331 return AddSource(V);
4333 if (!Walk(VecOpEE, Walk) || Nodes.
empty())
4340 for (
Value *V : Nodes) {
4346 if (!IsFloatReduction) {
4348 IsFloatReduction =
true;
4362 DenseMap<Value *, Demand> Demands;
4363 auto DemandOf = [&](
Value *
V) -> Demand & {
4365 Demand &
D = Demands[
V];
4366 if (
D.Lanes.getBitWidth() !=
N)
4370 DemandOf(VecOpEE).Lanes.setBit(0);
4372 Demand DV = Demands.
lookup(V);
4373 if (DV.Lanes.isZero())
4376 ArrayRef<int>
Mask = SVI->getShuffleMask();
4377 Demand &
DS = DemandOf(SVI->getOperand(0));
4378 for (
unsigned I = 0,
E =
Mask.size();
I !=
E; ++
I) {
4380 if (!DV.Lanes[
I] || Mask[
I] < 0 ||
4381 (
unsigned)Mask[
I] >=
DS.Lanes.getBitWidth())
4383 if (
DS.Lanes[Mask[
I]] || DV.Duplicates[
I])
4384 DS.Duplicates.setBit(Mask[
I]);
4385 DS.Lanes.setBit(Mask[
I]);
4389 for (
Value *
Op : {
U->getOperand(0),
U->getOperand(1)}) {
4390 Demand &DOp = DemandOf(
Op);
4392 DOp.Duplicates |= DV.Duplicates | (DOp.Lanes & DV.Lanes);
4393 DOp.Lanes |= DV.Lanes;
4400 auto CoversChain = [&](
Value *
V) {
4401 SmallVector<Value *, 8> Worklist(1, VecOpEE);
4402 SmallPtrSet<Value *, 8> Seen;
4404 while (!Worklist.empty()) {
4407 for (
unsigned I = 0;
I !=
NumOps; ++
I) {
4411 if (!Nodes.contains(
Op))
4413 Worklist.push_back(
Op);
4421 struct ReductionCut {
4425 std::optional<ReductionCut> Cut;
4426 for (
Value *S : Sources) {
4427 auto It = Demands.
find(S);
4428 if (It == Demands.
end() || It->second.Lanes.isZero())
4430 if (!IsIdempotent && !It->second.Duplicates.isZero()) {
4435 Cut = ReductionCut{S, It->second.Lanes};
4442 if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
4446 Cut->Elts |= It->second.Lanes;
4449 for (
Value *V : Nodes) {
4452 auto It = Demands.
find(V);
4453 if (It == Demands.
end() || !It->second.Lanes.isAllOnes())
4455 if (!IsIdempotent && !It->second.Duplicates.isZero())
4457 if (!CoversChain(V))
4459 Cut = ReductionCut{
V, It->second.Lanes};
4464 if (!Cut || Cut->Elts.popcount() < 2)
4474 for (
Value *V : Nodes)
4478 bool IsPartialReduction = !Cut->Elts.isAllOnes();
4479 FixedVectorType *ReduceVecTy =
4484 SmallVector<int> ExtractMask;
4486 if (IsPartialReduction) {
4487 for (
unsigned I = 0,
E = Cut->Elts.getBitWidth();
I !=
E; ++
I)
4489 ExtractMask.push_back(
I);
4490 unsigned SubIdx = 0, SubLen;
4491 auto SK = Cut->Elts.isShiftedMask(SubIdx, SubLen)
4495 SubIdx, ReduceVecTy);
4498 IntrinsicCostAttributes ICA(
4499 ReducedOp, ReduceVecTy->getElementType(),
4503 IsFloatReduction ? CommonFMF : FastMathFlags());
4506 LLVM_DEBUG(
dbgs() <<
"Found reduction shuffle chain: " <<
I <<
"\n OldCost : "
4507 << OrigCost <<
" vs NewCost: " << NewCost <<
"\n");
4512 if (VecOpEE->
hasOneUse() ? (NewCost > OrigCost) : (NewCost >= OrigCost))
4515 Value *ReduceInput = Cut->Src;
4516 if (IsPartialReduction)
4519 Value *ReducedResult;
4520 if (IsFloatReduction) {
4522 *CommonBinOp, ReduceVecTy->getElementType(),
false,
4525 {Identity, ReduceInput}, CommonFMF);
4530 replaceValue(
I, *ReducedResult);
4539bool VectorCombine::foldCastFromReductions(Instruction &
I) {
4544 bool TruncOnly =
false;
4547 case Intrinsic::vector_reduce_add:
4548 case Intrinsic::vector_reduce_mul:
4551 case Intrinsic::vector_reduce_and:
4552 case Intrinsic::vector_reduce_or:
4553 case Intrinsic::vector_reduce_xor:
4560 Value *ReductionSrc =
I.getOperand(0);
4572 Type *ResultTy =
I.getType();
4575 ReductionOpc, ReductionSrcTy, std::nullopt,
CostKind);
4585 if (OldCost <= NewCost || !NewCost.
isValid())
4589 II->getIntrinsicID(), {Src});
4591 replaceValue(
I, *NewCast);
4619bool VectorCombine::foldSignBitReductionCmp(Instruction &
I) {
4621 IntrinsicInst *ReduceOp;
4622 const APInt *CmpVal;
4629 case Intrinsic::vector_reduce_or:
4630 case Intrinsic::vector_reduce_umax:
4631 case Intrinsic::vector_reduce_and:
4632 case Intrinsic::vector_reduce_umin:
4633 case Intrinsic::vector_reduce_add:
4644 unsigned BitWidth = VecTy->getScalarSizeInBits();
4648 unsigned NumElts = VecTy->getNumElements();
4657 case Intrinsic::vector_reduce_or:
4658 case Intrinsic::vector_reduce_umax:
4659 TreeOpcode = Instruction::Or;
4661 case Intrinsic::vector_reduce_and:
4662 case Intrinsic::vector_reduce_umin:
4663 TreeOpcode = Instruction::And;
4665 case Intrinsic::vector_reduce_add:
4666 TreeOpcode = Instruction::Add;
4674 SmallVector<Value *, 8> Worklist;
4675 SmallVector<Value *, 8> Sources;
4677 std::optional<bool> IsAShr;
4678 constexpr unsigned MaxSources = 8;
4683 while (!Worklist.
empty() && Worklist.
size() <= MaxSources &&
4684 Sources.
size() <= MaxSources) {
4693 bool ThisIsAShr = Shr->getOpcode() == Instruction::AShr;
4695 IsAShr = ThisIsAShr;
4696 else if (*IsAShr != ThisIsAShr)
4722 if (Sources.
empty() || Sources.
size() > MaxSources ||
4723 Worklist.
size() > MaxSources || !IsAShr)
4726 unsigned NumSources = Sources.
size();
4730 if (OrigIID == Intrinsic::vector_reduce_add &&
4738 (OrigIID == Intrinsic::vector_reduce_add) ? NumSources * NumElts : 1;
4741 NegativeVal.negate();
4773 TestsNegative =
false;
4774 }
else if (*CmpVal == NegativeVal) {
4775 TestsNegative =
true;
4779 IsEq = Pred == ICmpInst::ICMP_EQ;
4780 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeHigh) {
4782 TestsNegative = (RangeHigh == NegativeVal);
4783 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeHigh - 1) {
4785 TestsNegative = (RangeHigh == NegativeVal);
4786 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeLow) {
4788 TestsNegative = (RangeLow == NegativeVal);
4789 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeLow + 1) {
4791 TestsNegative = (RangeLow == NegativeVal);
4834 enum CheckKind :
unsigned {
4841 auto RequiresOr = [](CheckKind
C) ->
bool {
return C & 0b100; };
4843 auto IsNegativeCheck = [](CheckKind
C) ->
bool {
return C & 0b010; };
4845 auto Invert = [](CheckKind
C) {
return CheckKind(
C ^ 0b011); };
4849 case Intrinsic::vector_reduce_or:
4850 case Intrinsic::vector_reduce_umax:
4851 Base = TestsNegative ? AnyNeg : AllNonNeg;
4853 case Intrinsic::vector_reduce_and:
4854 case Intrinsic::vector_reduce_umin:
4855 Base = TestsNegative ? AllNeg : AnyNonNeg;
4857 case Intrinsic::vector_reduce_add:
4858 Base = TestsNegative ? AllNeg : AllNonNeg;
4873 return ArithCost <= MinMaxCost ? std::make_pair(Arith, ArithCost)
4874 : std::make_pair(MinMax, MinMaxCost);
4878 auto [NewIID, NewCost] = RequiresOr(
Check)
4879 ? PickCheaper(Intrinsic::vector_reduce_or,
4880 Intrinsic::vector_reduce_umax)
4881 : PickCheaper(
Intrinsic::vector_reduce_and,
4885 if (NumSources > 1) {
4886 unsigned CombineOpc =
4887 RequiresOr(
Check) ? Instruction::Or : Instruction::And;
4892 LLVM_DEBUG(
dbgs() <<
"Found sign-bit reduction cmp: " <<
I <<
"\n OldCost: "
4893 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4895 if (NewCost > OldCost)
4900 Type *ScalarTy = VecTy->getScalarType();
4903 if (NumSources == 1) {
4914 replaceValue(
I, *NewCmp);
4945bool VectorCombine::foldReductionZeroTest(Instruction &
I) {
4954 if (!
II || !
II->hasOneUse())
4957 auto ReduceID =
II->getIntrinsicID();
4958 if (ReduceID != Intrinsic::vector_reduce_or &&
4959 ReduceID != Intrinsic::vector_reduce_umax)
4962 Value *Vec =
II->getArgOperand(0);
4964 if (!VecTy || !VecTy->getElementType()->isIntegerTy())
4969 ? Intrinsic::vector_reduce_or
4984 LLVM_DEBUG(
dbgs() <<
"Found a reduction zero test: " <<
I <<
"\n OldCost: "
4985 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4987 if (!OldCost.
isValid() || !NewCost.
isValid() || NewCost > OldCost)
4993 replaceValue(
I, *NewReduce);
5018bool VectorCombine::foldICmpEqZeroVectorReduce(Instruction &
I) {
5029 switch (
II->getIntrinsicID()) {
5030 case Intrinsic::vector_reduce_add:
5031 case Intrinsic::vector_reduce_or:
5032 case Intrinsic::vector_reduce_umin:
5033 case Intrinsic::vector_reduce_umax:
5034 case Intrinsic::vector_reduce_smin:
5035 case Intrinsic::vector_reduce_smax:
5041 Value *InnerOp =
II->getArgOperand(0);
5084 switch (
II->getIntrinsicID()) {
5085 case Intrinsic::vector_reduce_add: {
5090 unsigned NumElems = XTy->getNumElements();
5096 if (LeadingZerosX <= LostBits || LeadingZerosFX <= LostBits)
5104 case Intrinsic::vector_reduce_smin:
5105 case Intrinsic::vector_reduce_smax:
5115 LLVM_DEBUG(
dbgs() <<
"Found a reduction to 0 comparison with removable op: "
5131 case Intrinsic::vector_reduce_add:
5132 case Intrinsic::vector_reduce_or:
5138 case Intrinsic::vector_reduce_umin:
5139 case Intrinsic::vector_reduce_umax:
5140 case Intrinsic::vector_reduce_smin:
5141 case Intrinsic::vector_reduce_smax:
5153 NewReduceCost + (InnerOp->
hasOneUse() ? 0 : ExtCost);
5155 LLVM_DEBUG(
dbgs() <<
"Found a removable extension before reduction: "
5156 << *InnerOp <<
"\n OldCost: " << OldCost
5157 <<
" vs NewCost: " << NewCost <<
"\n");
5163 if (NewCost > OldCost)
5172 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::getNullValue(Ty));
5173 replaceValue(
I, *NewCmp);
5204bool VectorCombine::foldEquivalentReductionCmp(Instruction &
I) {
5207 const APInt *CmpVal;
5212 if (!
II || !
II->hasOneUse())
5215 const auto IsValidOrUmaxCmp = [&]() {
5224 bool IsPositive = CmpVal->
isAllOnes() && Pred == ICmpInst::ICMP_SGT;
5226 bool IsNegative = (CmpVal->
isZero() || CmpVal->
isOne() || *CmpVal == 2) &&
5227 Pred == ICmpInst::ICMP_SLT;
5228 return IsEquality || IsPositive || IsNegative;
5231 const auto IsValidAndUminCmp = [&]() {
5236 const auto LeadingOnes = CmpVal->
countl_one();
5243 bool IsNegative = CmpVal->
isZero() && Pred == ICmpInst::ICMP_SLT;
5252 ((*CmpVal)[0] || (*CmpVal)[1]) && Pred == ICmpInst::ICMP_SGT;
5253 return IsEquality || IsNegative || IsPositive;
5261 switch (OriginalIID) {
5262 case Intrinsic::vector_reduce_or:
5263 if (!IsValidOrUmaxCmp())
5265 AlternativeIID = Intrinsic::vector_reduce_umax;
5267 case Intrinsic::vector_reduce_umax:
5268 if (!IsValidOrUmaxCmp())
5270 AlternativeIID = Intrinsic::vector_reduce_or;
5272 case Intrinsic::vector_reduce_and:
5273 if (!IsValidAndUminCmp())
5275 AlternativeIID = Intrinsic::vector_reduce_umin;
5277 case Intrinsic::vector_reduce_umin:
5278 if (!IsValidAndUminCmp())
5280 AlternativeIID = Intrinsic::vector_reduce_and;
5293 if (ReductionOpc != Instruction::ICmp)
5304 <<
"\n OrigCost: " << OrigCost
5305 <<
" vs AltCost: " << AltCost <<
"\n");
5307 if (AltCost >= OrigCost)
5311 Type *ScalarTy = VecTy->getScalarType();
5314 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::get(ScalarTy, *CmpVal));
5316 replaceValue(
I, *NewCmp);
5330 unsigned Depth = 0) {
5331 constexpr unsigned MaxLocalDepth = 2;
5332 if (
Depth > MaxLocalDepth)
5335 auto NumSignBits = [&](
const Value *
X) {
5338 if (NumSignBits(V) == V->getType()->getScalarSizeInBits())
5343 return NumSignBits(
A) >= 2 && NumSignBits(
B) >= 2 &&
5354bool VectorCombine::foldReduceAddCmpZero(Instruction &
I) {
5364 if (!VecTy || VecTy->getNumElements() < 2)
5370 if (!IsNonNegative && !IsNonPositive)
5375 unsigned NumElts = VecTy->getNumElements();
5377 if (
Log2_32(NumElts) >= NumSignBits)
5380 ICmpInst::Predicate NewPred;
5382 case ICmpInst::ICMP_EQ:
5383 case ICmpInst::ICMP_ULE:
5384 case ICmpInst::ICMP_SLE:
5385 case ICmpInst::ICMP_SGE:
5386 NewPred = ICmpInst::ICMP_EQ;
5388 case ICmpInst::ICMP_NE:
5389 case ICmpInst::ICMP_UGT:
5390 case ICmpInst::ICMP_SGT:
5391 case ICmpInst::ICMP_SLT:
5392 NewPred = ICmpInst::ICMP_NE;
5402 if (!IsNonNegative &&
5403 (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE))
5405 if (!IsNonPositive &&
5406 (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE))
5408 if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE ||
5409 Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) &&
5410 Log2_32(NumElts) >= NumSignBits - 1)
5414 Instruction::Add, VecTy, std::nullopt,
CostKind);
5416 Instruction::Or, VecTy, std::nullopt,
CostKind);
5418 Intrinsic::umax, VecTy, FastMathFlags(),
CostKind);
5421 bool UseOr = OrCost.
isValid() && (!UmaxCost.
isValid() || OrCost <= UmaxCost);
5423 if (AltCost > OrigCost)
5429 Intrinsic::vector_reduce_umax, {VecTy}, {Vec});
5430 Worklist.pushValue(NewReduce);
5432 NewPred, NewReduce, ConstantInt::getNullValue(VecTy->getScalarType()));
5433 replaceValue(
I, *NewCmp);
5442 constexpr unsigned MaxVisited = 32;
5445 bool FoundReduction =
false;
5448 while (!WorkList.
empty()) {
5450 for (
User *U :
I->users()) {
5452 if (!UI || !Visited.
insert(UI).second)
5454 if (Visited.
size() > MaxVisited)
5460 switch (
II->getIntrinsicID()) {
5461 case Intrinsic::vector_reduce_add:
5462 case Intrinsic::vector_reduce_mul:
5463 case Intrinsic::vector_reduce_and:
5464 case Intrinsic::vector_reduce_or:
5465 case Intrinsic::vector_reduce_xor:
5466 case Intrinsic::vector_reduce_smin:
5467 case Intrinsic::vector_reduce_smax:
5468 case Intrinsic::vector_reduce_umin:
5469 case Intrinsic::vector_reduce_umax:
5470 FoundReduction =
true;
5483 return FoundReduction;
5496bool VectorCombine::foldSelectShuffle(Instruction &
I,
bool FromReduction) {
5501 if (!Op0 || !Op1 || Op0 == Op1 || !Op0->isBinaryOp() || !Op1->isBinaryOp() ||
5502 VT != Op0->getType())
5509 SmallPtrSet<Instruction *, 4> InputShuffles({SVI0A, SVI0B, SVI1A, SVI1B});
5511 if (!
I ||
I->getOperand(0)->getType() != VT)
5513 return any_of(
I->users(), [&](User *U) {
5514 return U != Op0 && U != Op1 &&
5515 !(isa<ShuffleVectorInst>(U) &&
5516 (InputShuffles.contains(cast<Instruction>(U)) ||
5517 isInstructionTriviallyDead(cast<Instruction>(U))));
5520 if (checkSVNonOpUses(SVI0A) || checkSVNonOpUses(SVI0B) ||
5521 checkSVNonOpUses(SVI1A) || checkSVNonOpUses(SVI1B))
5529 for (
auto *U :
I->users()) {
5531 if (!SV ||
SV->getType() != VT)
5533 if ((
SV->getOperand(0) != Op0 &&
SV->getOperand(0) != Op1) ||
5534 (
SV->getOperand(1) != Op0 &&
SV->getOperand(1) != Op1))
5541 if (!collectShuffles(Op0) || !collectShuffles(Op1))
5545 if (FromReduction && Shuffles.
size() > 1)
5550 if (!FromReduction) {
5551 for (
size_t Idx = 0,
E = Shuffles.
size(); Idx !=
E; ++Idx) {
5552 for (
auto *U : Shuffles[Idx]->
users()) {
5567 int MaxV1Elt = 0, MaxV2Elt = 0;
5568 unsigned NumElts = VT->getNumElements();
5569 for (ShuffleVectorInst *SVN : Shuffles) {
5570 SmallVector<int>
Mask;
5571 SVN->getShuffleMask(Mask);
5575 Value *SVOp0 = SVN->getOperand(0);
5576 Value *SVOp1 = SVN->getOperand(1);
5581 for (
int &Elem : Mask) {
5587 if (SVOp0 == Op1 && SVOp1 == Op0) {
5591 if (SVOp0 != Op0 || SVOp1 != Op1)
5597 SmallVector<int> ReconstructMask;
5598 for (
unsigned I = 0;
I <
Mask.size();
I++) {
5601 }
else if (Mask[
I] <
static_cast<int>(NumElts)) {
5602 MaxV1Elt = std::max(MaxV1Elt, Mask[
I]);
5603 auto It =
find_if(
V1, [&](
const std::pair<int, int> &
A) {
5604 return Mask[
I] ==
A.first;
5610 V1.emplace_back(Mask[
I],
V1.size());
5613 MaxV2Elt = std::max<int>(MaxV2Elt, Mask[
I] - NumElts);
5614 auto It =
find_if(V2, [&](
const std::pair<int, int> &
A) {
5615 return Mask[
I] -
static_cast<int>(NumElts) ==
A.first;
5629 sort(ReconstructMask);
5630 OrigReconstructMasks.
push_back(std::move(ReconstructMask));
5637 if (
V1.empty() || V2.
empty() ||
5638 (MaxV1Elt ==
static_cast<int>(
V1.size()) - 1 &&
5639 MaxV2Elt ==
static_cast<int>(V2.
size()) - 1))
5651 if (InputShuffles.contains(SSV))
5653 return SV->getMaskValue(M);
5661 std::pair<int, int>
Y) {
5662 int MXA = GetBaseMaskValue(
A,
X.first);
5663 int MYA = GetBaseMaskValue(
A,
Y.first);
5667 return SortBase(SVI0A,
A,
B);
5669 stable_sort(V2, [&](std::pair<int, int>
A, std::pair<int, int>
B) {
5670 return SortBase(SVI1A,
A,
B);
5675 for (
const auto &Mask : OrigReconstructMasks) {
5676 SmallVector<int> ReconstructMask;
5677 for (
int M : Mask) {
5679 auto It =
find_if(V, [M](
auto A) {
return A.second ==
M; });
5680 assert(It !=
V.end() &&
"Expected all entries in Mask");
5681 return std::distance(
V.begin(), It);
5685 else if (M <
static_cast<int>(NumElts)) {
5688 ReconstructMask.
push_back(NumElts + FindIndex(V2, M));
5691 ReconstructMasks.
push_back(std::move(ReconstructMask));
5696 SmallVector<int> V1A, V1B, V2A, V2B;
5697 for (
unsigned I = 0;
I <
V1.size();
I++) {
5701 for (
unsigned I = 0;
I < V2.
size();
I++) {
5702 V2A.
push_back(GetBaseMaskValue(SVI1A, V2[
I].first));
5703 V2B.
push_back(GetBaseMaskValue(SVI1B, V2[
I].first));
5705 while (V1A.
size() < NumElts) {
5709 while (V2A.
size() < NumElts) {
5728 unsigned ElementSize = VT->getElementType()->getPrimitiveSizeInBits();
5729 unsigned MaxVectorSize =
5731 unsigned MaxElementsInVector = MaxVectorSize / ElementSize;
5732 if (MaxElementsInVector == 0)
5741 std::set<SmallVector<int, 4>> UniqueShuffles;
5746 unsigned NumFullVectors =
Mask.size() / MaxElementsInVector;
5747 if (NumFullVectors < 2)
5748 return C + ShuffleCost;
5749 SmallVector<int, 4> SubShuffle(MaxElementsInVector);
5750 unsigned NumUniqueGroups = 0;
5751 unsigned NumGroups =
Mask.size() / MaxElementsInVector;
5754 for (
unsigned I = 0;
I < NumFullVectors; ++
I) {
5755 for (
unsigned J = 0; J < MaxElementsInVector; ++J)
5756 SubShuffle[J] = Mask[MaxElementsInVector *
I + J];
5757 if (UniqueShuffles.insert(SubShuffle).second)
5758 NumUniqueGroups += 1;
5760 return C + ShuffleCost * NumUniqueGroups / NumGroups;
5766 SmallVector<int, 16>
Mask;
5767 SV->getShuffleMask(Mask);
5768 return AddShuffleMaskAdjustedCost(
C, Mask);
5771 auto AllShufflesHaveSameOperands =
5772 [](SmallPtrSetImpl<Instruction *> &InputShuffles) {
5773 if (InputShuffles.size() < 2)
5775 ShuffleVectorInst *FirstSV =
5782 std::next(InputShuffles.begin()), InputShuffles.end(),
5783 [&](Instruction *
I) {
5784 ShuffleVectorInst *SV = dyn_cast<ShuffleVectorInst>(I);
5785 return SV && SV->getOperand(0) == In0 && SV->getOperand(1) == In1;
5794 CostBefore += std::accumulate(Shuffles.begin(), Shuffles.end(),
5796 if (AllShufflesHaveSameOperands(InputShuffles)) {
5797 UniqueShuffles.clear();
5798 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5801 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5807 FixedVectorType *Op0SmallVT =
5809 FixedVectorType *Op1SmallVT =
5814 UniqueShuffles.clear();
5815 CostAfter += std::accumulate(ReconstructMasks.begin(), ReconstructMasks.end(),
5817 std::set<SmallVector<int>> OutputShuffleMasks({V1A, V1B, V2A, V2B});
5819 std::accumulate(OutputShuffleMasks.begin(), OutputShuffleMasks.end(),
5822 LLVM_DEBUG(
dbgs() <<
"Found a binop select shuffle pattern: " <<
I <<
"\n");
5824 <<
" vs CostAfter: " << CostAfter <<
"\n");
5825 if (CostBefore < CostAfter ||
5836 if (InputShuffles.contains(SSV))
5838 return SV->getOperand(
Op);
5842 GetShuffleOperand(SVI0A, 1), V1A);
5845 GetShuffleOperand(SVI0B, 1), V1B);
5848 GetShuffleOperand(SVI1A, 1), V2A);
5851 GetShuffleOperand(SVI1B, 1), V2B);
5856 I->copyIRFlags(Op0,
true);
5861 I->copyIRFlags(Op1,
true);
5863 for (
int S = 0,
E = ReconstructMasks.size(); S !=
E; S++) {
5866 replaceValue(*Shuffles[S], *NSV,
false);
5869 Worklist.pushValue(NSV0A);
5870 Worklist.pushValue(NSV0B);
5871 Worklist.pushValue(NSV1A);
5872 Worklist.pushValue(NSV1B);
5882bool VectorCombine::shrinkType(Instruction &
I) {
5883 Value *ZExted, *OtherOperand;
5889 Value *ZExtOperand =
I.getOperand(
I.getOperand(0) == OtherOperand ? 1 : 0);
5893 unsigned BW = SmallTy->getElementType()->getPrimitiveSizeInBits();
5895 if (
I.getOpcode() == Instruction::LShr) {
5912 Instruction::ZExt, BigTy, SmallTy,
5913 TargetTransformInfo::CastContextHint::None,
CostKind);
5918 for (User *U : ZExtOperand->
users()) {
5925 ShrinkCost += ZExtCost;
5940 ShrinkCost += ZExtCost;
5947 Instruction::Trunc, SmallTy, BigTy,
5948 TargetTransformInfo::CastContextHint::None,
CostKind);
5953 if (ShrinkCost > CurrentCost)
5957 Value *Op0 = ZExted;
5960 if (
I.getOperand(0) == OtherOperand)
5965 NewBinOpI->copyIRFlags(&
I);
5966 NewBinOpI->copyMetadata(
I);
5969 replaceValue(
I, *NewZExtr);
5975bool VectorCombine::foldInsExtVectorToShuffle(Instruction &
I) {
5976 Value *DstVec, *SrcVec;
5987 if (!DstVecTy || !SrcVecTy ||
5993 if (InsIdx >= NumDstElts || ExtIdx >= NumSrcElts || NumDstElts == 1)
6000 bool NeedExpOrNarrow = NumSrcElts != NumDstElts;
6002 if (NeedDstSrcSwap) {
6004 Mask[InsIdx] = ExtIdx % NumDstElts;
6008 std::iota(
Mask.begin(),
Mask.end(), 0);
6009 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
6022 SmallVector<int> ExtToVecMask;
6023 if (!NeedExpOrNarrow) {
6028 nullptr, {DstVec, SrcVec});
6034 ExtToVecMask[ExtIdx % NumDstElts] = ExtIdx;
6037 DstVecTy, SrcVecTy,
CostKind, ExtToVecMask);
6041 if (!Ext->hasOneUse())
6044 LLVM_DEBUG(
dbgs() <<
"Found a insert/extract shuffle-like pair: " <<
I
6045 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6048 if (OldCost < NewCost)
6051 if (NeedExpOrNarrow) {
6052 if (!NeedDstSrcSwap)
6065 replaceValue(
I, *Shuf);
6089bool VectorCombine::foldDeinterleaveInterleavePair(Instruction &
I) {
6106 if (
U.getUser()->isDroppable())
6110 if (!Extract || Extract->getNumIndices() != 1)
6113 unsigned Index = *Extract->idx_begin();
6114 if (Index >= Factor || CurrentUses[Index])
6122 IntrinsicInst *Interleave =
nullptr;
6123 unsigned NumVisited = 0;
6127 return CB->arg_size();
6128 return Inst->getNumOperands();
6131 auto IsSupportedElementwise = [&](
Instruction *Inst) {
6137 if (
II->hasOperandBundles() ||
6140 }
else if (!
isa<BinaryOperator, UnaryOperator, CastInst, CmpInst,
6141 SelectInst, FreezeInst>(Inst)) {
6147 for (
unsigned Op = 0,
E = GetNumDataOperands(Inst);
Op !=
E; ++
Op) {
6150 OperandTy->getElementCount() != ResultTy->getElementCount())
6162 NumVisited += Factor;
6164 for (Use *&CurrentUse : CurrentUses) {
6165 Use *NextUse = CurrentUse->getUser()->getSingleUndroppableUse();
6171 CurrentUse = NextUse;
6176 II &&
II->getIntrinsicID() == ExpectedInterleaveIID) {
6177 if (
II->hasOperandBundles())
6180 for (
unsigned Index = 0;
Index != Factor; ++
Index)
6181 if (CurrentUses[Index]->getUser() !=
II ||
6182 CurrentUses[Index]->getOperandNo() != Index)
6190 if (!IsSupportedElementwise(FirstInst))
6193 unsigned ChainOperand = CurrentUses.front()->getOperandNo();
6194 bool MismatchedUse =
any_of(CurrentUses, [&](Use *U) {
6196 return Inst != FirstInst && (
U->getOperandNo() != ChainOperand ||
6197 !FirstInst->isSameOperationAs(
6203 auto GetSplatOrScalar = [](
Value *
V) {
6210 for (
unsigned Op = 0,
E = GetNumDataOperands(FirstInst);
Op !=
E; ++
Op) {
6211 if (
Op == ChainOperand)
6214 Value *CommonValue = GetSplatOrScalar(FirstInst->getOperand(
Op));
6215 if (!CommonValue ||
any_of(CurrentUses, [&](Use *U) {
6217 return Inst != FirstInst &&
6231 ElementCount WideEC =
6234 auto CreateWideInstruction = [&](
Instruction *NarrowInst,
6237 assert(IsSupportedElementwise(NarrowInst) &&
6238 "Expected supported elementwise");
6242 return Builder.
CreateCast(Cast->getOpcode(), NewOperands[0],
6245 return Builder.
CreateCmp(
Cmp->getPredicate(), NewOperands[0],
6249 NewOperands[0], NewOperands[1], NewOperands[2],
"",
6261 for (
const ElementwiseStep &Step : Steps) {
6263 unsigned ChainOperand = Step.front()->getOperandNo();
6268 unsigned NumOperands = GetNumDataOperands(NarrowInst);
6269 SmallVector<Value *, 4> NewOperands;
6270 NewOperands.
reserve(NumOperands);
6272 for (
unsigned Op = 0;
Op != NumOperands; ++
Op) {
6275 if (
Op == ChainOperand)
6276 Operand = WideValue;
6282 auto *WideResultTy =
6285 CreateWideInstruction(NarrowInst, NewOperands, WideResultTy);
6294 WideValue = NewValue;
6298 replaceValue(*Interleave, *WideValue);
6306bool VectorCombine::foldInterleaveIntrinsics(Instruction &
I) {
6307 const APInt *SplatVal0, *SplatVal1;
6317 auto *ExtVTy = VectorType::getExtendedElementVectorType(VTy);
6318 unsigned Width = VTy->getElementType()->getIntegerBitWidth();
6327 LLVM_DEBUG(
dbgs() <<
"VC: The cost to cast from " << *ExtVTy <<
" to "
6328 << *
I.getType() <<
" is too high.\n");
6332 APInt NewSplatVal = SplatVal1->
zext(Width * 2);
6333 NewSplatVal <<= Width;
6334 NewSplatVal |= SplatVal0->
zext(Width * 2);
6336 ExtVTy->getElementCount(), ConstantInt::get(
F.getContext(), NewSplatVal));
6371bool VectorCombine::foldDeinterleaveIntrinsics(Instruction &
I) {
6372 if (foldDeinterleaveInterleavePair(
I))
6376 if (
DL->isBigEndian())
6379 using namespace PatternMatch;
6380 Value *DeinterleavedVal;
6391 unsigned HalfElementWidth = ElementWidth / 2;
6395 std::array<ExtractValueInst *, 2> OrigFields{};
6396 for (User *Usr :
I.users()) {
6399 if (!
E ||
E->getNumIndices() != 1)
6401 unsigned Idx = *
E->idx_begin();
6403 if (Idx >= 2 || OrigFields[Idx] || !
E->hasNUses(2))
6405 OrigFields[Idx] =
E;
6409 SmallVector<Instruction *, 2> MergeInsts;
6410 for (
auto *FieldUsr : OrigFields[0]->
users()) {
6418 auto MatchMerge = [&](void) ->
bool {
6421 return match(MergeInsts[0],
6425 match(MergeInsts[1],
6430 if (!MatchMerge()) {
6431 std::swap(MergeInsts[0], MergeInsts[1]);
6446 auto *NewFieldTy = VecTy->getWithNewBitWidth(HalfElementWidth);
6456 if (OldCost <= NewCost || !NewCost.
isValid()) {
6458 dbgs() <<
"VC: New deinterleave2 sequence cost (" << NewCost <<
")"
6459 <<
" is higher than that of the old one (" << OldCost <<
")\n");
6467 Intrinsic::vector_deinterleave2, {NewVecTy}, {NewVecCast});
6468 for (
auto [Idx, MergeInst] :
enumerate(MergeInsts)) {
6470 NewField = Builder.
CreateBitCast(NewField, MergeInst->getType());
6471 replaceValue(*MergeInst, *NewField);
6477bool VectorCombine::foldBitcastOfVPLoad(Instruction &
I) {
6478 const DataLayout &
DL =
I.getDataLayout();
6493 DL.getValueOrABITypeAlignment(
II->getPointerAlignment(), OrigVecTy);
6494 ElementCount OrigVecCnt = OrigVecTy->getElementCount();
6496 ElementCount NewVecCnt = NewVecTy->getElementCount();
6508 II->getMemoryPointerParam(),
false,
6514 {Intrinsic::vp_load, NewVecTy,
II->getMemoryPointerParam(),
false,
6518 <<
" NewCost=" << NewCost <<
"\n");
6519 if (NewCost > OldCost || !NewCost.
isValid())
6527 NewVecTy, Intrinsic::vp_load,
6528 {
II->getMemoryPointerParam(), NewMask, NewEVL});
6531 0, AttrBuilder(
II->getContext()).addAlignmentAttr(OrigAlign));
6532 replaceValue(*Cast, *NewVP);
6542bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &
I) {
6546 Type *Ty =
X->getType();
6547 Type *VecTy =
I.getOperand(0)->getType();
6561 if (CanUseBswap || CanUseFshl) {
6572 IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
6573 IntrinsicCostAttributes ICABFshl(Intrinsic::fshl, Ty, {
X,
X, HalfBW},
6575 IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
6580 if (!InnerCall->hasOneUse())
6583 else if (!InnerBitCast->hasOneUse())
6586 <<
"\n OldCost: " << OldCost
6587 <<
" vs NewCost: " << NewCost <<
"\n");
6588 if (NewCost.isValid() && NewCost < OldCost) {
6594 Worklist.pushValue(
Swap);
6596 replaceValue(
I, *BRev);
6605 Type *Ty =
I.getType();
6607 TypeSize ElementSize =
DL->getTypeStoreSize(Ty);
6610 Type *NewVecTy = VectorType::get(I8Ty, NewVecCnt);
6623 IntrinsicCostAttributes ICANew(Intrinsic::bitreverse, NewVecTy, {NewVecTy});
6626 InstructionCost NewCost = CastToVecCost + NewIntrinsicCost + CastToOrigCost;
6627 if (!InnerII->hasOneUse())
6630 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6632 if (!NewCost.
isValid() || NewCost >= OldCost)
6640 replaceValue(
I, *CastToOrig);
6650 unsigned RawNumElements = MaxIdx + 1u;
6654 return RawNumElements;
6658 return RawNumElements;
6663 return RawNumElements;
6668 if (ElemsPerReg == 0 || RawNumElements <= ElemsPerReg)
6669 return RawNumElements;
6671 return alignTo(RawNumElements, ElemsPerReg);
6675bool VectorCombine::shrinkLoadForShuffles(Instruction &
I) {
6677 if (!OldLoad || !OldLoad->isSimple())
6684 unsigned const OldNumElements = OldLoadTy->getNumElements();
6690 using IndexRange = std::pair<int, int>;
6691 auto GetIndexRangeInShuffles = [&]() -> std::optional<IndexRange> {
6692 IndexRange OutputRange = IndexRange(OldNumElements, -1);
6693 for (llvm::Use &Use :
I.uses()) {
6695 User *Shuffle =
Use.getUser();
6700 return std::nullopt;
6707 for (
int Index : Mask) {
6708 if (Index >= 0 && Index <
static_cast<int>(OldNumElements)) {
6709 OutputRange.first = std::min(Index, OutputRange.first);
6710 OutputRange.second = std::max(Index, OutputRange.second);
6715 if (OutputRange.second < OutputRange.first)
6716 return std::nullopt;
6722 if (std::optional<IndexRange> Indices = GetIndexRangeInShuffles()) {
6723 unsigned const NewNumElements =
6728 if (NewNumElements < OldNumElements) {
6733 Type *ElemTy = OldLoadTy->getElementType();
6735 Value *PtrOp = OldLoad->getPointerOperand();
6738 Instruction::Load, OldLoad->getType(), OldLoad->getAlign(),
6739 OldLoad->getPointerAddressSpace(),
CostKind);
6742 OldLoad->getPointerAddressSpace(),
CostKind);
6744 using UseEntry = std::pair<ShuffleVectorInst *, std::vector<int>>;
6746 unsigned const MaxIndex = NewNumElements * 2u;
6748 for (llvm::Use &Use :
I.uses()) {
6755 ArrayRef<int> OldMask = Shuffle->getShuffleMask();
6761 for (
int Index : OldMask) {
6762 if (Index >=
static_cast<int>(MaxIndex))
6776 dbgs() <<
"Found a load used only by shufflevector instructions: "
6777 <<
I <<
"\n OldCost: " << OldCost
6778 <<
" vs NewCost: " << NewCost <<
"\n");
6780 if (OldCost < NewCost || !NewCost.
isValid())
6786 NewLoad->copyMetadata(
I);
6789 for (UseEntry &Use : NewUses) {
6790 ShuffleVectorInst *Shuffle =
Use.first;
6791 std::vector<int> &NewMask =
Use.second;
6798 replaceValue(*Shuffle, *NewShuffle,
false);
6811bool VectorCombine::shrinkPhiOfShuffles(Instruction &
I) {
6813 if (!Phi ||
Phi->getNumIncomingValues() != 2u)
6817 ArrayRef<int> Mask0;
6818 ArrayRef<int> Mask1;
6831 auto const InputNumElements = InputVT->getNumElements();
6833 if (InputNumElements >= ResultVT->getNumElements())
6838 SmallVector<int, 16> NewMask;
6841 for (
auto [
M0,
M1] :
zip(Mask0, Mask1)) {
6842 if (
M0 >= 0 &&
M1 >= 0)
6844 else if (
M0 == -1 &&
M1 == -1)
6857 int MaskOffset = NewMask[0
u];
6858 unsigned Index = (InputNumElements + MaskOffset) % InputNumElements;
6861 for (
unsigned I = 0u;
I < InputNumElements; ++
I) {
6875 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6878 if (NewCost > OldCost)
6890 auto *NewPhi = Builder.
CreatePHI(NewShuf0->getType(), 2u);
6892 NewPhi->addIncoming(
Op,
Phi->getIncomingBlock(1u));
6898 replaceValue(*Phi, *NewShuf1);
6904bool VectorCombine::run() {
6918 auto Opcode =
I.getOpcode();
6926 if (IsFixedVectorType) {
6928 case Instruction::InsertElement:
6929 if (vectorizeLoadInsert(
I))
6932 case Instruction::ShuffleVector:
6933 if (widenSubvectorLoad(
I))
6944 if (scalarizeOpOrCmp(
I))
6946 if (scalarizeLoad(
I))
6948 if (scalarizeExtExtract(
I))
6950 if (foldInterleaveIntrinsics(
I))
6952 if (foldBitcastOfVPLoad(
I))
6956 if (foldDeinterleaveIntrinsics(
I))
6959 if (Opcode == Instruction::Store)
6960 if (foldInsertElementsToStores(
I))
6964 if (TryEarlyFoldsOnly)
6967 if (Opcode == Instruction::Call)
6968 if (foldBitOrderReverseAndSwap(
I))
6970 if (Opcode == Instruction::BitCast)
6971 if (foldBitOrderReverseAndSwap(
I))
6978 if (IsFixedVectorType) {
6980 case Instruction::InsertElement:
6981 if (foldInsExtFNeg(
I))
6983 if (foldInsExtBinop(
I))
6985 if (foldInsExtVectorToShuffle(
I))
6988 case Instruction::ShuffleVector:
6989 if (foldPermuteOfBinops(
I))
6991 if (foldShuffleOfBinops(
I))
6993 if (foldShuffleOfSelects(
I))
6995 if (foldShuffleOfCastops(
I))
6997 if (foldShuffleOfShuffles(
I))
6999 if (foldPermuteOfIntrinsic(
I))
7001 if (foldShufflesOfLengthChangingShuffles(
I))
7003 if (foldShuffleOfIntrinsics(
I))
7005 if (foldSelectShuffle(
I))
7007 if (foldShuffleToIdentity(
I))
7010 case Instruction::Load:
7011 if (shrinkLoadForShuffles(
I))
7014 case Instruction::BitCast:
7015 if (foldBitcastShuffle(
I))
7017 if (foldSelectsFromBitcast(
I))
7020 case Instruction::And:
7021 case Instruction::Or:
7022 case Instruction::Xor:
7023 if (foldBitOpOfCastops(
I))
7025 if (foldBitOpOfCastConstant(
I))
7028 case Instruction::PHI:
7029 if (shrinkPhiOfShuffles(
I))
7039 case Instruction::Call:
7040 if (foldShuffleFromReductions(
I))
7042 if (foldCastFromReductions(
I))
7045 case Instruction::ExtractElement:
7046 if (foldShuffleChainsToReduce(
I))
7049 case Instruction::ICmp:
7050 if (foldSignBitReductionCmp(
I))
7052 if (foldICmpEqZeroVectorReduce(
I))
7054 if (foldReductionZeroTest(
I))
7056 if (foldEquivalentReductionCmp(
I))
7058 if (foldReduceAddCmpZero(
I))
7061 case Instruction::FCmp:
7062 if (foldExtractExtract(
I))
7065 case Instruction::Or:
7066 if (foldConcatOfBoolMasks(
I))
7071 if (foldExtractExtract(
I))
7073 if (foldExtractedCmps(
I))
7075 if (foldBinopOfReductions(
I))
7084 bool MadeChange =
false;
7085 for (BasicBlock &BB :
F) {
7097 if (!
I->isDebugOrPseudoInst())
7098 MadeChange |= FoldInst(*
I);
7105 while (!Worklist.isEmpty()) {
7115 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
This file contains the declarations for profiling metadata utility functions.
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 Value * materializeScalarizedGEPIndex(Value *Idx, IntegerType *GEPIndexTy, IRBuilderBase &Builder)
Materialize an index for a scalarized GEP after profitability is known.
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 IntegerType * getScalarizedGEPIndexInfo(VectorType *VecTy, Value *Idx, Type *PtrTy, const DataLayout &DL)
Return the GEP index type if the unsigned vector index Idx can be represented by an inbounds GEP.
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 ugt(const APInt &RHS) const
Unsigned greater than comparison.
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.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
unsigned countl_one() const
Count the number of leading one bits.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
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.
InstListType::iterator iterator
Instruction iterators...
BinaryOps getOpcode() const
Represents analyses that only rely on functions' control flow.
Value * getArgOperand(unsigned i) const
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.
iterator find(const_arg_type_t< KeyT > Val)
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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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)
Value * CreateNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, bool IsNUW, bool IsNSW, const Twine &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="")
Value * CreateFCmpFMF(CmpInst::Predicate P, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
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 * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
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 * CreateUnOpFMF(Instruction::UnaryOps Opc, Value *V, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
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 * CreateExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, bool IsExact, const Twine &Name="")
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...
iterator_range< user_iterator > users()
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...
@ CompareCallTargets
Check for equivalence by comparing call targets.
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.
Class to represent integer types.
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
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*X will result in a value whose quantity matches our ...
constexpr ScalarTy getFixedValue() const
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS*X will result in a value whose quantity matches our own.
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.
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 Intrinsic::ID getInterleaveIntrinsicID(unsigned Factor)
Returns the corresponding llvm.vector.interleaveN intrinsic for factor N.
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.
AllOnesConstantMatch m_AllOnes()
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.
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)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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)
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
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).
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
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 void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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 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 Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal,...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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.
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 bool programUndefinedIfPoison(const Instruction *Inst)
LLVM_ABI unsigned getDeinterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.deinterleaveN intrinsics.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr int PoisonMaskElem
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 bool willNotFreeBetween(const Instruction *Assume, const Instruction *CtxI, const DominatorTree *DT=nullptr)
Returns true, if no instruction between Assume and CtxI may free (including through synchronization).
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.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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