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");
1382 replaceValue(
I, *Insert);
1389bool VectorCombine::foldExtractedCmps(Instruction &
I) {
1394 if (!BI || !
I.getType()->isIntegerTy(1))
1399 Value *
B0 =
I.getOperand(0), *
B1 =
I.getOperand(1);
1402 CmpPredicate
P0,
P1;
1421 ExtractElementInst *ConvertToShuf = getShuffleExtract(Ext0, Ext1,
CostKind);
1424 assert((ConvertToShuf == Ext0 || ConvertToShuf == Ext1) &&
1425 "Unknown ExtractElementInst");
1430 unsigned CmpOpcode =
1436 if (Index0 >= VecTy->getNumElements() || Index1 >= VecTy->getNumElements())
1448 Ext0Cost + Ext1Cost + CmpCost * 2 +
1454 int CheapIndex = ConvertToShuf == Ext0 ? Index1 : Index0;
1455 int ExpensiveIndex = ConvertToShuf == Ext0 ? Index0 : Index1;
1460 ShufMask[CheapIndex] = ExpensiveIndex;
1465 NewCost += Ext0->
hasOneUse() ? 0 : Ext0Cost;
1466 NewCost += Ext1->
hasOneUse() ? 0 : Ext1Cost;
1471 if (OldCost < NewCost || !NewCost.
isValid())
1481 Value *
LHS = ConvertToShuf == Ext0 ? Shuf : VCmp;
1482 Value *
RHS = ConvertToShuf == Ext0 ? VCmp : Shuf;
1485 replaceValue(
I, *NewExt);
1512bool VectorCombine::foldSelectsFromBitcast(Instruction &
I) {
1519 if (!SrcVecTy || !DstVecTy)
1529 if (SrcEltBits != 32 && SrcEltBits != 64)
1532 if (!DstEltTy->
isIntegerTy() || DstEltBits >= SrcEltBits)
1549 if (!ScalarSelCost.
isValid() || ScalarSelCost == 0)
1552 unsigned MinSelects = (VecSelCost.
getValue() / ScalarSelCost.
getValue()) + 1;
1555 if (!BC->hasNUsesOrMore(MinSelects))
1560 DenseMap<Value *, SmallVector<SelectInst *, 8>> CondToSelects;
1562 for (User *U : BC->users()) {
1567 for (User *ExtUser : Ext->users()) {
1571 Cond->getType()->isIntegerTy(1))
1576 if (CondToSelects.
empty())
1579 bool MadeChange =
false;
1580 Value *SrcVec = BC->getOperand(0);
1583 for (
auto [
Cond, Selects] : CondToSelects) {
1585 if (Selects.size() < MinSelects) {
1586 LLVM_DEBUG(
dbgs() <<
"VectorCombine: foldSelectsFromBitcast not "
1587 <<
"profitable (VecCost=" << VecSelCost
1588 <<
", ScalarCost=" << ScalarSelCost
1589 <<
", NumSelects=" << Selects.size() <<
")\n");
1594 auto InsertPt = std::next(BC->getIterator());
1598 InsertPt = std::next(CondInst->getIterator());
1606 for (SelectInst *Sel : Selects) {
1608 Value *Idx = Ext->getIndexOperand();
1612 replaceValue(*Sel, *NewExt);
1617 <<
" selects into vector select\n");
1631 unsigned ReductionOpc =
1637 CostBeforeReduction =
1638 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, ExtType,
1640 CostAfterReduction =
1641 TTI.getExtendedReductionCost(ReductionOpc, IsUnsigned,
II.getType(),
1645 if (RedOp &&
II.getIntrinsicID() == Intrinsic::vector_reduce_add &&
1651 (Op0->
getOpcode() == RedOp->getOpcode() || Op0 == Op1)) {
1658 TTI.getCastInstrCost(Op0->
getOpcode(), MulType, ExtType,
1661 TTI.getArithmeticInstrCost(Instruction::Mul, MulType,
CostKind);
1663 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, MulType,
1666 CostBeforeReduction = ExtCost * 2 + MulCost + Ext2Cost;
1667 CostAfterReduction =
TTI.getMulAccReductionCost(
1668 IsUnsigned, ReductionOpc,
II.getType(), ExtType,
CostKind);
1671 CostAfterReduction =
TTI.getArithmeticReductionCost(ReductionOpc, VecRedTy,
1675bool VectorCombine::foldBinopOfReductions(Instruction &
I) {
1678 if (BinOpOpc == Instruction::Sub)
1679 ReductionIID = Intrinsic::vector_reduce_add;
1683 if (ReductionIID == Intrinsic::vector_reduce_fadd ||
1684 ReductionIID == Intrinsic::vector_reduce_fmul)
1687 auto checkIntrinsicAndGetItsArgument = [](
Value *
V,
1692 if (
II->getIntrinsicID() == IID &&
II->hasOneUse())
1693 return II->getArgOperand(0);
1697 Value *
V0 = checkIntrinsicAndGetItsArgument(
I.getOperand(0), ReductionIID);
1700 Value *
V1 = checkIntrinsicAndGetItsArgument(
I.getOperand(1), ReductionIID);
1705 if (
V1->getType() != VTy)
1709 unsigned ReductionOpc =
1722 CostOfRedOperand0 + CostOfRedOperand1 +
1725 if (NewCost >= OldCost || !NewCost.
isValid())
1729 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
1732 if (BinOpOpc == Instruction::Or)
1739 replaceValue(
I, *Rdx);
1748 unsigned NumScanned = 0;
1749 if (std::any_of(Begin, End, [&](
const Instruction &Instr) {
1763class ScalarizationResult {
1764 enum class StatusTy { Unsafe, Safe, SafeWithFreeze };
1769 ScalarizationResult(StatusTy Status,
Value *ToFreeze =
nullptr)
1770 : Status(Status), ToFreeze(ToFreeze) {}
1773 ScalarizationResult(
const ScalarizationResult &
Other) =
default;
1774 ~ScalarizationResult() {
1775 assert(!ToFreeze &&
"freeze() not called with ToFreeze being set");
1778 static ScalarizationResult unsafe() {
return {StatusTy::Unsafe}; }
1779 static ScalarizationResult safe() {
return {StatusTy::Safe}; }
1780 static ScalarizationResult safeWithFreeze(
Value *ToFreeze) {
1781 return {StatusTy::SafeWithFreeze, ToFreeze};
1785 bool isSafe()
const {
return Status == StatusTy::Safe; }
1787 bool isUnsafe()
const {
return Status == StatusTy::Unsafe; }
1790 bool isSafeWithFreeze()
const {
return Status == StatusTy::SafeWithFreeze; }
1795 Status = StatusTy::Unsafe;
1799 void freeze(IRBuilderBase &Builder, Instruction &UserI) {
1800 assert(isSafeWithFreeze() &&
1801 "should only be used when freezing is required");
1803 "UserI must be a user of ToFreeze");
1804 IRBuilder<>::InsertPointGuard Guard(Builder);
1809 if (
U.get() == ToFreeze)
1824 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1828 if (
C->getValue().ult(NumElements))
1829 return ScalarizationResult::safe();
1830 return ScalarizationResult::unsafe();
1835 return ScalarizationResult::unsafe();
1837 APInt Zero(IntWidth, 0);
1838 APInt MaxElts(IntWidth, NumElements);
1845 return ScalarizationResult::safe();
1846 return ScalarizationResult::unsafe();
1859 if (ValidIndices.
contains(IdxRange))
1860 return ScalarizationResult::safeWithFreeze(IdxBase);
1861 return ScalarizationResult::unsafe();
1881 unsigned GEPBits = GEPIndexTy->getBitWidth();
1882 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1884 uint64_t MaxLane = NumElements - 1;
1886 if (
C->getValue().uge(NumElements))
1888 MaxLane =
C->getZExtValue();
1892 if (!
DL.typeSizeEqualsStoreSize(
ElemTy))
1912 unsigned WideBits = std::max(GEPBits, 128u);
1913 APInt MaxLaneValue(WideBits, MaxLane);
1914 APInt ByteOffset = MaxLaneValue;
1919 if (ByteOffset.
ugt(MaxGEPOffset))
1932 if (SrcBits >= DstBits)
1935 return Builder.CreateZExt(Idx, GEPIndexTy, Idx->
getName() +
".gepidx");
1947 C->getZExtValue() *
DL.getTypeStoreSize(ScalarType));
1984bool VectorCombine::foldInsertElementsToStores(Instruction &
I) {
1999 if (!
Insert->hasOneUse())
2003 InsertElements.
push_back({InsertVal, Idx});
2007 if (InsertElements.
empty())
2012 std::reverse(InsertElements.
begin(), InsertElements.
end());
2021 if (InsertElements.
size() == FVT->getNumElements()) {
2022 Value *FirstVal = InsertElements.
front().first;
2023 if (
all_of(InsertElements,
2024 [FirstVal](
const auto &Elt) {
return Elt.first == FirstVal; }))
2028 Value *SrcAddr =
Load->getPointerOperand()->stripPointerCasts();
2033 if (!
Load->isSimple() ||
Load->getParent() !=
SI->getParent() ||
2034 !
DL->typeSizeEqualsStoreSize(
Load->getType()->getScalarType()) ||
2035 SrcAddr !=
SI->getPointerOperand()->stripPointerCasts())
2045 for (
auto [InsertVal, Idx] : InsertElements) {
2046 auto ScalarizableIdx =
2048 if (ScalarizableIdx.isUnsafe())
2054 ScalarizableIdx.discard();
2060 ScalarizableIdx.discard();
2064 Instruction::Store,
SI->getValueOperand()->getType(),
SI->getAlign(),
2067 if (
Load->hasOneUse())
2072 for (
auto [InsertVal, Idx] : InsertElements) {
2075 Index = CIdx->getZExtValue();
2086 for (
auto [InsertVal, Idx] : InsertElements) {
2089 const Value *GEPIndices[] = {ConstantInt::get(Idx->
getType(), 0), Idx};
2094 for (
auto [InsertVal, Idx] : InsertElements) {
2096 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2104 LLVM_DEBUG(
dbgs() <<
"Found an insert-elements vector store scalarization "
2107 <<
" NumInserts: " << InsertElements.size() <<
"\n"
2108 <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2111 if (OldCost <= NewCost)
2114 for (
auto [InsertVal, Idx] : InsertElements) {
2115 auto ScalarizableIdx =
2117 assert(!ScalarizableIdx.isUnsafe() &&
"already checked above");
2119 if (ScalarizableIdx.isSafeWithFreeze())
2124 StoreInst *LastStore =
nullptr;
2125 for (
auto [InsertVal, Idx] : InsertElements) {
2126 auto ScalarizableIdx =
2128 if (ScalarizableIdx.isUnsafe())
2131 IntegerType *GEPIndexTy =
2136 SI->getValueOperand()->getType(),
SI->getPointerOperand(),
2137 {ConstantInt::get(GEPIdx->getType(), 0), GEPIdx});
2144 LastStore->
setMetadata(LLVMContext::MD_invariant_group,
nullptr);
2146 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2151 replaceValue(
I, *LastStore);
2158bool VectorCombine::scalarizeLoad(Instruction &
I) {
2168 if (!LI->isSimple() || !
DL->typeSizeEqualsStoreSize(VecTy->getScalarType()))
2171 bool AllExtracts =
true;
2172 bool AllBitcasts =
true;
2174 unsigned NumInstChecked = 0;
2179 for (User *U : LI->users()) {
2181 if (!UI || UI->getParent() != LI->getParent())
2186 if (UI->use_empty())
2190 AllExtracts =
false;
2192 AllBitcasts =
false;
2196 for (Instruction &
I :
2197 make_range(std::next(LI->getIterator()), UI->getIterator())) {
2204 LastCheckedInst = UI;
2209 return scalarizeLoadExtract(LI, VecTy, Ptr);
2211 return scalarizeLoadBitcast(LI, VecTy, Ptr);
2216bool VectorCombine::scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
2221 DenseMap<ExtractElementInst *, ScalarizationResult> NeedFreeze;
2222 DenseMap<ExtractElementInst *, IntegerType *> GEPIndexInfos;
2225 for (
auto &Pair : NeedFreeze)
2226 Pair.second.discard();
2234 for (User *U : LI->
users()) {
2239 if (ScalarIdx.isUnsafe())
2245 ScalarIdx.discard();
2251 if (ScalarIdx.isSafeWithFreeze()) {
2252 NeedFreeze.try_emplace(UI, ScalarIdx);
2253 ScalarIdx.discard();
2259 Index ?
Index->getZExtValue() : -1);
2265 if (!Index && UI->getIndexOperand()->getType()->getIntegerBitWidth() <
2268 Instruction::ZExt, GEPIndex, UI->getIndexOperand()->getType(),
2272 LLVM_DEBUG(
dbgs() <<
"Found all extractions of a vector load: " << *LI
2273 <<
"\n LoadExtractCost: " << OriginalCost
2274 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2276 if (ScalarizedCost > OriginalCost)
2278 if (ScalarizedCost == OriginalCost && !LI->
hasOneUse())
2285 Type *ElemType = VecTy->getElementType();
2288 for (User *U : LI->
users()) {
2290 Value *Idx = EI->getIndexOperand();
2293 if (
auto It = NeedFreeze.find(EI); It != NeedFreeze.end())
2297 auto It = GEPIndexInfos.
find(EI);
2299 "Missing scalarized GEP index information");
2302 VecTy, Ptr, {ConstantInt::get(GEPIdx->
getType(), 0), GEPIdx});
2304 Builder.
CreateLoad(ElemType,
GEP, EI->getName() +
".scalar"));
2306 Align ScalarOpAlignment =
2308 NewLoad->setAlignment(ScalarOpAlignment);
2311 size_t Offset = ConstIdx->getZExtValue() *
DL->getTypeStoreSize(ElemType);
2316 replaceValue(*EI, *NewLoad,
false);
2319 FailureGuard.release();
2324bool VectorCombine::scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
2333 Type *TargetScalarType =
nullptr;
2334 unsigned VecBitWidth =
DL->getTypeSizeInBits(VecTy);
2336 for (User *U : LI->
users()) {
2339 Type *DestTy = BC->getDestTy();
2343 unsigned DestBitWidth =
DL->getTypeSizeInBits(DestTy);
2344 if (DestBitWidth != VecBitWidth)
2348 if (!TargetScalarType)
2349 TargetScalarType = DestTy;
2350 else if (TargetScalarType != DestTy)
2358 if (!TargetScalarType)
2366 LLVM_DEBUG(
dbgs() <<
"Found vector load feeding only bitcasts: " << *LI
2367 <<
"\n OriginalCost: " << OriginalCost
2368 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2370 if (ScalarizedCost >= OriginalCost)
2381 ScalarLoad->copyMetadata(*LI);
2384 for (User *U : LI->
users()) {
2386 replaceValue(*BC, *ScalarLoad,
false);
2392bool VectorCombine::scalarizeExtExtract(Instruction &
I) {
2407 Type *ScalarDstTy = DstTy->getElementType();
2408 if (
DL->getTypeSizeInBits(SrcTy) !=
DL->getTypeSizeInBits(ScalarDstTy))
2414 unsigned ExtCnt = 0;
2415 bool ExtLane0 =
false;
2416 for (User *U : Ext->users()) {
2422 if (Idx >= SrcTy->getNumElements())
2434 Instruction::And, ScalarDstTy,
CostKind,
2437 (ExtCnt - ExtLane0) *
2439 Instruction::LShr, ScalarDstTy,
CostKind,
2442 if (ScalarCost > VectorCost)
2445 Value *ScalarV = Ext->getOperand(0);
2452 SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
2453 bool AllExtractsTriggerUB =
true;
2454 ExtractElementInst *LastExtract =
nullptr;
2456 for (User *U : Ext->users()) {
2459 AllExtractsTriggerUB =
false;
2463 if (!LastExtract || LastExtract->
comesBefore(Extract))
2464 LastExtract = Extract;
2466 if (ExtractedLanes.
size() != DstTy->getNumElements() ||
2467 !AllExtractsTriggerUB ||
2475 uint64_t SrcEltSizeInBits =
DL->getTypeSizeInBits(SrcTy->getElementType());
2476 uint64_t TotalBits =
DL->getTypeSizeInBits(SrcTy);
2479 Value *
Mask = ConstantInt::get(PackedTy, EltBitMask);
2480 for (User *U : Ext->users()) {
2486 ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits)
2487 : (Idx * SrcEltSizeInBits);
2490 U->replaceAllUsesWith(
And);
2498bool VectorCombine::foldConcatOfBoolMasks(Instruction &
I) {
2499 Type *Ty =
I.getType();
2504 if (
DL->isBigEndian())
2531 if (ShAmtX > ShAmtY) {
2539 uint64_t ShAmtDiff = ShAmtY - ShAmtX;
2540 unsigned NumSHL = (ShAmtX > 0) + (ShAmtY > 0);
2545 MaskTy->getNumElements() != ShAmtDiff ||
2546 MaskTy->getNumElements() > (
BitWidth / 2))
2551 Type::getIntNTy(Ty->
getContext(), ConcatTy->getNumElements());
2552 auto *MaskIntTy = Type::getIntNTy(Ty->
getContext(), ShAmtDiff);
2555 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2572 if (Ty != ConcatIntTy)
2578 LLVM_DEBUG(
dbgs() <<
"Found a concatenation of bitcasted bool masks: " <<
I
2579 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2582 if (NewCost > OldCost)
2592 if (Ty != ConcatIntTy) {
2602 replaceValue(
I, *Result);
2608bool VectorCombine::foldPermuteOfBinops(Instruction &
I) {
2609 BinaryOperator *BinOp;
2610 ArrayRef<int> OuterMask;
2618 Value *Op00, *Op01, *Op10, *Op11;
2619 ArrayRef<int> Mask0, Mask1;
2624 if (!Match0 && !Match1)
2637 if (!ShuffleDstTy || !BinOpTy || !Op0Ty || !Op1Ty)
2640 unsigned NumSrcElts = BinOpTy->getNumElements();
2645 any_of(OuterMask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
2649 SmallVector<int> NewMask0, NewMask1;
2650 for (
int M : OuterMask) {
2651 if (M < 0 || M >= (
int)NumSrcElts) {
2655 NewMask0.
push_back(Match0 ? Mask0[M] : M);
2656 NewMask1.
push_back(Match1 ? Mask1[M] : M);
2660 unsigned NumOpElts = Op0Ty->getNumElements();
2661 bool IsIdentity0 = ShuffleDstTy == Op0Ty &&
2662 all_of(NewMask0, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2664 bool IsIdentity1 = ShuffleDstTy == Op1Ty &&
2665 all_of(NewMask1, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2674 ShuffleDstTy, BinOpTy,
CostKind, OuterMask,
2675 0,
nullptr, {BinOp}, &
I);
2677 NewCost += BinOpCost;
2683 OldCost += Shuf0Cost;
2685 NewCost += Shuf0Cost;
2691 OldCost += Shuf1Cost;
2693 NewCost += Shuf1Cost;
2701 Op0Ty,
CostKind, NewMask0, 0,
nullptr, {Op00, Op01});
2705 Op1Ty,
CostKind, NewMask1, 0,
nullptr, {Op10, Op11});
2707 LLVM_DEBUG(
dbgs() <<
"Found a shuffle feeding a shuffled binop: " <<
I
2708 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2712 if (NewCost > OldCost)
2723 NewInst->copyIRFlags(BinOp);
2727 replaceValue(
I, *NewBO);
2733bool VectorCombine::foldShuffleOfBinops(Instruction &
I) {
2734 ArrayRef<int> OldMask;
2741 if (
LHS->getOpcode() !=
RHS->getOpcode())
2745 bool IsCommutative =
false;
2754 IsCommutative = BinaryOperator::isCommutative(BO->getOpcode());
2765 if (!ShuffleDstTy || !BinResTy || !BinOpTy ||
X->getType() !=
Z->getType())
2768 bool SameBinOp =
LHS ==
RHS;
2769 unsigned NumSrcElts = BinOpTy->getNumElements();
2772 if (IsCommutative &&
X != Z &&
Y != W && (
X == W ||
Y == Z))
2775 auto ConvertToUnary = [NumSrcElts](
int &
M) {
2776 if (M >= (
int)NumSrcElts)
2780 SmallVector<int> NewMask0(OldMask);
2789 SmallVector<int> NewMask1(OldMask);
2808 ShuffleDstTy, BinResTy,
CostKind, OldMask, 0,
2818 ArrayRef<int> InnerMask;
2820 m_Mask(InnerMask)))) &&
2823 [NumSrcElts](
int M) {
return M < (int)NumSrcElts; })) {
2835 bool ReducedInstCount =
false;
2836 ReducedInstCount |= MergeInner(
X, 0, NewMask0,
CostKind);
2837 ReducedInstCount |= MergeInner(
Y, 0, NewMask1,
CostKind);
2838 ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0,
CostKind);
2839 ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1,
CostKind);
2840 bool SingleSrcBinOp = (
X ==
Y) && (Z == W) && (NewMask0 == NewMask1);
2852 I.getType()->getScalarType()->isIntegerTy(1) &&
2856 auto *ShuffleCmpTy =
2859 SK0, ShuffleCmpTy, BinOpTy,
CostKind, NewMask0, 0,
nullptr, {
X,
Z});
2860 if (!SingleSrcBinOp)
2862 NewMask1, 0,
nullptr, {
Y,
W});
2870 PredLHS,
CostKind, Op0Info, Op1Info);
2880 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2887 if (ReducedInstCount ? (NewCost > OldCost) : (NewCost >= OldCost))
2896 : Builder.
CreateCmp(PredLHS, Shuf0, Shuf1);
2900 NewInst->copyIRFlags(
LHS);
2901 NewInst->andIRFlags(
RHS);
2906 replaceValue(
I, *NewBO);
2913bool VectorCombine::foldShuffleOfSelects(Instruction &
I) {
2915 Value *C1, *
T1, *F1, *C2, *T2, *F2;
2926 if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2932 if (((SI0FOp ==
nullptr) != (SI1FOp ==
nullptr)) ||
2933 ((SI0FOp !=
nullptr) &&
2934 (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())))
2940 auto SelOp = Instruction::Select;
2948 CostSel1 + CostSel2 +
2950 {
I.getOperand(0),
I.getOperand(1)}, &
I);
2954 CostKind, Mask, 0,
nullptr, {C1, C2});
2964 if (!Sel1->hasOneUse())
2965 NewCost += CostSel1;
2966 if (!Sel2->hasOneUse())
2967 NewCost += CostSel2;
2970 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2972 if (NewCost > OldCost)
2981 NewSel = Builder.
CreateSelectFMF(ShuffleCmp, ShuffleTrue, ShuffleFalse,
2982 SI0FOp->getFastMathFlags());
2984 NewSel = Builder.
CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
2989 replaceValue(
I, *NewSel);
2995bool VectorCombine::foldShuffleOfCastops(Instruction &
I) {
2997 ArrayRef<int> OldMask;
3006 if (!C0 || (IsBinaryShuffle && !C1))
3013 if (!IsBinaryShuffle && Opcode == Instruction::BitCast)
3016 if (IsBinaryShuffle) {
3017 if (C0->getSrcTy() != C1->getSrcTy())
3020 if (Opcode != C1->getOpcode()) {
3022 Opcode = Instruction::SExt;
3031 if (!ShuffleDstTy || !CastDstTy || !CastSrcTy)
3034 unsigned NumSrcElts = CastSrcTy->getNumElements();
3035 unsigned NumDstElts = CastDstTy->getNumElements();
3036 assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) &&
3037 "Only bitcasts expected to alter src/dst element counts");
3041 if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 &&
3042 (NumDstElts % NumSrcElts) != 0)
3045 SmallVector<int, 16> NewMask;
3046 if (NumSrcElts >= NumDstElts) {
3049 assert(NumSrcElts % NumDstElts == 0 &&
"Unexpected shuffle mask");
3050 unsigned ScaleFactor = NumSrcElts / NumDstElts;
3055 assert(NumDstElts % NumSrcElts == 0 &&
"Unexpected shuffle mask");
3056 unsigned ScaleFactor = NumDstElts / NumSrcElts;
3061 auto *NewShuffleDstTy =
3070 if (IsBinaryShuffle)
3077 OldMask, 0,
nullptr, {}, &
I);
3085 if (IsBinaryShuffle) {
3095 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3097 if (NewCost > OldCost)
3101 if (IsBinaryShuffle)
3111 NewInst->copyIRFlags(C0);
3112 if (IsBinaryShuffle)
3113 NewInst->andIRFlags(C1);
3117 replaceValue(
I, *Cast);
3127bool VectorCombine::foldShuffleOfShuffles(Instruction &
I) {
3128 ArrayRef<int> OuterMask;
3129 Value *OuterV0, *OuterV1;
3134 ArrayRef<int> InnerMask0, InnerMask1;
3135 Value *X0, *X1, *Y0, *Y1;
3140 if (!Match0 && !Match1)
3145 SmallVector<int, 16> PoisonMask1;
3150 InnerMask1 = PoisonMask1;
3154 X0 = Match0 ? X0 : OuterV0;
3155 Y0 = Match0 ? Y0 : OuterV0;
3156 X1 = Match1 ? X1 : OuterV1;
3157 Y1 = Match1 ? Y1 : OuterV1;
3161 if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy ||
3165 unsigned NumSrcElts = ShuffleSrcTy->getNumElements();
3166 unsigned NumImmElts = ShuffleImmTy->getNumElements();
3171 SmallVector<int, 16> NewMask(OuterMask);
3172 Value *NewX =
nullptr, *NewY =
nullptr;
3173 for (
int &M : NewMask) {
3174 Value *Src =
nullptr;
3175 if (0 <= M && M < (
int)NumImmElts) {
3179 Src =
M >= (int)NumSrcElts ? Y0 : X0;
3180 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3182 }
else if (M >= (
int)NumImmElts) {
3187 Src =
M >= (int)NumSrcElts ? Y1 : X1;
3188 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3192 assert(0 <= M && M < (
int)NumSrcElts &&
"Unexpected shuffle mask index");
3201 if (!NewX || NewX == Src) {
3205 if (!NewY || NewY == Src) {
3224 replaceValue(
I, *NewX);
3241 bool IsUnary =
all_of(NewMask, [&](
int M) {
return M < (int)NumSrcElts; });
3247 nullptr, {NewX, NewY});
3249 NewCost += InnerCost0;
3251 NewCost += InnerCost1;
3254 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3256 if (NewCost > OldCost)
3260 replaceValue(
I, *Shuf);
3276bool VectorCombine::foldShufflesOfLengthChangingShuffles(Instruction &
I) {
3281 unsigned ChainLength = 0;
3282 SmallVector<int>
Mask;
3283 SmallVector<int> YMask;
3293 ArrayRef<int> OuterMask;
3294 Value *OuterV0, *OuterV1;
3295 if (ChainLength != 0 && !Trunk->
hasOneUse())
3298 m_Mask(OuterMask))))
3300 if (OuterV0->
getType() != TrunkType) {
3306 ArrayRef<int> InnerMask0, InnerMask1;
3312 bool Match0Leaf = Match0 && A0->
getType() !=
I.getType();
3313 bool Match1Leaf = Match1 && A1->
getType() !=
I.getType();
3314 if (Match0Leaf == Match1Leaf) {
3320 SmallVector<int> CommutedOuterMask;
3327 for (
int &M : CommutedOuterMask) {
3330 if (M < (
int)NumTrunkElts)
3335 OuterMask = CommutedOuterMask;
3354 int NumLeafElts = YType->getNumElements();
3355 SmallVector<int> LocalYMask(InnerMask1);
3356 for (
int &M : LocalYMask) {
3357 if (M >= NumLeafElts)
3367 Mask.assign(OuterMask);
3368 YMask.
assign(LocalYMask);
3369 OldCost = NewCost = LocalOldCost;
3376 SmallVector<int> NewYMask(YMask);
3378 for (
auto [CombinedM, LeafM] :
llvm::zip(NewYMask, LocalYMask)) {
3379 if (LeafM == -1 || CombinedM == LeafM)
3381 if (CombinedM == -1) {
3391 SmallVector<int> NewMask;
3392 NewMask.
reserve(NumTrunkElts);
3393 for (
int M : Mask) {
3394 if (M < 0 || M >=
static_cast<int>(NumTrunkElts))
3409 if (LocalNewCost >= NewCost && LocalOldCost < LocalNewCost - NewCost)
3413 if (ChainLength == 1) {
3414 dbgs() <<
"Found chain of shuffles fed by length-changing shuffles: "
3417 dbgs() <<
" next chain link: " << *Trunk <<
'\n'
3418 <<
" old cost: " << (OldCost + LocalOldCost)
3419 <<
" new cost: " << LocalNewCost <<
'\n';
3424 OldCost += LocalOldCost;
3425 NewCost = LocalNewCost;
3429 if (ChainLength <= 1)
3437 return M < 0 || M >=
static_cast<int>(NumTrunkElts);
3440 for (
int &M : Mask) {
3441 if (M >=
static_cast<int>(NumTrunkElts))
3442 M = YMask[
M - NumTrunkElts];
3446 replaceValue(
I, *Root);
3453 replaceValue(
I, *Root);
3459bool VectorCombine::foldShuffleOfIntrinsics(Instruction &
I) {
3461 ArrayRef<int> OldMask;
3471 if (IID != II1->getIntrinsicID())
3480 if (!ShuffleDstTy || !II0Ty)
3486 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3487 Value *Arg0 = II0->getArgOperand(Idx);
3488 Value *Arg1 = II1->getArgOperand(Idx);
3505 II0Ty,
CostKind, OldMask, 0,
nullptr, {II0, II1}, &
I);
3509 SmallDenseSet<std::pair<Value *, Value *>> SeenOperandPairs;
3510 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3512 NewArgsTy.
push_back(II0->getArgOperand(Idx)->getType());
3516 ShuffleDstTy->getNumElements());
3518 std::pair<Value *, Value *> OperandPair =
3519 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3520 if (!SeenOperandPairs.
insert(OperandPair).second) {
3526 OldMask, 0,
nullptr,
3527 {II0->getArgOperand(Idx), II1->getArgOperand(Idx)});
3530 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3533 if (!II0->hasOneUse())
3535 if (II1 != II0 && !II1->hasOneUse())
3539 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3542 if (NewCost > OldCost)
3546 SmallDenseMap<std::pair<Value *, Value *>,
Value *> ShuffleCache;
3547 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3549 NewArgs.
push_back(II0->getArgOperand(Idx));
3551 std::pair<Value *, Value *> OperandPair =
3552 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3553 auto It = ShuffleCache.
find(OperandPair);
3554 if (It != ShuffleCache.
end()) {
3560 II0->getArgOperand(Idx), II1->getArgOperand(Idx), OldMask);
3561 ShuffleCache[OperandPair] = Shuf;
3570 NewInst->copyIRFlags(II0);
3571 NewInst->andIRFlags(II1);
3574 replaceValue(
I, *NewIntrinsic);
3580bool VectorCombine::foldPermuteOfIntrinsic(Instruction &
I) {
3592 if (!ShuffleDstTy || !IntrinsicSrcTy)
3596 unsigned NumSrcElts = IntrinsicSrcTy->getNumElements();
3597 if (
any_of(Mask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
3610 IntrinsicSrcTy,
CostKind, Mask, 0,
nullptr, {
V0}, &
I);
3614 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3616 NewArgsTy.
push_back(II0->getArgOperand(
I)->getType());
3620 ShuffleDstTy->getNumElements());
3623 ArgTy, VecTy,
CostKind, Mask, 0,
nullptr,
3624 {II0->getArgOperand(
I)});
3627 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3632 if (!II0->hasOneUse())
3635 LLVM_DEBUG(
dbgs() <<
"Found a permute of intrinsic: " <<
I <<
"\n OldCost: "
3636 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
3638 if (NewCost > OldCost)
3643 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3656 NewInst->copyIRFlags(II0);
3658 replaceValue(
I, *NewIntrinsic);
3668 int M = SV->getMaskValue(Lane);
3671 if (
static_cast<unsigned>(M) < NumElts) {
3672 V = SV->getOperand(0);
3675 V = SV->getOperand(1);
3686 auto [U, Lane] = IL;
3699 unsigned NumElts = Ty->getNumElements();
3700 if (Item.
size() == NumElts || NumElts == 1 || Item.
size() % NumElts != 0)
3706 std::iota(ConcatMask.
begin(), ConcatMask.
end(), 0);
3712 unsigned NumSlices = Item.
size() / NumElts;
3717 for (
unsigned Slice = 0; Slice < NumSlices; ++Slice) {
3718 Value *SliceV = Item[Slice * NumElts].first;
3719 if (!SliceV || SliceV->
getType() != Ty)
3721 for (
unsigned Elt = 0; Elt < NumElts; ++Elt) {
3722 auto [V, Lane] = Item[Slice * NumElts + Elt];
3723 if (Lane !=
static_cast<int>(Elt) || SliceV != V)
3732 const DenseSet<std::pair<Value *, Use *>> &IdentityLeafs,
3733 const DenseSet<std::pair<Value *, Use *>> &SplatLeafs,
3734 const DenseSet<std::pair<Value *, Use *>> &ConcatLeafs,
3737 auto [FrontV, FrontLane] = Item.
front();
3739 if (IdentityLeafs.contains(std::make_pair(FrontV, From))) {
3742 if (SplatLeafs.contains(std::make_pair(FrontV, From))) {
3744 return Builder.CreateShuffleVector(FrontV, Mask);
3746 if (ConcatLeafs.contains(std::make_pair(FrontV, From))) {
3750 for (
unsigned S = 0; S <
Values.size(); ++S)
3751 Values[S] = Item[S * NumElts].first;
3753 while (
Values.size() > 1) {
3756 std::iota(Mask.begin(), Mask.end(), 0);
3758 for (
unsigned S = 0; S < NewValues.
size(); ++S)
3760 Builder.CreateShuffleVector(
Values[S * 2],
Values[S * 2 + 1], Mask);
3774 if (BCDstTy && BCSrcTy &&
3775 BCDstTy->getElementCount() != BCSrcTy->getElementCount()) {
3776 unsigned DstElts = BCDstTy->getNumElements();
3777 unsigned SrcElts = BCSrcTy->getNumElements();
3779 if (DstElts > SrcElts) {
3781 unsigned R = DstElts / SrcElts;
3782 if (Item.
size() % R != 0)
3784 for (
unsigned Idx = 0,
E = Item.
size(); Idx <
E; Idx += R) {
3785 auto [V, Lane] = Item[Idx];
3795 unsigned R = SrcElts / DstElts;
3796 for (
auto [V, Lane] : Item) {
3802 for (
unsigned J = 0; J < R; ++J)
3807 IdentityLeafs, SplatLeafs, ConcatLeafs,
3808 Builder, WorkList,
TTI);
3810 return Builder.CreateBitCast(
3815 unsigned NumOps =
I->getNumOperands() - (
II ? 1 : 0);
3817 for (
unsigned Idx = 0; Idx <
NumOps; Idx++) {
3820 Ops[Idx] =
II->getOperand(Idx);
3825 IdentityLeafs, SplatLeafs, ConcatLeafs, Builder, WorkList,
TTI);
3835 for (
const auto &Lane : Item)
3848 auto *
Value = Builder.CreateCmp(CI->getPredicate(),
Ops[0],
Ops[1]);
3858 auto *
Value = Builder.CreateCast(CI->getOpcode(),
Ops[0], DstTy);
3863 auto *
Value = Builder.CreateIntrinsic(DstTy,
II->getIntrinsicID(),
Ops);
3877bool VectorCombine::foldShuffleToIdentity(Instruction &
I) {
3879 if (!Ty ||
I.use_empty())
3883 for (
unsigned M = 0,
E = Ty->getNumElements(); M <
E; ++M)
3887 Candidates.
push_back(std::make_pair(Start, &*
I.use_begin()));
3888 DenseSet<std::pair<Value *, Use *>> IdentityLeafs, SplatLeafs, ConcatLeafs;
3889 unsigned NumVisited = 0;
3890 bool TraversedElCountChangingBitcast =
false;
3892 while (!Candidates.
empty()) {
3897 auto Item = ItemFrom.first;
3898 auto From = ItemFrom.second;
3899 auto [FrontV, FrontLane] = Item.front();
3906 if (FrontLane == 0 &&
3910 Value *FrontV = Item.front().first;
3912 E.value().second == (int)
E.index());
3914 IdentityLeafs.
insert(std::make_pair(FrontV, From));
3919 C &&
C->getSplatValue() &&
3921 Value *FrontV = Item.front().first;
3927 SplatLeafs.
insert(std::make_pair(FrontV, From));
3932 auto [FrontV, FrontLane] = Item.front();
3933 auto [
V, Lane] = IL;
3934 return !
V || (
V == FrontV && Lane == FrontLane);
3936 SplatLeafs.
insert(std::make_pair(FrontV, From));
3942 auto CheckLaneIsEquivalentToFirst = [Item](
InstLane IL) {
3943 Value *FrontV = Item.front().first;
3952 if (CI->getPredicate() !=
cast<CmpInst>(FrontV)->getPredicate())
3955 if (CI->getSrcTy()->getScalarType() !=
3960 SI->getOperand(0)->getType() !=
3967 II->getIntrinsicID() ==
3969 !
II->hasOperandBundles());
3976 BO && BO->isIntDivRem())
3983 }
else if (
isa<UnaryOperator, TruncInst, ZExtInst, SExtInst, FPToSIInst,
3984 FPToUIInst, SIToFPInst, UIToFPInst>(FrontV)) {
3991 if (BCDstTy && BCSrcTy) {
3992 ElementCount DstEC = BCDstTy->getElementCount();
3993 ElementCount SrcEC = BCSrcTy->getElementCount();
3994 if (DstEC == SrcEC) {
3997 &BitCast->getOperandUse(0));
4002 if (DstElts > SrcElts && DstElts % SrcElts == 0) {
4006 unsigned R = DstElts / SrcElts;
4008 bool Valid = Item.size() %
R == 0;
4009 for (
unsigned Idx = 0,
E = Item.size(); Valid && Idx <
E;
4011 auto [
V0, L0] = Item[Idx];
4014 [](
InstLane IL) {
return IL.first !=
nullptr; })) {
4025 for (
unsigned J = 1; J <
R; ++J) {
4026 auto [VJ, LJ] = Item[Idx + J];
4027 if (!VJ || VJ != V0 || LJ != L0 + (
int)J) {
4038 TraversedElCountChangingBitcast =
true;
4039 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4042 }
else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
4045 unsigned R = SrcElts / DstElts;
4047 for (
auto [V, Lane] : Item) {
4053 for (
unsigned J = 0; J <
R; ++J)
4056 TraversedElCountChangingBitcast =
true;
4057 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4063 &Sel->getOperandUse(0));
4065 &Sel->getOperandUse(1));
4067 &Sel->getOperandUse(2));
4071 !
II->hasOperandBundles()) {
4072 for (
unsigned Op = 0,
E =
II->getNumOperands() - 1;
Op <
E;
Op++) {
4076 Value *FrontV = Item.front().first;
4093 ConcatLeafs.
insert(std::make_pair(FrontV, From));
4100 if (NumVisited <= 1)
4106 if (NumVisited == 2 && TraversedElCountChangingBitcast)
4109 LLVM_DEBUG(
dbgs() <<
"Found a superfluous identity shuffle: " <<
I <<
"\n");
4116 ConcatLeafs, Builder, Worklist, &
TTI);
4117 replaceValue(
I, *V);
4124bool VectorCombine::foldShuffleFromReductions(Instruction &
I) {
4128 switch (
II->getIntrinsicID()) {
4129 case Intrinsic::vector_reduce_add:
4130 case Intrinsic::vector_reduce_mul:
4131 case Intrinsic::vector_reduce_and:
4132 case Intrinsic::vector_reduce_or:
4133 case Intrinsic::vector_reduce_xor:
4134 case Intrinsic::vector_reduce_smin:
4135 case Intrinsic::vector_reduce_smax:
4136 case Intrinsic::vector_reduce_umin:
4137 case Intrinsic::vector_reduce_umax:
4146 std::queue<Value *> Worklist;
4147 SmallPtrSet<Value *, 4> Visited;
4148 ShuffleVectorInst *Shuffle =
nullptr;
4152 while (!Worklist.empty()) {
4153 Value *CV = Worklist.front();
4165 if (CI->isBinaryOp()) {
4166 for (
auto *
Op : CI->operand_values())
4170 if (Shuffle && Shuffle != SV)
4187 for (
auto *V : Visited)
4188 for (
auto *U :
V->users())
4189 if (!Visited.contains(U) && U != &
I)
4192 FixedVectorType *VecType =
4196 FixedVectorType *ShuffleInputType =
4198 if (!ShuffleInputType)
4204 SmallVector<int> ConcatMask;
4206 sort(ConcatMask, [](
int X,
int Y) {
return (
unsigned)
X < (unsigned)
Y; });
4207 bool UsesSecondVec =
4208 any_of(ConcatMask, [&](
int M) {
return M >= (int)NumInputElts; });
4215 ShuffleInputType,
CostKind, ConcatMask);
4217 LLVM_DEBUG(
dbgs() <<
"Found a reduction feeding from a shuffle: " << *Shuffle
4219 LLVM_DEBUG(
dbgs() <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
4221 bool MadeChanges =
false;
4222 if (NewCost < OldCost) {
4226 LLVM_DEBUG(
dbgs() <<
"Created new shuffle: " << *NewShuffle <<
"\n");
4227 replaceValue(*Shuffle, *NewShuffle);
4233 MadeChanges |= foldSelectShuffle(*Shuffle,
true);
4254bool VectorCombine::foldShuffleChainsToReduce(Instruction &
I) {
4263 if (FVT->getNumElements() < 2)
4266 std::optional<Instruction::BinaryOps> CommonBinOp;
4267 std::optional<Intrinsic::ID> CommonCallOp;
4272 CommonBinOp = BO->getOpcode();
4274 CommonCallOp = MMI->getIntrinsicID();
4280 FastMathFlags CommonFMF;
4281 bool IsFloatReduction =
false;
4285 auto IsChainNode = [&](
Value *
V) {
4287 return CommonBinOp && BO->getOpcode() == *CommonBinOp;
4289 return CommonCallOp && MMI->getIntrinsicID() == *CommonCallOp;
4297 constexpr unsigned MaxChainNodes = 32;
4298 SmallSetVector<Value *, 16> Nodes;
4299 SmallSetVector<Value *, 4> Sources;
4300 unsigned NumVisited = 0;
4301 auto AddSource = [&](
Value *
V) {
4307 auto Walk = [&](
Value *
V,
auto &&Walk) ->
bool {
4310 if (++NumVisited > MaxChainNodes)
4312 if (!IsChainNode(V))
4313 return AddSource(V);
4318 if (!Walk(
U->getOperand(
I), Walk))
4327 return AddSource(V);
4329 if (!Walk(VecOpEE, Walk) || Nodes.
empty())
4336 for (
Value *V : Nodes) {
4342 if (!IsFloatReduction) {
4344 IsFloatReduction =
true;
4358 DenseMap<Value *, Demand> Demands;
4359 auto DemandOf = [&](
Value *
V) -> Demand & {
4361 Demand &
D = Demands[
V];
4362 if (
D.Lanes.getBitWidth() !=
N)
4366 DemandOf(VecOpEE).Lanes.setBit(0);
4368 Demand DV = Demands.
lookup(V);
4369 if (DV.Lanes.isZero())
4372 ArrayRef<int>
Mask = SVI->getShuffleMask();
4373 Demand &
DS = DemandOf(SVI->getOperand(0));
4374 for (
unsigned I = 0,
E =
Mask.size();
I !=
E; ++
I) {
4376 if (!DV.Lanes[
I] || Mask[
I] < 0 ||
4377 (
unsigned)Mask[
I] >=
DS.Lanes.getBitWidth())
4379 if (
DS.Lanes[Mask[
I]] || DV.Duplicates[
I])
4380 DS.Duplicates.setBit(Mask[
I]);
4381 DS.Lanes.setBit(Mask[
I]);
4385 for (
Value *
Op : {
U->getOperand(0),
U->getOperand(1)}) {
4386 Demand &DOp = DemandOf(
Op);
4388 DOp.Duplicates |= DV.Duplicates | (DOp.Lanes & DV.Lanes);
4389 DOp.Lanes |= DV.Lanes;
4396 auto CoversChain = [&](
Value *
V) {
4397 SmallVector<Value *, 8> Worklist(1, VecOpEE);
4398 SmallPtrSet<Value *, 8> Seen;
4400 while (!Worklist.empty()) {
4403 for (
unsigned I = 0;
I !=
NumOps; ++
I) {
4407 if (!Nodes.contains(
Op))
4409 Worklist.push_back(
Op);
4417 struct ReductionCut {
4421 std::optional<ReductionCut> Cut;
4422 for (
Value *S : Sources) {
4423 auto It = Demands.
find(S);
4424 if (It == Demands.
end() || It->second.Lanes.isZero())
4426 if (!IsIdempotent && !It->second.Duplicates.isZero()) {
4431 Cut = ReductionCut{S, It->second.Lanes};
4438 if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
4442 Cut->Elts |= It->second.Lanes;
4445 for (
Value *V : Nodes) {
4448 auto It = Demands.
find(V);
4449 if (It == Demands.
end() || !It->second.Lanes.isAllOnes())
4451 if (!IsIdempotent && !It->second.Duplicates.isZero())
4453 if (!CoversChain(V))
4455 Cut = ReductionCut{
V, It->second.Lanes};
4460 if (!Cut || Cut->Elts.popcount() < 2)
4470 for (
Value *V : Nodes)
4474 bool IsPartialReduction = !Cut->Elts.isAllOnes();
4475 FixedVectorType *ReduceVecTy =
4480 SmallVector<int> ExtractMask;
4482 if (IsPartialReduction) {
4483 for (
unsigned I = 0,
E = Cut->Elts.getBitWidth();
I !=
E; ++
I)
4485 ExtractMask.push_back(
I);
4486 unsigned SubIdx = 0, SubLen;
4487 auto SK = Cut->Elts.isShiftedMask(SubIdx, SubLen)
4491 SubIdx, ReduceVecTy);
4494 IntrinsicCostAttributes ICA(
4495 ReducedOp, ReduceVecTy->getElementType(),
4499 IsFloatReduction ? CommonFMF : FastMathFlags());
4502 LLVM_DEBUG(
dbgs() <<
"Found reduction shuffle chain: " <<
I <<
"\n OldCost : "
4503 << OrigCost <<
" vs NewCost: " << NewCost <<
"\n");
4508 if (VecOpEE->
hasOneUse() ? (NewCost > OrigCost) : (NewCost >= OrigCost))
4511 Value *ReduceInput = Cut->Src;
4512 if (IsPartialReduction)
4515 Value *ReducedResult;
4516 if (IsFloatReduction) {
4518 *CommonBinOp, ReduceVecTy->getElementType(),
false,
4521 {Identity, ReduceInput}, CommonFMF);
4526 replaceValue(
I, *ReducedResult);
4535bool VectorCombine::foldCastFromReductions(Instruction &
I) {
4540 bool TruncOnly =
false;
4543 case Intrinsic::vector_reduce_add:
4544 case Intrinsic::vector_reduce_mul:
4547 case Intrinsic::vector_reduce_and:
4548 case Intrinsic::vector_reduce_or:
4549 case Intrinsic::vector_reduce_xor:
4556 Value *ReductionSrc =
I.getOperand(0);
4568 Type *ResultTy =
I.getType();
4571 ReductionOpc, ReductionSrcTy, std::nullopt,
CostKind);
4581 if (OldCost <= NewCost || !NewCost.
isValid())
4585 II->getIntrinsicID(), {Src});
4587 replaceValue(
I, *NewCast);
4615bool VectorCombine::foldSignBitReductionCmp(Instruction &
I) {
4617 IntrinsicInst *ReduceOp;
4618 const APInt *CmpVal;
4625 case Intrinsic::vector_reduce_or:
4626 case Intrinsic::vector_reduce_umax:
4627 case Intrinsic::vector_reduce_and:
4628 case Intrinsic::vector_reduce_umin:
4629 case Intrinsic::vector_reduce_add:
4640 unsigned BitWidth = VecTy->getScalarSizeInBits();
4644 unsigned NumElts = VecTy->getNumElements();
4653 case Intrinsic::vector_reduce_or:
4654 case Intrinsic::vector_reduce_umax:
4655 TreeOpcode = Instruction::Or;
4657 case Intrinsic::vector_reduce_and:
4658 case Intrinsic::vector_reduce_umin:
4659 TreeOpcode = Instruction::And;
4661 case Intrinsic::vector_reduce_add:
4662 TreeOpcode = Instruction::Add;
4670 SmallVector<Value *, 8> Worklist;
4671 SmallVector<Value *, 8> Sources;
4673 std::optional<bool> IsAShr;
4674 constexpr unsigned MaxSources = 8;
4679 while (!Worklist.
empty() && Worklist.
size() <= MaxSources &&
4680 Sources.
size() <= MaxSources) {
4689 bool ThisIsAShr = Shr->getOpcode() == Instruction::AShr;
4691 IsAShr = ThisIsAShr;
4692 else if (*IsAShr != ThisIsAShr)
4718 if (Sources.
empty() || Sources.
size() > MaxSources ||
4719 Worklist.
size() > MaxSources || !IsAShr)
4722 unsigned NumSources = Sources.
size();
4726 if (OrigIID == Intrinsic::vector_reduce_add &&
4734 (OrigIID == Intrinsic::vector_reduce_add) ? NumSources * NumElts : 1;
4737 NegativeVal.negate();
4769 TestsNegative =
false;
4770 }
else if (*CmpVal == NegativeVal) {
4771 TestsNegative =
true;
4775 IsEq = Pred == ICmpInst::ICMP_EQ;
4776 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeHigh) {
4778 TestsNegative = (RangeHigh == NegativeVal);
4779 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeHigh - 1) {
4781 TestsNegative = (RangeHigh == NegativeVal);
4782 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeLow) {
4784 TestsNegative = (RangeLow == NegativeVal);
4785 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeLow + 1) {
4787 TestsNegative = (RangeLow == NegativeVal);
4830 enum CheckKind :
unsigned {
4837 auto RequiresOr = [](CheckKind
C) ->
bool {
return C & 0b100; };
4839 auto IsNegativeCheck = [](CheckKind
C) ->
bool {
return C & 0b010; };
4841 auto Invert = [](CheckKind
C) {
return CheckKind(
C ^ 0b011); };
4845 case Intrinsic::vector_reduce_or:
4846 case Intrinsic::vector_reduce_umax:
4847 Base = TestsNegative ? AnyNeg : AllNonNeg;
4849 case Intrinsic::vector_reduce_and:
4850 case Intrinsic::vector_reduce_umin:
4851 Base = TestsNegative ? AllNeg : AnyNonNeg;
4853 case Intrinsic::vector_reduce_add:
4854 Base = TestsNegative ? AllNeg : AllNonNeg;
4869 return ArithCost <= MinMaxCost ? std::make_pair(Arith, ArithCost)
4870 : std::make_pair(MinMax, MinMaxCost);
4874 auto [NewIID, NewCost] = RequiresOr(
Check)
4875 ? PickCheaper(Intrinsic::vector_reduce_or,
4876 Intrinsic::vector_reduce_umax)
4877 : PickCheaper(
Intrinsic::vector_reduce_and,
4881 if (NumSources > 1) {
4882 unsigned CombineOpc =
4883 RequiresOr(
Check) ? Instruction::Or : Instruction::And;
4888 LLVM_DEBUG(
dbgs() <<
"Found sign-bit reduction cmp: " <<
I <<
"\n OldCost: "
4889 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4891 if (NewCost > OldCost)
4896 Type *ScalarTy = VecTy->getScalarType();
4899 if (NumSources == 1) {
4910 replaceValue(
I, *NewCmp);
4941bool VectorCombine::foldReductionZeroTest(Instruction &
I) {
4950 if (!
II || !
II->hasOneUse())
4953 auto ReduceID =
II->getIntrinsicID();
4954 if (ReduceID != Intrinsic::vector_reduce_or &&
4955 ReduceID != Intrinsic::vector_reduce_umax)
4958 Value *Vec =
II->getArgOperand(0);
4960 if (!VecTy || !VecTy->getElementType()->isIntegerTy())
4965 ? Intrinsic::vector_reduce_or
4980 LLVM_DEBUG(
dbgs() <<
"Found a reduction zero test: " <<
I <<
"\n OldCost: "
4981 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4983 if (!OldCost.
isValid() || !NewCost.
isValid() || NewCost > OldCost)
4989 replaceValue(
I, *NewReduce);
5014bool VectorCombine::foldICmpEqZeroVectorReduce(Instruction &
I) {
5025 switch (
II->getIntrinsicID()) {
5026 case Intrinsic::vector_reduce_add:
5027 case Intrinsic::vector_reduce_or:
5028 case Intrinsic::vector_reduce_umin:
5029 case Intrinsic::vector_reduce_umax:
5030 case Intrinsic::vector_reduce_smin:
5031 case Intrinsic::vector_reduce_smax:
5037 Value *InnerOp =
II->getArgOperand(0);
5080 switch (
II->getIntrinsicID()) {
5081 case Intrinsic::vector_reduce_add: {
5086 unsigned NumElems = XTy->getNumElements();
5092 if (LeadingZerosX <= LostBits || LeadingZerosFX <= LostBits)
5100 case Intrinsic::vector_reduce_smin:
5101 case Intrinsic::vector_reduce_smax:
5111 LLVM_DEBUG(
dbgs() <<
"Found a reduction to 0 comparison with removable op: "
5127 case Intrinsic::vector_reduce_add:
5128 case Intrinsic::vector_reduce_or:
5134 case Intrinsic::vector_reduce_umin:
5135 case Intrinsic::vector_reduce_umax:
5136 case Intrinsic::vector_reduce_smin:
5137 case Intrinsic::vector_reduce_smax:
5149 NewReduceCost + (InnerOp->
hasOneUse() ? 0 : ExtCost);
5151 LLVM_DEBUG(
dbgs() <<
"Found a removable extension before reduction: "
5152 << *InnerOp <<
"\n OldCost: " << OldCost
5153 <<
" vs NewCost: " << NewCost <<
"\n");
5159 if (NewCost > OldCost)
5168 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::getNullValue(Ty));
5169 replaceValue(
I, *NewCmp);
5200bool VectorCombine::foldEquivalentReductionCmp(Instruction &
I) {
5203 const APInt *CmpVal;
5208 if (!
II || !
II->hasOneUse())
5211 const auto IsValidOrUmaxCmp = [&]() {
5220 bool IsPositive = CmpVal->
isAllOnes() && Pred == ICmpInst::ICMP_SGT;
5222 bool IsNegative = (CmpVal->
isZero() || CmpVal->
isOne() || *CmpVal == 2) &&
5223 Pred == ICmpInst::ICMP_SLT;
5224 return IsEquality || IsPositive || IsNegative;
5227 const auto IsValidAndUminCmp = [&]() {
5232 const auto LeadingOnes = CmpVal->
countl_one();
5239 bool IsNegative = CmpVal->
isZero() && Pred == ICmpInst::ICMP_SLT;
5248 ((*CmpVal)[0] || (*CmpVal)[1]) && Pred == ICmpInst::ICMP_SGT;
5249 return IsEquality || IsNegative || IsPositive;
5257 switch (OriginalIID) {
5258 case Intrinsic::vector_reduce_or:
5259 if (!IsValidOrUmaxCmp())
5261 AlternativeIID = Intrinsic::vector_reduce_umax;
5263 case Intrinsic::vector_reduce_umax:
5264 if (!IsValidOrUmaxCmp())
5266 AlternativeIID = Intrinsic::vector_reduce_or;
5268 case Intrinsic::vector_reduce_and:
5269 if (!IsValidAndUminCmp())
5271 AlternativeIID = Intrinsic::vector_reduce_umin;
5273 case Intrinsic::vector_reduce_umin:
5274 if (!IsValidAndUminCmp())
5276 AlternativeIID = Intrinsic::vector_reduce_and;
5289 if (ReductionOpc != Instruction::ICmp)
5300 <<
"\n OrigCost: " << OrigCost
5301 <<
" vs AltCost: " << AltCost <<
"\n");
5303 if (AltCost >= OrigCost)
5307 Type *ScalarTy = VecTy->getScalarType();
5310 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::get(ScalarTy, *CmpVal));
5312 replaceValue(
I, *NewCmp);
5326 unsigned Depth = 0) {
5327 constexpr unsigned MaxLocalDepth = 2;
5328 if (
Depth > MaxLocalDepth)
5331 auto NumSignBits = [&](
const Value *
X) {
5334 if (NumSignBits(V) == V->getType()->getScalarSizeInBits())
5339 return NumSignBits(
A) >= 2 && NumSignBits(
B) >= 2 &&
5350bool VectorCombine::foldReduceAddCmpZero(Instruction &
I) {
5360 if (!VecTy || VecTy->getNumElements() < 2)
5366 if (!IsNonNegative && !IsNonPositive)
5371 unsigned NumElts = VecTy->getNumElements();
5373 if (
Log2_32(NumElts) >= NumSignBits)
5376 ICmpInst::Predicate NewPred;
5378 case ICmpInst::ICMP_EQ:
5379 case ICmpInst::ICMP_ULE:
5380 case ICmpInst::ICMP_SLE:
5381 case ICmpInst::ICMP_SGE:
5382 NewPred = ICmpInst::ICMP_EQ;
5384 case ICmpInst::ICMP_NE:
5385 case ICmpInst::ICMP_UGT:
5386 case ICmpInst::ICMP_SGT:
5387 case ICmpInst::ICMP_SLT:
5388 NewPred = ICmpInst::ICMP_NE;
5398 if (!IsNonNegative &&
5399 (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE))
5401 if (!IsNonPositive &&
5402 (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE))
5404 if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE ||
5405 Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) &&
5406 Log2_32(NumElts) >= NumSignBits - 1)
5410 Instruction::Add, VecTy, std::nullopt,
CostKind);
5412 Instruction::Or, VecTy, std::nullopt,
CostKind);
5414 Intrinsic::umax, VecTy, FastMathFlags(),
CostKind);
5417 bool UseOr = OrCost.
isValid() && (!UmaxCost.
isValid() || OrCost <= UmaxCost);
5419 if (AltCost > OrigCost)
5425 Intrinsic::vector_reduce_umax, {VecTy}, {Vec});
5426 Worklist.pushValue(NewReduce);
5428 NewPred, NewReduce, ConstantInt::getNullValue(VecTy->getScalarType()));
5429 replaceValue(
I, *NewCmp);
5438 constexpr unsigned MaxVisited = 32;
5441 bool FoundReduction =
false;
5444 while (!WorkList.
empty()) {
5446 for (
User *U :
I->users()) {
5448 if (!UI || !Visited.
insert(UI).second)
5450 if (Visited.
size() > MaxVisited)
5456 switch (
II->getIntrinsicID()) {
5457 case Intrinsic::vector_reduce_add:
5458 case Intrinsic::vector_reduce_mul:
5459 case Intrinsic::vector_reduce_and:
5460 case Intrinsic::vector_reduce_or:
5461 case Intrinsic::vector_reduce_xor:
5462 case Intrinsic::vector_reduce_smin:
5463 case Intrinsic::vector_reduce_smax:
5464 case Intrinsic::vector_reduce_umin:
5465 case Intrinsic::vector_reduce_umax:
5466 FoundReduction =
true;
5479 return FoundReduction;
5492bool VectorCombine::foldSelectShuffle(Instruction &
I,
bool FromReduction) {
5497 if (!Op0 || !Op1 || Op0 == Op1 || !Op0->isBinaryOp() || !Op1->isBinaryOp() ||
5498 VT != Op0->getType())
5505 SmallPtrSet<Instruction *, 4> InputShuffles({SVI0A, SVI0B, SVI1A, SVI1B});
5507 if (!
I ||
I->getOperand(0)->getType() != VT)
5509 return any_of(
I->users(), [&](User *U) {
5510 return U != Op0 && U != Op1 &&
5511 !(isa<ShuffleVectorInst>(U) &&
5512 (InputShuffles.contains(cast<Instruction>(U)) ||
5513 isInstructionTriviallyDead(cast<Instruction>(U))));
5516 if (checkSVNonOpUses(SVI0A) || checkSVNonOpUses(SVI0B) ||
5517 checkSVNonOpUses(SVI1A) || checkSVNonOpUses(SVI1B))
5525 for (
auto *U :
I->users()) {
5527 if (!SV ||
SV->getType() != VT)
5529 if ((
SV->getOperand(0) != Op0 &&
SV->getOperand(0) != Op1) ||
5530 (
SV->getOperand(1) != Op0 &&
SV->getOperand(1) != Op1))
5537 if (!collectShuffles(Op0) || !collectShuffles(Op1))
5541 if (FromReduction && Shuffles.
size() > 1)
5546 if (!FromReduction) {
5547 for (
size_t Idx = 0,
E = Shuffles.
size(); Idx !=
E; ++Idx) {
5548 for (
auto *U : Shuffles[Idx]->
users()) {
5563 int MaxV1Elt = 0, MaxV2Elt = 0;
5564 unsigned NumElts = VT->getNumElements();
5565 for (ShuffleVectorInst *SVN : Shuffles) {
5566 SmallVector<int>
Mask;
5567 SVN->getShuffleMask(Mask);
5571 Value *SVOp0 = SVN->getOperand(0);
5572 Value *SVOp1 = SVN->getOperand(1);
5577 for (
int &Elem : Mask) {
5583 if (SVOp0 == Op1 && SVOp1 == Op0) {
5587 if (SVOp0 != Op0 || SVOp1 != Op1)
5593 SmallVector<int> ReconstructMask;
5594 for (
unsigned I = 0;
I <
Mask.size();
I++) {
5597 }
else if (Mask[
I] <
static_cast<int>(NumElts)) {
5598 MaxV1Elt = std::max(MaxV1Elt, Mask[
I]);
5599 auto It =
find_if(
V1, [&](
const std::pair<int, int> &
A) {
5600 return Mask[
I] ==
A.first;
5606 V1.emplace_back(Mask[
I],
V1.size());
5609 MaxV2Elt = std::max<int>(MaxV2Elt, Mask[
I] - NumElts);
5610 auto It =
find_if(V2, [&](
const std::pair<int, int> &
A) {
5611 return Mask[
I] -
static_cast<int>(NumElts) ==
A.first;
5625 sort(ReconstructMask);
5626 OrigReconstructMasks.
push_back(std::move(ReconstructMask));
5633 if (
V1.empty() || V2.
empty() ||
5634 (MaxV1Elt ==
static_cast<int>(
V1.size()) - 1 &&
5635 MaxV2Elt ==
static_cast<int>(V2.
size()) - 1))
5647 if (InputShuffles.contains(SSV))
5649 return SV->getMaskValue(M);
5657 std::pair<int, int>
Y) {
5658 int MXA = GetBaseMaskValue(
A,
X.first);
5659 int MYA = GetBaseMaskValue(
A,
Y.first);
5663 return SortBase(SVI0A,
A,
B);
5665 stable_sort(V2, [&](std::pair<int, int>
A, std::pair<int, int>
B) {
5666 return SortBase(SVI1A,
A,
B);
5671 for (
const auto &Mask : OrigReconstructMasks) {
5672 SmallVector<int> ReconstructMask;
5673 for (
int M : Mask) {
5675 auto It =
find_if(V, [M](
auto A) {
return A.second ==
M; });
5676 assert(It !=
V.end() &&
"Expected all entries in Mask");
5677 return std::distance(
V.begin(), It);
5681 else if (M <
static_cast<int>(NumElts)) {
5684 ReconstructMask.
push_back(NumElts + FindIndex(V2, M));
5687 ReconstructMasks.
push_back(std::move(ReconstructMask));
5692 SmallVector<int> V1A, V1B, V2A, V2B;
5693 for (
unsigned I = 0;
I <
V1.size();
I++) {
5697 for (
unsigned I = 0;
I < V2.
size();
I++) {
5698 V2A.
push_back(GetBaseMaskValue(SVI1A, V2[
I].first));
5699 V2B.
push_back(GetBaseMaskValue(SVI1B, V2[
I].first));
5701 while (V1A.
size() < NumElts) {
5705 while (V2A.
size() < NumElts) {
5724 unsigned ElementSize = VT->getElementType()->getPrimitiveSizeInBits();
5725 unsigned MaxVectorSize =
5727 unsigned MaxElementsInVector = MaxVectorSize / ElementSize;
5728 if (MaxElementsInVector == 0)
5737 std::set<SmallVector<int, 4>> UniqueShuffles;
5742 unsigned NumFullVectors =
Mask.size() / MaxElementsInVector;
5743 if (NumFullVectors < 2)
5744 return C + ShuffleCost;
5745 SmallVector<int, 4> SubShuffle(MaxElementsInVector);
5746 unsigned NumUniqueGroups = 0;
5747 unsigned NumGroups =
Mask.size() / MaxElementsInVector;
5750 for (
unsigned I = 0;
I < NumFullVectors; ++
I) {
5751 for (
unsigned J = 0; J < MaxElementsInVector; ++J)
5752 SubShuffle[J] = Mask[MaxElementsInVector *
I + J];
5753 if (UniqueShuffles.insert(SubShuffle).second)
5754 NumUniqueGroups += 1;
5756 return C + ShuffleCost * NumUniqueGroups / NumGroups;
5762 SmallVector<int, 16>
Mask;
5763 SV->getShuffleMask(Mask);
5764 return AddShuffleMaskAdjustedCost(
C, Mask);
5767 auto AllShufflesHaveSameOperands =
5768 [](SmallPtrSetImpl<Instruction *> &InputShuffles) {
5769 if (InputShuffles.size() < 2)
5771 ShuffleVectorInst *FirstSV =
5778 std::next(InputShuffles.begin()), InputShuffles.end(),
5779 [&](Instruction *
I) {
5780 ShuffleVectorInst *SV = dyn_cast<ShuffleVectorInst>(I);
5781 return SV && SV->getOperand(0) == In0 && SV->getOperand(1) == In1;
5790 CostBefore += std::accumulate(Shuffles.begin(), Shuffles.end(),
5792 if (AllShufflesHaveSameOperands(InputShuffles)) {
5793 UniqueShuffles.clear();
5794 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5797 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5803 FixedVectorType *Op0SmallVT =
5805 FixedVectorType *Op1SmallVT =
5810 UniqueShuffles.clear();
5811 CostAfter += std::accumulate(ReconstructMasks.begin(), ReconstructMasks.end(),
5813 std::set<SmallVector<int>> OutputShuffleMasks({V1A, V1B, V2A, V2B});
5815 std::accumulate(OutputShuffleMasks.begin(), OutputShuffleMasks.end(),
5818 LLVM_DEBUG(
dbgs() <<
"Found a binop select shuffle pattern: " <<
I <<
"\n");
5820 <<
" vs CostAfter: " << CostAfter <<
"\n");
5821 if (CostBefore < CostAfter ||
5832 if (InputShuffles.contains(SSV))
5834 return SV->getOperand(
Op);
5838 GetShuffleOperand(SVI0A, 1), V1A);
5841 GetShuffleOperand(SVI0B, 1), V1B);
5844 GetShuffleOperand(SVI1A, 1), V2A);
5847 GetShuffleOperand(SVI1B, 1), V2B);
5852 I->copyIRFlags(Op0,
true);
5857 I->copyIRFlags(Op1,
true);
5859 for (
int S = 0,
E = ReconstructMasks.size(); S !=
E; S++) {
5862 replaceValue(*Shuffles[S], *NSV,
false);
5865 Worklist.pushValue(NSV0A);
5866 Worklist.pushValue(NSV0B);
5867 Worklist.pushValue(NSV1A);
5868 Worklist.pushValue(NSV1B);
5878bool VectorCombine::shrinkType(Instruction &
I) {
5879 Value *ZExted, *OtherOperand;
5885 Value *ZExtOperand =
I.getOperand(
I.getOperand(0) == OtherOperand ? 1 : 0);
5889 unsigned BW = SmallTy->getElementType()->getPrimitiveSizeInBits();
5891 if (
I.getOpcode() == Instruction::LShr) {
5908 Instruction::ZExt, BigTy, SmallTy,
5909 TargetTransformInfo::CastContextHint::None,
CostKind);
5914 for (User *U : ZExtOperand->
users()) {
5921 ShrinkCost += ZExtCost;
5936 ShrinkCost += ZExtCost;
5943 Instruction::Trunc, SmallTy, BigTy,
5944 TargetTransformInfo::CastContextHint::None,
CostKind);
5949 if (ShrinkCost > CurrentCost)
5953 Value *Op0 = ZExted;
5956 if (
I.getOperand(0) == OtherOperand)
5961 NewBinOpI->copyIRFlags(&
I);
5962 NewBinOpI->copyMetadata(
I);
5965 replaceValue(
I, *NewZExtr);
5971bool VectorCombine::foldInsExtVectorToShuffle(Instruction &
I) {
5972 Value *DstVec, *SrcVec;
5983 if (!DstVecTy || !SrcVecTy ||
5989 if (InsIdx >= NumDstElts || ExtIdx >= NumSrcElts || NumDstElts == 1)
5996 bool NeedExpOrNarrow = NumSrcElts != NumDstElts;
5998 if (NeedDstSrcSwap) {
6000 Mask[InsIdx] = ExtIdx % NumDstElts;
6004 std::iota(
Mask.begin(),
Mask.end(), 0);
6005 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
6018 SmallVector<int> ExtToVecMask;
6019 if (!NeedExpOrNarrow) {
6024 nullptr, {DstVec, SrcVec});
6030 ExtToVecMask[ExtIdx % NumDstElts] = ExtIdx;
6033 DstVecTy, SrcVecTy,
CostKind, ExtToVecMask);
6037 if (!Ext->hasOneUse())
6040 LLVM_DEBUG(
dbgs() <<
"Found a insert/extract shuffle-like pair: " <<
I
6041 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6044 if (OldCost < NewCost)
6047 if (NeedExpOrNarrow) {
6048 if (!NeedDstSrcSwap)
6061 replaceValue(
I, *Shuf);
6085bool VectorCombine::foldDeinterleaveInterleavePair(Instruction &
I) {
6102 if (
U.getUser()->isDroppable())
6106 if (!Extract || Extract->getNumIndices() != 1)
6109 unsigned Index = *Extract->idx_begin();
6110 if (Index >= Factor || CurrentUses[Index])
6118 IntrinsicInst *Interleave =
nullptr;
6119 unsigned NumVisited = 0;
6123 return CB->arg_size();
6124 return Inst->getNumOperands();
6127 auto IsSupportedElementwise = [&](
Instruction *Inst) {
6133 if (
II->hasOperandBundles() ||
6136 }
else if (!
isa<BinaryOperator, UnaryOperator, CastInst, CmpInst,
6137 SelectInst, FreezeInst>(Inst)) {
6143 for (
unsigned Op = 0,
E = GetNumDataOperands(Inst);
Op !=
E; ++
Op) {
6146 OperandTy->getElementCount() != ResultTy->getElementCount())
6158 NumVisited += Factor;
6160 for (Use *&CurrentUse : CurrentUses) {
6161 Use *NextUse = CurrentUse->getUser()->getSingleUndroppableUse();
6167 CurrentUse = NextUse;
6172 II &&
II->getIntrinsicID() == ExpectedInterleaveIID) {
6173 if (
II->hasOperandBundles())
6176 for (
unsigned Index = 0;
Index != Factor; ++
Index)
6177 if (CurrentUses[Index]->getUser() !=
II ||
6178 CurrentUses[Index]->getOperandNo() != Index)
6186 if (!IsSupportedElementwise(FirstInst))
6189 unsigned ChainOperand = CurrentUses.front()->getOperandNo();
6190 bool MismatchedUse =
any_of(CurrentUses, [&](Use *U) {
6192 return Inst != FirstInst && (
U->getOperandNo() != ChainOperand ||
6193 !FirstInst->isSameOperationAs(
6199 auto GetSplatOrScalar = [](
Value *
V) {
6206 for (
unsigned Op = 0,
E = GetNumDataOperands(FirstInst);
Op !=
E; ++
Op) {
6207 if (
Op == ChainOperand)
6210 Value *CommonValue = GetSplatOrScalar(FirstInst->getOperand(
Op));
6211 if (!CommonValue ||
any_of(CurrentUses, [&](Use *U) {
6213 return Inst != FirstInst &&
6227 ElementCount WideEC =
6230 auto CreateWideInstruction = [&](
Instruction *NarrowInst,
6233 assert(IsSupportedElementwise(NarrowInst) &&
6234 "Expected supported elementwise");
6238 return Builder.
CreateCast(Cast->getOpcode(), NewOperands[0],
6241 return Builder.
CreateCmp(
Cmp->getPredicate(), NewOperands[0],
6245 NewOperands[0], NewOperands[1], NewOperands[2],
"",
6257 for (
const ElementwiseStep &Step : Steps) {
6259 unsigned ChainOperand = Step.front()->getOperandNo();
6264 unsigned NumOperands = GetNumDataOperands(NarrowInst);
6265 SmallVector<Value *, 4> NewOperands;
6266 NewOperands.
reserve(NumOperands);
6268 for (
unsigned Op = 0;
Op != NumOperands; ++
Op) {
6271 if (
Op == ChainOperand)
6272 Operand = WideValue;
6278 auto *WideResultTy =
6281 CreateWideInstruction(NarrowInst, NewOperands, WideResultTy);
6290 WideValue = NewValue;
6294 replaceValue(*Interleave, *WideValue);
6302bool VectorCombine::foldInterleaveIntrinsics(Instruction &
I) {
6303 const APInt *SplatVal0, *SplatVal1;
6313 auto *ExtVTy = VectorType::getExtendedElementVectorType(VTy);
6314 unsigned Width = VTy->getElementType()->getIntegerBitWidth();
6323 LLVM_DEBUG(
dbgs() <<
"VC: The cost to cast from " << *ExtVTy <<
" to "
6324 << *
I.getType() <<
" is too high.\n");
6328 APInt NewSplatVal = SplatVal1->
zext(Width * 2);
6329 NewSplatVal <<= Width;
6330 NewSplatVal |= SplatVal0->
zext(Width * 2);
6332 ExtVTy->getElementCount(), ConstantInt::get(
F.getContext(), NewSplatVal));
6367bool VectorCombine::foldDeinterleaveIntrinsics(Instruction &
I) {
6368 if (foldDeinterleaveInterleavePair(
I))
6372 if (
DL->isBigEndian())
6375 using namespace PatternMatch;
6376 Value *DeinterleavedVal;
6387 unsigned HalfElementWidth = ElementWidth / 2;
6391 std::array<ExtractValueInst *, 2> OrigFields{};
6392 for (User *Usr :
I.users()) {
6395 if (!
E ||
E->getNumIndices() != 1)
6397 unsigned Idx = *
E->idx_begin();
6399 if (Idx >= 2 || OrigFields[Idx] || !
E->hasNUses(2))
6401 OrigFields[Idx] =
E;
6405 SmallVector<Instruction *, 2> MergeInsts;
6406 for (
auto *FieldUsr : OrigFields[0]->
users()) {
6414 auto MatchMerge = [&](void) ->
bool {
6417 return match(MergeInsts[0],
6421 match(MergeInsts[1],
6426 if (!MatchMerge()) {
6427 std::swap(MergeInsts[0], MergeInsts[1]);
6442 auto *NewFieldTy = VecTy->getWithNewBitWidth(HalfElementWidth);
6452 if (OldCost <= NewCost || !NewCost.
isValid()) {
6454 dbgs() <<
"VC: New deinterleave2 sequence cost (" << NewCost <<
")"
6455 <<
" is higher than that of the old one (" << OldCost <<
")\n");
6463 Intrinsic::vector_deinterleave2, {NewVecTy}, {NewVecCast});
6464 for (
auto [Idx, MergeInst] :
enumerate(MergeInsts)) {
6466 NewField = Builder.
CreateBitCast(NewField, MergeInst->getType());
6467 replaceValue(*MergeInst, *NewField);
6473bool VectorCombine::foldBitcastOfVPLoad(Instruction &
I) {
6474 const DataLayout &
DL =
I.getDataLayout();
6489 DL.getValueOrABITypeAlignment(
II->getPointerAlignment(), OrigVecTy);
6490 ElementCount OrigVecCnt = OrigVecTy->getElementCount();
6492 ElementCount NewVecCnt = NewVecTy->getElementCount();
6504 II->getMemoryPointerParam(),
false,
6510 {Intrinsic::vp_load, NewVecTy,
II->getMemoryPointerParam(),
false,
6514 <<
" NewCost=" << NewCost <<
"\n");
6515 if (NewCost > OldCost || !NewCost.
isValid())
6523 NewVecTy, Intrinsic::vp_load,
6524 {
II->getMemoryPointerParam(), NewMask, NewEVL});
6527 0, AttrBuilder(
II->getContext()).addAlignmentAttr(OrigAlign));
6528 replaceValue(*Cast, *NewVP);
6538bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &
I) {
6542 Type *Ty =
X->getType();
6543 Type *VecTy =
I.getOperand(0)->getType();
6557 if (CanUseBswap || CanUseFshl) {
6568 IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
6569 IntrinsicCostAttributes ICABFshl(Intrinsic::fshl, Ty, {
X,
X, HalfBW},
6571 IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
6576 if (!InnerCall->hasOneUse())
6579 else if (!InnerBitCast->hasOneUse())
6582 <<
"\n OldCost: " << OldCost
6583 <<
" vs NewCost: " << NewCost <<
"\n");
6584 if (NewCost.isValid() && NewCost < OldCost) {
6590 Worklist.pushValue(
Swap);
6592 replaceValue(
I, *BRev);
6601 Type *Ty =
I.getType();
6603 TypeSize ElementSize =
DL->getTypeStoreSize(Ty);
6606 Type *NewVecTy = VectorType::get(I8Ty, NewVecCnt);
6619 IntrinsicCostAttributes ICANew(Intrinsic::bitreverse, NewVecTy, {NewVecTy});
6622 InstructionCost NewCost = CastToVecCost + NewIntrinsicCost + CastToOrigCost;
6623 if (!InnerII->hasOneUse())
6626 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6628 if (!NewCost.
isValid() || NewCost >= OldCost)
6636 replaceValue(
I, *CastToOrig);
6646 unsigned RawNumElements = MaxIdx + 1u;
6650 return RawNumElements;
6654 return RawNumElements;
6659 return RawNumElements;
6664 if (ElemsPerReg == 0 || RawNumElements <= ElemsPerReg)
6665 return RawNumElements;
6667 return alignTo(RawNumElements, ElemsPerReg);
6671bool VectorCombine::shrinkLoadForShuffles(Instruction &
I) {
6673 if (!OldLoad || !OldLoad->isSimple())
6680 unsigned const OldNumElements = OldLoadTy->getNumElements();
6686 using IndexRange = std::pair<int, int>;
6687 auto GetIndexRangeInShuffles = [&]() -> std::optional<IndexRange> {
6688 IndexRange OutputRange = IndexRange(OldNumElements, -1);
6689 for (llvm::Use &Use :
I.uses()) {
6691 User *Shuffle =
Use.getUser();
6696 return std::nullopt;
6703 for (
int Index : Mask) {
6704 if (Index >= 0 && Index <
static_cast<int>(OldNumElements)) {
6705 OutputRange.first = std::min(Index, OutputRange.first);
6706 OutputRange.second = std::max(Index, OutputRange.second);
6711 if (OutputRange.second < OutputRange.first)
6712 return std::nullopt;
6718 if (std::optional<IndexRange> Indices = GetIndexRangeInShuffles()) {
6719 unsigned const NewNumElements =
6724 if (NewNumElements < OldNumElements) {
6729 Type *ElemTy = OldLoadTy->getElementType();
6731 Value *PtrOp = OldLoad->getPointerOperand();
6734 Instruction::Load, OldLoad->getType(), OldLoad->getAlign(),
6735 OldLoad->getPointerAddressSpace(),
CostKind);
6738 OldLoad->getPointerAddressSpace(),
CostKind);
6740 using UseEntry = std::pair<ShuffleVectorInst *, std::vector<int>>;
6742 unsigned const MaxIndex = NewNumElements * 2u;
6744 for (llvm::Use &Use :
I.uses()) {
6751 ArrayRef<int> OldMask = Shuffle->getShuffleMask();
6757 for (
int Index : OldMask) {
6758 if (Index >=
static_cast<int>(MaxIndex))
6772 dbgs() <<
"Found a load used only by shufflevector instructions: "
6773 <<
I <<
"\n OldCost: " << OldCost
6774 <<
" vs NewCost: " << NewCost <<
"\n");
6776 if (OldCost < NewCost || !NewCost.
isValid())
6782 NewLoad->copyMetadata(
I);
6785 for (UseEntry &Use : NewUses) {
6786 ShuffleVectorInst *Shuffle =
Use.first;
6787 std::vector<int> &NewMask =
Use.second;
6794 replaceValue(*Shuffle, *NewShuffle,
false);
6807bool VectorCombine::shrinkPhiOfShuffles(Instruction &
I) {
6809 if (!Phi ||
Phi->getNumIncomingValues() != 2u)
6813 ArrayRef<int> Mask0;
6814 ArrayRef<int> Mask1;
6827 auto const InputNumElements = InputVT->getNumElements();
6829 if (InputNumElements >= ResultVT->getNumElements())
6834 SmallVector<int, 16> NewMask;
6837 for (
auto [
M0,
M1] :
zip(Mask0, Mask1)) {
6838 if (
M0 >= 0 &&
M1 >= 0)
6840 else if (
M0 == -1 &&
M1 == -1)
6853 int MaskOffset = NewMask[0
u];
6854 unsigned Index = (InputNumElements + MaskOffset) % InputNumElements;
6857 for (
unsigned I = 0u;
I < InputNumElements; ++
I) {
6871 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6874 if (NewCost > OldCost)
6886 auto *NewPhi = Builder.
CreatePHI(NewShuf0->getType(), 2u);
6888 NewPhi->addIncoming(
Op,
Phi->getIncomingBlock(1u));
6894 replaceValue(*Phi, *NewShuf1);
6900bool VectorCombine::run() {
6914 auto Opcode =
I.getOpcode();
6922 if (IsFixedVectorType) {
6924 case Instruction::InsertElement:
6925 if (vectorizeLoadInsert(
I))
6928 case Instruction::ShuffleVector:
6929 if (widenSubvectorLoad(
I))
6940 if (scalarizeOpOrCmp(
I))
6942 if (scalarizeLoad(
I))
6944 if (scalarizeExtExtract(
I))
6946 if (foldInterleaveIntrinsics(
I))
6948 if (foldBitcastOfVPLoad(
I))
6952 if (foldDeinterleaveIntrinsics(
I))
6955 if (Opcode == Instruction::Store)
6956 if (foldInsertElementsToStores(
I))
6960 if (TryEarlyFoldsOnly)
6963 if (Opcode == Instruction::Call)
6964 if (foldBitOrderReverseAndSwap(
I))
6966 if (Opcode == Instruction::BitCast)
6967 if (foldBitOrderReverseAndSwap(
I))
6974 if (IsFixedVectorType) {
6976 case Instruction::InsertElement:
6977 if (foldInsExtFNeg(
I))
6979 if (foldInsExtBinop(
I))
6981 if (foldInsExtVectorToShuffle(
I))
6984 case Instruction::ShuffleVector:
6985 if (foldPermuteOfBinops(
I))
6987 if (foldShuffleOfBinops(
I))
6989 if (foldShuffleOfSelects(
I))
6991 if (foldShuffleOfCastops(
I))
6993 if (foldShuffleOfShuffles(
I))
6995 if (foldPermuteOfIntrinsic(
I))
6997 if (foldShufflesOfLengthChangingShuffles(
I))
6999 if (foldShuffleOfIntrinsics(
I))
7001 if (foldSelectShuffle(
I))
7003 if (foldShuffleToIdentity(
I))
7006 case Instruction::Load:
7007 if (shrinkLoadForShuffles(
I))
7010 case Instruction::BitCast:
7011 if (foldBitcastShuffle(
I))
7013 if (foldSelectsFromBitcast(
I))
7016 case Instruction::And:
7017 case Instruction::Or:
7018 case Instruction::Xor:
7019 if (foldBitOpOfCastops(
I))
7021 if (foldBitOpOfCastConstant(
I))
7024 case Instruction::PHI:
7025 if (shrinkPhiOfShuffles(
I))
7035 case Instruction::Call:
7036 if (foldShuffleFromReductions(
I))
7038 if (foldCastFromReductions(
I))
7041 case Instruction::ExtractElement:
7042 if (foldShuffleChainsToReduce(
I))
7045 case Instruction::ICmp:
7046 if (foldSignBitReductionCmp(
I))
7048 if (foldICmpEqZeroVectorReduce(
I))
7050 if (foldReductionZeroTest(
I))
7052 if (foldEquivalentReductionCmp(
I))
7054 if (foldReduceAddCmpZero(
I))
7057 case Instruction::FCmp:
7058 if (foldExtractExtract(
I))
7061 case Instruction::Or:
7062 if (foldConcatOfBoolMasks(
I))
7067 if (foldExtractExtract(
I))
7069 if (foldExtractedCmps(
I))
7071 if (foldBinopOfReductions(
I))
7080 bool MadeChange =
false;
7081 for (BasicBlock &BB :
F) {
7093 if (!
I->isDebugOrPseudoInst())
7094 MadeChange |= FoldInst(*
I);
7101 while (!Worklist.isEmpty()) {
7111 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