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))
1341 Scalar = Builder.
CreateCmp(CI->getPredicate(), ScalarOps[0], ScalarOps[1]);
1347 Scalar->setName(
I.getName() +
".scalar");
1352 ScalarInst->copyIRFlags(&
I);
1355 replaceValue(
I, *Insert);
1362bool VectorCombine::foldExtractedCmps(Instruction &
I) {
1367 if (!BI || !
I.getType()->isIntegerTy(1))
1372 Value *
B0 =
I.getOperand(0), *
B1 =
I.getOperand(1);
1375 CmpPredicate
P0,
P1;
1394 ExtractElementInst *ConvertToShuf = getShuffleExtract(Ext0, Ext1,
CostKind);
1397 assert((ConvertToShuf == Ext0 || ConvertToShuf == Ext1) &&
1398 "Unknown ExtractElementInst");
1403 unsigned CmpOpcode =
1409 if (Index0 >= VecTy->getNumElements() || Index1 >= VecTy->getNumElements())
1421 Ext0Cost + Ext1Cost + CmpCost * 2 +
1427 int CheapIndex = ConvertToShuf == Ext0 ? Index1 : Index0;
1428 int ExpensiveIndex = ConvertToShuf == Ext0 ? Index0 : Index1;
1433 ShufMask[CheapIndex] = ExpensiveIndex;
1438 NewCost += Ext0->
hasOneUse() ? 0 : Ext0Cost;
1439 NewCost += Ext1->
hasOneUse() ? 0 : Ext1Cost;
1444 if (OldCost < NewCost || !NewCost.
isValid())
1454 Value *
LHS = ConvertToShuf == Ext0 ? Shuf : VCmp;
1455 Value *
RHS = ConvertToShuf == Ext0 ? VCmp : Shuf;
1458 replaceValue(
I, *NewExt);
1485bool VectorCombine::foldSelectsFromBitcast(Instruction &
I) {
1492 if (!SrcVecTy || !DstVecTy)
1502 if (SrcEltBits != 32 && SrcEltBits != 64)
1505 if (!DstEltTy->
isIntegerTy() || DstEltBits >= SrcEltBits)
1522 if (!ScalarSelCost.
isValid() || ScalarSelCost == 0)
1525 unsigned MinSelects = (VecSelCost.
getValue() / ScalarSelCost.
getValue()) + 1;
1528 if (!BC->hasNUsesOrMore(MinSelects))
1533 DenseMap<Value *, SmallVector<SelectInst *, 8>> CondToSelects;
1535 for (User *U : BC->users()) {
1540 for (User *ExtUser : Ext->users()) {
1544 Cond->getType()->isIntegerTy(1))
1549 if (CondToSelects.
empty())
1552 bool MadeChange =
false;
1553 Value *SrcVec = BC->getOperand(0);
1556 for (
auto [
Cond, Selects] : CondToSelects) {
1558 if (Selects.size() < MinSelects) {
1559 LLVM_DEBUG(
dbgs() <<
"VectorCombine: foldSelectsFromBitcast not "
1560 <<
"profitable (VecCost=" << VecSelCost
1561 <<
", ScalarCost=" << ScalarSelCost
1562 <<
", NumSelects=" << Selects.size() <<
")\n");
1567 auto InsertPt = std::next(BC->getIterator());
1571 InsertPt = std::next(CondInst->getIterator());
1579 for (SelectInst *Sel : Selects) {
1581 Value *Idx = Ext->getIndexOperand();
1585 replaceValue(*Sel, *NewExt);
1590 <<
" selects into vector select\n");
1604 unsigned ReductionOpc =
1610 CostBeforeReduction =
1611 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, ExtType,
1613 CostAfterReduction =
1614 TTI.getExtendedReductionCost(ReductionOpc, IsUnsigned,
II.getType(),
1618 if (RedOp &&
II.getIntrinsicID() == Intrinsic::vector_reduce_add &&
1624 (Op0->
getOpcode() == RedOp->getOpcode() || Op0 == Op1)) {
1631 TTI.getCastInstrCost(Op0->
getOpcode(), MulType, ExtType,
1634 TTI.getArithmeticInstrCost(Instruction::Mul, MulType,
CostKind);
1636 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, MulType,
1639 CostBeforeReduction = ExtCost * 2 + MulCost + Ext2Cost;
1640 CostAfterReduction =
TTI.getMulAccReductionCost(
1641 IsUnsigned, ReductionOpc,
II.getType(), ExtType,
CostKind);
1644 CostAfterReduction =
TTI.getArithmeticReductionCost(ReductionOpc, VecRedTy,
1648bool VectorCombine::foldBinopOfReductions(Instruction &
I) {
1651 if (BinOpOpc == Instruction::Sub)
1652 ReductionIID = Intrinsic::vector_reduce_add;
1656 if (ReductionIID == Intrinsic::vector_reduce_fadd ||
1657 ReductionIID == Intrinsic::vector_reduce_fmul)
1660 auto checkIntrinsicAndGetItsArgument = [](
Value *
V,
1665 if (
II->getIntrinsicID() == IID &&
II->hasOneUse())
1666 return II->getArgOperand(0);
1670 Value *
V0 = checkIntrinsicAndGetItsArgument(
I.getOperand(0), ReductionIID);
1673 Value *
V1 = checkIntrinsicAndGetItsArgument(
I.getOperand(1), ReductionIID);
1678 if (
V1->getType() != VTy)
1682 unsigned ReductionOpc =
1695 CostOfRedOperand0 + CostOfRedOperand1 +
1698 if (NewCost >= OldCost || !NewCost.
isValid())
1702 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
1705 if (BinOpOpc == Instruction::Or)
1712 replaceValue(
I, *Rdx);
1721 unsigned NumScanned = 0;
1722 if (std::any_of(Begin, End, [&](
const Instruction &Instr) {
1736class ScalarizationResult {
1737 enum class StatusTy { Unsafe, Safe, SafeWithFreeze };
1742 ScalarizationResult(StatusTy Status,
Value *ToFreeze =
nullptr)
1743 : Status(Status), ToFreeze(ToFreeze) {}
1746 ScalarizationResult(
const ScalarizationResult &
Other) =
default;
1747 ~ScalarizationResult() {
1748 assert(!ToFreeze &&
"freeze() not called with ToFreeze being set");
1751 static ScalarizationResult unsafe() {
return {StatusTy::Unsafe}; }
1752 static ScalarizationResult safe() {
return {StatusTy::Safe}; }
1753 static ScalarizationResult safeWithFreeze(
Value *ToFreeze) {
1754 return {StatusTy::SafeWithFreeze, ToFreeze};
1758 bool isSafe()
const {
return Status == StatusTy::Safe; }
1760 bool isUnsafe()
const {
return Status == StatusTy::Unsafe; }
1763 bool isSafeWithFreeze()
const {
return Status == StatusTy::SafeWithFreeze; }
1768 Status = StatusTy::Unsafe;
1772 void freeze(IRBuilderBase &Builder, Instruction &UserI) {
1773 assert(isSafeWithFreeze() &&
1774 "should only be used when freezing is required");
1776 "UserI must be a user of ToFreeze");
1777 IRBuilder<>::InsertPointGuard Guard(Builder);
1782 if (
U.get() == ToFreeze)
1797 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1801 if (
C->getValue().ult(NumElements))
1802 return ScalarizationResult::safe();
1803 return ScalarizationResult::unsafe();
1808 return ScalarizationResult::unsafe();
1810 APInt Zero(IntWidth, 0);
1811 APInt MaxElts(IntWidth, NumElements);
1818 return ScalarizationResult::safe();
1819 return ScalarizationResult::unsafe();
1832 if (ValidIndices.
contains(IdxRange))
1833 return ScalarizationResult::safeWithFreeze(IdxBase);
1834 return ScalarizationResult::unsafe();
1854 unsigned GEPBits = GEPIndexTy->getBitWidth();
1855 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1857 uint64_t MaxLane = NumElements - 1;
1859 if (
C->getValue().uge(NumElements))
1861 MaxLane =
C->getZExtValue();
1865 if (!
DL.typeSizeEqualsStoreSize(
ElemTy))
1885 unsigned WideBits = std::max(GEPBits, 128u);
1886 APInt MaxLaneValue(WideBits, MaxLane);
1887 APInt ByteOffset = MaxLaneValue;
1892 if (ByteOffset.
ugt(MaxGEPOffset))
1905 if (SrcBits >= DstBits)
1908 return Builder.CreateZExt(Idx, GEPIndexTy, Idx->
getName() +
".gepidx");
1920 C->getZExtValue() *
DL.getTypeStoreSize(ScalarType));
1957bool VectorCombine::foldInsertElementsToStores(Instruction &
I) {
1972 if (!
Insert->hasOneUse())
1976 InsertElements.
push_back({InsertVal, Idx});
1980 if (InsertElements.
empty())
1985 std::reverse(InsertElements.
begin(), InsertElements.
end());
1994 if (InsertElements.
size() == FVT->getNumElements()) {
1995 Value *FirstVal = InsertElements.
front().first;
1996 if (
all_of(InsertElements,
1997 [FirstVal](
const auto &Elt) {
return Elt.first == FirstVal; }))
2001 Value *SrcAddr =
Load->getPointerOperand()->stripPointerCasts();
2006 if (!
Load->isSimple() ||
Load->getParent() !=
SI->getParent() ||
2007 !
DL->typeSizeEqualsStoreSize(
Load->getType()->getScalarType()) ||
2008 SrcAddr !=
SI->getPointerOperand()->stripPointerCasts())
2018 for (
auto [InsertVal, Idx] : InsertElements) {
2019 auto ScalarizableIdx =
2021 if (ScalarizableIdx.isUnsafe())
2027 ScalarizableIdx.discard();
2033 ScalarizableIdx.discard();
2037 Instruction::Store,
SI->getValueOperand()->getType(),
SI->getAlign(),
2040 if (
Load->hasOneUse())
2045 for (
auto [InsertVal, Idx] : InsertElements) {
2048 Index = CIdx->getZExtValue();
2059 for (
auto [InsertVal, Idx] : InsertElements) {
2062 const Value *GEPIndices[] = {ConstantInt::get(Idx->
getType(), 0), Idx};
2067 for (
auto [InsertVal, Idx] : InsertElements) {
2069 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2077 LLVM_DEBUG(
dbgs() <<
"Found an insert-elements vector store scalarization "
2080 <<
" NumInserts: " << InsertElements.size() <<
"\n"
2081 <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2084 if (OldCost <= NewCost)
2087 for (
auto [InsertVal, Idx] : InsertElements) {
2088 auto ScalarizableIdx =
2090 assert(!ScalarizableIdx.isUnsafe() &&
"already checked above");
2092 if (ScalarizableIdx.isSafeWithFreeze())
2097 StoreInst *LastStore =
nullptr;
2098 for (
auto [InsertVal, Idx] : InsertElements) {
2099 auto ScalarizableIdx =
2101 if (ScalarizableIdx.isUnsafe())
2104 IntegerType *GEPIndexTy =
2109 SI->getValueOperand()->getType(),
SI->getPointerOperand(),
2110 {ConstantInt::get(GEPIdx->getType(), 0), GEPIdx});
2117 LastStore->
setMetadata(LLVMContext::MD_invariant_group,
nullptr);
2119 std::max(
SI->getAlign(),
Load->getAlign()), InsertVal->
getType(), Idx,
2124 replaceValue(
I, *LastStore);
2131bool VectorCombine::scalarizeLoad(Instruction &
I) {
2141 if (!LI->isSimple() || !
DL->typeSizeEqualsStoreSize(VecTy->getScalarType()))
2144 bool AllExtracts =
true;
2145 bool AllBitcasts =
true;
2147 unsigned NumInstChecked = 0;
2152 for (User *U : LI->users()) {
2154 if (!UI || UI->getParent() != LI->getParent())
2159 if (UI->use_empty())
2163 AllExtracts =
false;
2165 AllBitcasts =
false;
2169 for (Instruction &
I :
2170 make_range(std::next(LI->getIterator()), UI->getIterator())) {
2177 LastCheckedInst = UI;
2182 return scalarizeLoadExtract(LI, VecTy, Ptr);
2184 return scalarizeLoadBitcast(LI, VecTy, Ptr);
2189bool VectorCombine::scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
2194 DenseMap<ExtractElementInst *, ScalarizationResult> NeedFreeze;
2195 DenseMap<ExtractElementInst *, IntegerType *> GEPIndexInfos;
2198 for (
auto &Pair : NeedFreeze)
2199 Pair.second.discard();
2207 for (User *U : LI->
users()) {
2212 if (ScalarIdx.isUnsafe())
2218 ScalarIdx.discard();
2224 if (ScalarIdx.isSafeWithFreeze()) {
2225 NeedFreeze.try_emplace(UI, ScalarIdx);
2226 ScalarIdx.discard();
2232 Index ?
Index->getZExtValue() : -1);
2238 if (!Index && UI->getIndexOperand()->getType()->getIntegerBitWidth() <
2241 Instruction::ZExt, GEPIndex, UI->getIndexOperand()->getType(),
2245 LLVM_DEBUG(
dbgs() <<
"Found all extractions of a vector load: " << *LI
2246 <<
"\n LoadExtractCost: " << OriginalCost
2247 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2249 if (ScalarizedCost > OriginalCost)
2251 if (ScalarizedCost == OriginalCost && !LI->
hasOneUse())
2258 Type *ElemType = VecTy->getElementType();
2261 for (User *U : LI->
users()) {
2263 Value *Idx = EI->getIndexOperand();
2266 if (
auto It = NeedFreeze.find(EI); It != NeedFreeze.end())
2270 auto It = GEPIndexInfos.
find(EI);
2272 "Missing scalarized GEP index information");
2275 VecTy, Ptr, {ConstantInt::get(GEPIdx->
getType(), 0), GEPIdx});
2277 Builder.
CreateLoad(ElemType,
GEP, EI->getName() +
".scalar"));
2279 Align ScalarOpAlignment =
2281 NewLoad->setAlignment(ScalarOpAlignment);
2284 size_t Offset = ConstIdx->getZExtValue() *
DL->getTypeStoreSize(ElemType);
2289 replaceValue(*EI, *NewLoad,
false);
2292 FailureGuard.release();
2297bool VectorCombine::scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
2306 Type *TargetScalarType =
nullptr;
2307 unsigned VecBitWidth =
DL->getTypeSizeInBits(VecTy);
2309 for (User *U : LI->
users()) {
2312 Type *DestTy = BC->getDestTy();
2316 unsigned DestBitWidth =
DL->getTypeSizeInBits(DestTy);
2317 if (DestBitWidth != VecBitWidth)
2321 if (!TargetScalarType)
2322 TargetScalarType = DestTy;
2323 else if (TargetScalarType != DestTy)
2331 if (!TargetScalarType)
2339 LLVM_DEBUG(
dbgs() <<
"Found vector load feeding only bitcasts: " << *LI
2340 <<
"\n OriginalCost: " << OriginalCost
2341 <<
" vs ScalarizedCost: " << ScalarizedCost <<
"\n");
2343 if (ScalarizedCost >= OriginalCost)
2354 ScalarLoad->copyMetadata(*LI);
2357 for (User *U : LI->
users()) {
2359 replaceValue(*BC, *ScalarLoad,
false);
2365bool VectorCombine::scalarizeExtExtract(Instruction &
I) {
2380 Type *ScalarDstTy = DstTy->getElementType();
2381 if (
DL->getTypeSizeInBits(SrcTy) !=
DL->getTypeSizeInBits(ScalarDstTy))
2387 unsigned ExtCnt = 0;
2388 bool ExtLane0 =
false;
2389 for (User *U : Ext->users()) {
2395 if (Idx >= SrcTy->getNumElements())
2407 Instruction::And, ScalarDstTy,
CostKind,
2410 (ExtCnt - ExtLane0) *
2412 Instruction::LShr, ScalarDstTy,
CostKind,
2415 if (ScalarCost > VectorCost)
2418 Value *ScalarV = Ext->getOperand(0);
2425 SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
2426 bool AllExtractsTriggerUB =
true;
2427 ExtractElementInst *LastExtract =
nullptr;
2429 for (User *U : Ext->users()) {
2432 AllExtractsTriggerUB =
false;
2436 if (!LastExtract || LastExtract->
comesBefore(Extract))
2437 LastExtract = Extract;
2439 if (ExtractedLanes.
size() != DstTy->getNumElements() ||
2440 !AllExtractsTriggerUB ||
2448 uint64_t SrcEltSizeInBits =
DL->getTypeSizeInBits(SrcTy->getElementType());
2449 uint64_t TotalBits =
DL->getTypeSizeInBits(SrcTy);
2452 Value *
Mask = ConstantInt::get(PackedTy, EltBitMask);
2453 for (User *U : Ext->users()) {
2459 ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits)
2460 : (Idx * SrcEltSizeInBits);
2463 U->replaceAllUsesWith(
And);
2471bool VectorCombine::foldConcatOfBoolMasks(Instruction &
I) {
2472 Type *Ty =
I.getType();
2477 if (
DL->isBigEndian())
2504 if (ShAmtX > ShAmtY) {
2512 uint64_t ShAmtDiff = ShAmtY - ShAmtX;
2513 unsigned NumSHL = (ShAmtX > 0) + (ShAmtY > 0);
2518 MaskTy->getNumElements() != ShAmtDiff ||
2519 MaskTy->getNumElements() > (
BitWidth / 2))
2524 Type::getIntNTy(Ty->
getContext(), ConcatTy->getNumElements());
2525 auto *MaskIntTy = Type::getIntNTy(Ty->
getContext(), ShAmtDiff);
2528 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2545 if (Ty != ConcatIntTy)
2551 LLVM_DEBUG(
dbgs() <<
"Found a concatenation of bitcasted bool masks: " <<
I
2552 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2555 if (NewCost > OldCost)
2565 if (Ty != ConcatIntTy) {
2575 replaceValue(
I, *Result);
2581bool VectorCombine::foldPermuteOfBinops(Instruction &
I) {
2582 BinaryOperator *BinOp;
2583 ArrayRef<int> OuterMask;
2591 Value *Op00, *Op01, *Op10, *Op11;
2592 ArrayRef<int> Mask0, Mask1;
2597 if (!Match0 && !Match1)
2610 if (!ShuffleDstTy || !BinOpTy || !Op0Ty || !Op1Ty)
2613 unsigned NumSrcElts = BinOpTy->getNumElements();
2618 any_of(OuterMask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
2622 SmallVector<int> NewMask0, NewMask1;
2623 for (
int M : OuterMask) {
2624 if (M < 0 || M >= (
int)NumSrcElts) {
2628 NewMask0.
push_back(Match0 ? Mask0[M] : M);
2629 NewMask1.
push_back(Match1 ? Mask1[M] : M);
2633 unsigned NumOpElts = Op0Ty->getNumElements();
2634 bool IsIdentity0 = ShuffleDstTy == Op0Ty &&
2635 all_of(NewMask0, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2637 bool IsIdentity1 = ShuffleDstTy == Op1Ty &&
2638 all_of(NewMask1, [NumOpElts](
int M) {
return M < (int)NumOpElts; }) &&
2647 ShuffleDstTy, BinOpTy,
CostKind, OuterMask,
2648 0,
nullptr, {BinOp}, &
I);
2650 NewCost += BinOpCost;
2656 OldCost += Shuf0Cost;
2658 NewCost += Shuf0Cost;
2664 OldCost += Shuf1Cost;
2666 NewCost += Shuf1Cost;
2674 Op0Ty,
CostKind, NewMask0, 0,
nullptr, {Op00, Op01});
2678 Op1Ty,
CostKind, NewMask1, 0,
nullptr, {Op10, Op11});
2680 LLVM_DEBUG(
dbgs() <<
"Found a shuffle feeding a shuffled binop: " <<
I
2681 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2685 if (NewCost > OldCost)
2696 NewInst->copyIRFlags(BinOp);
2700 replaceValue(
I, *NewBO);
2706bool VectorCombine::foldShuffleOfBinops(Instruction &
I) {
2707 ArrayRef<int> OldMask;
2714 if (
LHS->getOpcode() !=
RHS->getOpcode())
2718 bool IsCommutative =
false;
2727 IsCommutative = BinaryOperator::isCommutative(BO->getOpcode());
2738 if (!ShuffleDstTy || !BinResTy || !BinOpTy ||
X->getType() !=
Z->getType())
2741 bool SameBinOp =
LHS ==
RHS;
2742 unsigned NumSrcElts = BinOpTy->getNumElements();
2745 if (IsCommutative &&
X != Z &&
Y != W && (
X == W ||
Y == Z))
2748 auto ConvertToUnary = [NumSrcElts](
int &
M) {
2749 if (M >= (
int)NumSrcElts)
2753 SmallVector<int> NewMask0(OldMask);
2762 SmallVector<int> NewMask1(OldMask);
2781 ShuffleDstTy, BinResTy,
CostKind, OldMask, 0,
2791 ArrayRef<int> InnerMask;
2793 m_Mask(InnerMask)))) &&
2796 [NumSrcElts](
int M) {
return M < (int)NumSrcElts; })) {
2808 bool ReducedInstCount =
false;
2809 ReducedInstCount |= MergeInner(
X, 0, NewMask0,
CostKind);
2810 ReducedInstCount |= MergeInner(
Y, 0, NewMask1,
CostKind);
2811 ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0,
CostKind);
2812 ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1,
CostKind);
2813 bool SingleSrcBinOp = (
X ==
Y) && (Z == W) && (NewMask0 == NewMask1);
2825 I.getType()->getScalarType()->isIntegerTy(1) &&
2829 auto *ShuffleCmpTy =
2832 SK0, ShuffleCmpTy, BinOpTy,
CostKind, NewMask0, 0,
nullptr, {
X,
Z});
2833 if (!SingleSrcBinOp)
2835 NewMask1, 0,
nullptr, {
Y,
W});
2843 PredLHS,
CostKind, Op0Info, Op1Info);
2853 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2860 if (ReducedInstCount ? (NewCost > OldCost) : (NewCost >= OldCost))
2869 : Builder.
CreateCmp(PredLHS, Shuf0, Shuf1);
2873 NewInst->copyIRFlags(
LHS);
2874 NewInst->andIRFlags(
RHS);
2879 replaceValue(
I, *NewBO);
2886bool VectorCombine::foldShuffleOfSelects(Instruction &
I) {
2888 Value *C1, *
T1, *F1, *C2, *T2, *F2;
2899 if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2905 if (((SI0FOp ==
nullptr) != (SI1FOp ==
nullptr)) ||
2906 ((SI0FOp !=
nullptr) &&
2907 (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())))
2913 auto SelOp = Instruction::Select;
2921 CostSel1 + CostSel2 +
2923 {
I.getOperand(0),
I.getOperand(1)}, &
I);
2927 CostKind, Mask, 0,
nullptr, {C1, C2});
2937 if (!Sel1->hasOneUse())
2938 NewCost += CostSel1;
2939 if (!Sel2->hasOneUse())
2940 NewCost += CostSel2;
2943 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
2945 if (NewCost > OldCost)
2954 NewSel = Builder.
CreateSelectFMF(ShuffleCmp, ShuffleTrue, ShuffleFalse,
2955 SI0FOp->getFastMathFlags());
2957 NewSel = Builder.
CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
2962 replaceValue(
I, *NewSel);
2968bool VectorCombine::foldShuffleOfCastops(Instruction &
I) {
2970 ArrayRef<int> OldMask;
2979 if (!C0 || (IsBinaryShuffle && !C1))
2986 if (!IsBinaryShuffle && Opcode == Instruction::BitCast)
2989 if (IsBinaryShuffle) {
2990 if (C0->getSrcTy() != C1->getSrcTy())
2993 if (Opcode != C1->getOpcode()) {
2995 Opcode = Instruction::SExt;
3004 if (!ShuffleDstTy || !CastDstTy || !CastSrcTy)
3007 unsigned NumSrcElts = CastSrcTy->getNumElements();
3008 unsigned NumDstElts = CastDstTy->getNumElements();
3009 assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) &&
3010 "Only bitcasts expected to alter src/dst element counts");
3014 if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 &&
3015 (NumDstElts % NumSrcElts) != 0)
3018 SmallVector<int, 16> NewMask;
3019 if (NumSrcElts >= NumDstElts) {
3022 assert(NumSrcElts % NumDstElts == 0 &&
"Unexpected shuffle mask");
3023 unsigned ScaleFactor = NumSrcElts / NumDstElts;
3028 assert(NumDstElts % NumSrcElts == 0 &&
"Unexpected shuffle mask");
3029 unsigned ScaleFactor = NumDstElts / NumSrcElts;
3034 auto *NewShuffleDstTy =
3043 if (IsBinaryShuffle)
3050 OldMask, 0,
nullptr, {}, &
I);
3058 if (IsBinaryShuffle) {
3068 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3070 if (NewCost > OldCost)
3074 if (IsBinaryShuffle)
3084 NewInst->copyIRFlags(C0);
3085 if (IsBinaryShuffle)
3086 NewInst->andIRFlags(C1);
3090 replaceValue(
I, *Cast);
3100bool VectorCombine::foldShuffleOfShuffles(Instruction &
I) {
3101 ArrayRef<int> OuterMask;
3102 Value *OuterV0, *OuterV1;
3107 ArrayRef<int> InnerMask0, InnerMask1;
3108 Value *X0, *X1, *Y0, *Y1;
3113 if (!Match0 && !Match1)
3118 SmallVector<int, 16> PoisonMask1;
3123 InnerMask1 = PoisonMask1;
3127 X0 = Match0 ? X0 : OuterV0;
3128 Y0 = Match0 ? Y0 : OuterV0;
3129 X1 = Match1 ? X1 : OuterV1;
3130 Y1 = Match1 ? Y1 : OuterV1;
3134 if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy ||
3138 unsigned NumSrcElts = ShuffleSrcTy->getNumElements();
3139 unsigned NumImmElts = ShuffleImmTy->getNumElements();
3144 SmallVector<int, 16> NewMask(OuterMask);
3145 Value *NewX =
nullptr, *NewY =
nullptr;
3146 for (
int &M : NewMask) {
3147 Value *Src =
nullptr;
3148 if (0 <= M && M < (
int)NumImmElts) {
3152 Src =
M >= (int)NumSrcElts ? Y0 : X0;
3153 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3155 }
else if (M >= (
int)NumImmElts) {
3160 Src =
M >= (int)NumSrcElts ? Y1 : X1;
3161 M =
M >= (int)NumSrcElts ? (M - NumSrcElts) :
M;
3165 assert(0 <= M && M < (
int)NumSrcElts &&
"Unexpected shuffle mask index");
3174 if (!NewX || NewX == Src) {
3178 if (!NewY || NewY == Src) {
3197 replaceValue(
I, *NewX);
3214 bool IsUnary =
all_of(NewMask, [&](
int M) {
return M < (int)NumSrcElts; });
3220 nullptr, {NewX, NewY});
3222 NewCost += InnerCost0;
3224 NewCost += InnerCost1;
3227 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3229 if (NewCost > OldCost)
3233 replaceValue(
I, *Shuf);
3249bool VectorCombine::foldShufflesOfLengthChangingShuffles(Instruction &
I) {
3254 unsigned ChainLength = 0;
3255 SmallVector<int>
Mask;
3256 SmallVector<int> YMask;
3266 ArrayRef<int> OuterMask;
3267 Value *OuterV0, *OuterV1;
3268 if (ChainLength != 0 && !Trunk->
hasOneUse())
3271 m_Mask(OuterMask))))
3273 if (OuterV0->
getType() != TrunkType) {
3279 ArrayRef<int> InnerMask0, InnerMask1;
3285 bool Match0Leaf = Match0 && A0->
getType() !=
I.getType();
3286 bool Match1Leaf = Match1 && A1->
getType() !=
I.getType();
3287 if (Match0Leaf == Match1Leaf) {
3293 SmallVector<int> CommutedOuterMask;
3300 for (
int &M : CommutedOuterMask) {
3303 if (M < (
int)NumTrunkElts)
3308 OuterMask = CommutedOuterMask;
3327 int NumLeafElts = YType->getNumElements();
3328 SmallVector<int> LocalYMask(InnerMask1);
3329 for (
int &M : LocalYMask) {
3330 if (M >= NumLeafElts)
3340 Mask.assign(OuterMask);
3341 YMask.
assign(LocalYMask);
3342 OldCost = NewCost = LocalOldCost;
3349 SmallVector<int> NewYMask(YMask);
3351 for (
auto [CombinedM, LeafM] :
llvm::zip(NewYMask, LocalYMask)) {
3352 if (LeafM == -1 || CombinedM == LeafM)
3354 if (CombinedM == -1) {
3364 SmallVector<int> NewMask;
3365 NewMask.
reserve(NumTrunkElts);
3366 for (
int M : Mask) {
3367 if (M < 0 || M >=
static_cast<int>(NumTrunkElts))
3382 if (LocalNewCost >= NewCost && LocalOldCost < LocalNewCost - NewCost)
3386 if (ChainLength == 1) {
3387 dbgs() <<
"Found chain of shuffles fed by length-changing shuffles: "
3390 dbgs() <<
" next chain link: " << *Trunk <<
'\n'
3391 <<
" old cost: " << (OldCost + LocalOldCost)
3392 <<
" new cost: " << LocalNewCost <<
'\n';
3397 OldCost += LocalOldCost;
3398 NewCost = LocalNewCost;
3402 if (ChainLength <= 1)
3410 return M < 0 || M >=
static_cast<int>(NumTrunkElts);
3413 for (
int &M : Mask) {
3414 if (M >=
static_cast<int>(NumTrunkElts))
3415 M = YMask[
M - NumTrunkElts];
3419 replaceValue(
I, *Root);
3426 replaceValue(
I, *Root);
3432bool VectorCombine::foldShuffleOfIntrinsics(Instruction &
I) {
3434 ArrayRef<int> OldMask;
3444 if (IID != II1->getIntrinsicID())
3453 if (!ShuffleDstTy || !II0Ty)
3459 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3460 Value *Arg0 = II0->getArgOperand(Idx);
3461 Value *Arg1 = II1->getArgOperand(Idx);
3478 II0Ty,
CostKind, OldMask, 0,
nullptr, {II0, II1}, &
I);
3482 SmallDenseSet<std::pair<Value *, Value *>> SeenOperandPairs;
3483 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3485 NewArgsTy.
push_back(II0->getArgOperand(Idx)->getType());
3489 ShuffleDstTy->getNumElements());
3491 std::pair<Value *, Value *> OperandPair =
3492 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3493 if (!SeenOperandPairs.
insert(OperandPair).second) {
3499 OldMask, 0,
nullptr,
3500 {II0->getArgOperand(Idx), II1->getArgOperand(Idx)});
3503 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3506 if (!II0->hasOneUse())
3508 if (II1 != II0 && !II1->hasOneUse())
3512 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
3515 if (NewCost > OldCost)
3519 SmallDenseMap<std::pair<Value *, Value *>,
Value *> ShuffleCache;
3520 for (
unsigned Idx = 0,
E = II0->arg_size(); Idx !=
E; ++Idx) {
3522 NewArgs.
push_back(II0->getArgOperand(Idx));
3524 std::pair<Value *, Value *> OperandPair =
3525 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3526 auto It = ShuffleCache.
find(OperandPair);
3527 if (It != ShuffleCache.
end()) {
3533 II0->getArgOperand(Idx), II1->getArgOperand(Idx), OldMask);
3534 ShuffleCache[OperandPair] = Shuf;
3543 NewInst->copyIRFlags(II0);
3544 NewInst->andIRFlags(II1);
3547 replaceValue(
I, *NewIntrinsic);
3553bool VectorCombine::foldPermuteOfIntrinsic(Instruction &
I) {
3565 if (!ShuffleDstTy || !IntrinsicSrcTy)
3569 unsigned NumSrcElts = IntrinsicSrcTy->getNumElements();
3570 if (
any_of(Mask, [NumSrcElts](
int M) {
return M >= (int)NumSrcElts; }))
3583 IntrinsicSrcTy,
CostKind, Mask, 0,
nullptr, {
V0}, &
I);
3587 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3589 NewArgsTy.
push_back(II0->getArgOperand(
I)->getType());
3593 ShuffleDstTy->getNumElements());
3596 ArgTy, VecTy,
CostKind, Mask, 0,
nullptr,
3597 {II0->getArgOperand(
I)});
3600 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3605 if (!II0->hasOneUse())
3608 LLVM_DEBUG(
dbgs() <<
"Found a permute of intrinsic: " <<
I <<
"\n OldCost: "
3609 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
3611 if (NewCost > OldCost)
3616 for (
unsigned I = 0,
E = II0->arg_size();
I !=
E; ++
I) {
3629 NewInst->copyIRFlags(II0);
3631 replaceValue(
I, *NewIntrinsic);
3641 int M = SV->getMaskValue(Lane);
3644 if (
static_cast<unsigned>(M) < NumElts) {
3645 V = SV->getOperand(0);
3648 V = SV->getOperand(1);
3659 auto [U, Lane] = IL;
3672 unsigned NumElts = Ty->getNumElements();
3673 if (Item.
size() == NumElts || NumElts == 1 || Item.
size() % NumElts != 0)
3679 std::iota(ConcatMask.
begin(), ConcatMask.
end(), 0);
3685 unsigned NumSlices = Item.
size() / NumElts;
3690 for (
unsigned Slice = 0; Slice < NumSlices; ++Slice) {
3691 Value *SliceV = Item[Slice * NumElts].first;
3692 if (!SliceV || SliceV->
getType() != Ty)
3694 for (
unsigned Elt = 0; Elt < NumElts; ++Elt) {
3695 auto [V, Lane] = Item[Slice * NumElts + Elt];
3696 if (Lane !=
static_cast<int>(Elt) || SliceV != V)
3705 const DenseSet<std::pair<Value *, Use *>> &IdentityLeafs,
3706 const DenseSet<std::pair<Value *, Use *>> &SplatLeafs,
3707 const DenseSet<std::pair<Value *, Use *>> &ConcatLeafs,
3710 auto [FrontV, FrontLane] = Item.
front();
3712 if (IdentityLeafs.contains(std::make_pair(FrontV, From))) {
3715 if (SplatLeafs.contains(std::make_pair(FrontV, From))) {
3717 return Builder.CreateShuffleVector(FrontV, Mask);
3719 if (ConcatLeafs.contains(std::make_pair(FrontV, From))) {
3723 for (
unsigned S = 0; S <
Values.size(); ++S)
3724 Values[S] = Item[S * NumElts].first;
3726 while (
Values.size() > 1) {
3729 std::iota(Mask.begin(), Mask.end(), 0);
3731 for (
unsigned S = 0; S < NewValues.
size(); ++S)
3733 Builder.CreateShuffleVector(
Values[S * 2],
Values[S * 2 + 1], Mask);
3747 if (BCDstTy && BCSrcTy &&
3748 BCDstTy->getElementCount() != BCSrcTy->getElementCount()) {
3749 unsigned DstElts = BCDstTy->getNumElements();
3750 unsigned SrcElts = BCSrcTy->getNumElements();
3752 if (DstElts > SrcElts) {
3754 unsigned R = DstElts / SrcElts;
3755 if (Item.
size() % R != 0)
3757 for (
unsigned Idx = 0,
E = Item.
size(); Idx <
E; Idx += R) {
3758 auto [V, Lane] = Item[Idx];
3768 unsigned R = SrcElts / DstElts;
3769 for (
auto [V, Lane] : Item) {
3775 for (
unsigned J = 0; J < R; ++J)
3780 IdentityLeafs, SplatLeafs, ConcatLeafs,
3781 Builder, WorkList,
TTI);
3783 return Builder.CreateBitCast(
3788 unsigned NumOps =
I->getNumOperands() - (
II ? 1 : 0);
3790 for (
unsigned Idx = 0; Idx <
NumOps; Idx++) {
3793 Ops[Idx] =
II->getOperand(Idx);
3798 IdentityLeafs, SplatLeafs, ConcatLeafs, Builder, WorkList,
TTI);
3808 for (
const auto &Lane : Item)
3821 auto *
Value = Builder.CreateCmp(CI->getPredicate(),
Ops[0],
Ops[1]);
3831 auto *
Value = Builder.CreateCast(CI->getOpcode(),
Ops[0], DstTy);
3836 auto *
Value = Builder.CreateIntrinsic(DstTy,
II->getIntrinsicID(),
Ops);
3850bool VectorCombine::foldShuffleToIdentity(Instruction &
I) {
3852 if (!Ty ||
I.use_empty())
3856 for (
unsigned M = 0,
E = Ty->getNumElements(); M <
E; ++M)
3860 Candidates.
push_back(std::make_pair(Start, &*
I.use_begin()));
3861 DenseSet<std::pair<Value *, Use *>> IdentityLeafs, SplatLeafs, ConcatLeafs;
3862 unsigned NumVisited = 0;
3863 bool TraversedElCountChangingBitcast =
false;
3865 while (!Candidates.
empty()) {
3870 auto Item = ItemFrom.first;
3871 auto From = ItemFrom.second;
3872 auto [FrontV, FrontLane] = Item.front();
3879 if (FrontLane == 0 &&
3883 Value *FrontV = Item.front().first;
3885 E.value().second == (int)
E.index());
3887 IdentityLeafs.
insert(std::make_pair(FrontV, From));
3892 C &&
C->getSplatValue() &&
3894 Value *FrontV = Item.front().first;
3900 SplatLeafs.
insert(std::make_pair(FrontV, From));
3905 auto [FrontV, FrontLane] = Item.front();
3906 auto [
V, Lane] = IL;
3907 return !
V || (
V == FrontV && Lane == FrontLane);
3909 SplatLeafs.
insert(std::make_pair(FrontV, From));
3915 auto CheckLaneIsEquivalentToFirst = [Item](
InstLane IL) {
3916 Value *FrontV = Item.front().first;
3925 if (CI->getPredicate() !=
cast<CmpInst>(FrontV)->getPredicate())
3928 if (CI->getSrcTy()->getScalarType() !=
3933 SI->getOperand(0)->getType() !=
3940 II->getIntrinsicID() ==
3942 !
II->hasOperandBundles());
3949 BO && BO->isIntDivRem())
3956 }
else if (
isa<UnaryOperator, TruncInst, ZExtInst, SExtInst, FPToSIInst,
3957 FPToUIInst, SIToFPInst, UIToFPInst>(FrontV)) {
3964 if (BCDstTy && BCSrcTy) {
3965 ElementCount DstEC = BCDstTy->getElementCount();
3966 ElementCount SrcEC = BCSrcTy->getElementCount();
3967 if (DstEC == SrcEC) {
3970 &BitCast->getOperandUse(0));
3975 if (DstElts > SrcElts && DstElts % SrcElts == 0) {
3979 unsigned R = DstElts / SrcElts;
3981 bool Valid = Item.size() %
R == 0;
3982 for (
unsigned Idx = 0,
E = Item.size(); Valid && Idx <
E;
3984 auto [
V0, L0] = Item[Idx];
3987 [](
InstLane IL) {
return IL.first !=
nullptr; })) {
3998 for (
unsigned J = 1; J <
R; ++J) {
3999 auto [VJ, LJ] = Item[Idx + J];
4000 if (!VJ || VJ != V0 || LJ != L0 + (
int)J) {
4011 TraversedElCountChangingBitcast =
true;
4012 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4015 }
else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
4018 unsigned R = SrcElts / DstElts;
4020 for (
auto [V, Lane] : Item) {
4026 for (
unsigned J = 0; J <
R; ++J)
4029 TraversedElCountChangingBitcast =
true;
4030 Candidates.
emplace_back(NItem, &BitCast->getOperandUse(0));
4036 &Sel->getOperandUse(0));
4038 &Sel->getOperandUse(1));
4040 &Sel->getOperandUse(2));
4044 !
II->hasOperandBundles()) {
4045 for (
unsigned Op = 0,
E =
II->getNumOperands() - 1;
Op <
E;
Op++) {
4049 Value *FrontV = Item.front().first;
4066 ConcatLeafs.
insert(std::make_pair(FrontV, From));
4073 if (NumVisited <= 1)
4079 if (NumVisited == 2 && TraversedElCountChangingBitcast)
4082 LLVM_DEBUG(
dbgs() <<
"Found a superfluous identity shuffle: " <<
I <<
"\n");
4089 ConcatLeafs, Builder, Worklist, &
TTI);
4090 replaceValue(
I, *V);
4097bool VectorCombine::foldShuffleFromReductions(Instruction &
I) {
4101 switch (
II->getIntrinsicID()) {
4102 case Intrinsic::vector_reduce_add:
4103 case Intrinsic::vector_reduce_mul:
4104 case Intrinsic::vector_reduce_and:
4105 case Intrinsic::vector_reduce_or:
4106 case Intrinsic::vector_reduce_xor:
4107 case Intrinsic::vector_reduce_smin:
4108 case Intrinsic::vector_reduce_smax:
4109 case Intrinsic::vector_reduce_umin:
4110 case Intrinsic::vector_reduce_umax:
4119 std::queue<Value *> Worklist;
4120 SmallPtrSet<Value *, 4> Visited;
4121 ShuffleVectorInst *Shuffle =
nullptr;
4125 while (!Worklist.empty()) {
4126 Value *CV = Worklist.front();
4138 if (CI->isBinaryOp()) {
4139 for (
auto *
Op : CI->operand_values())
4143 if (Shuffle && Shuffle != SV)
4160 for (
auto *V : Visited)
4161 for (
auto *U :
V->users())
4162 if (!Visited.contains(U) && U != &
I)
4165 FixedVectorType *VecType =
4169 FixedVectorType *ShuffleInputType =
4171 if (!ShuffleInputType)
4177 SmallVector<int> ConcatMask;
4179 sort(ConcatMask, [](
int X,
int Y) {
return (
unsigned)
X < (unsigned)
Y; });
4180 bool UsesSecondVec =
4181 any_of(ConcatMask, [&](
int M) {
return M >= (int)NumInputElts; });
4188 ShuffleInputType,
CostKind, ConcatMask);
4190 LLVM_DEBUG(
dbgs() <<
"Found a reduction feeding from a shuffle: " << *Shuffle
4192 LLVM_DEBUG(
dbgs() <<
" OldCost: " << OldCost <<
" vs NewCost: " << NewCost
4194 bool MadeChanges =
false;
4195 if (NewCost < OldCost) {
4199 LLVM_DEBUG(
dbgs() <<
"Created new shuffle: " << *NewShuffle <<
"\n");
4200 replaceValue(*Shuffle, *NewShuffle);
4206 MadeChanges |= foldSelectShuffle(*Shuffle,
true);
4227bool VectorCombine::foldShuffleChainsToReduce(Instruction &
I) {
4236 if (FVT->getNumElements() < 2)
4239 std::optional<Instruction::BinaryOps> CommonBinOp;
4240 std::optional<Intrinsic::ID> CommonCallOp;
4245 CommonBinOp = BO->getOpcode();
4247 CommonCallOp = MMI->getIntrinsicID();
4253 FastMathFlags CommonFMF;
4254 bool IsFloatReduction =
false;
4258 auto IsChainNode = [&](
Value *
V) {
4260 return CommonBinOp && BO->getOpcode() == *CommonBinOp;
4262 return CommonCallOp && MMI->getIntrinsicID() == *CommonCallOp;
4270 constexpr unsigned MaxChainNodes = 32;
4271 SmallSetVector<Value *, 16> Nodes;
4272 SmallSetVector<Value *, 4> Sources;
4273 unsigned NumVisited = 0;
4274 auto AddSource = [&](
Value *
V) {
4280 auto Walk = [&](
Value *
V,
auto &&Walk) ->
bool {
4283 if (++NumVisited > MaxChainNodes)
4285 if (!IsChainNode(V))
4286 return AddSource(V);
4291 if (!Walk(
U->getOperand(
I), Walk))
4300 return AddSource(V);
4302 if (!Walk(VecOpEE, Walk) || Nodes.
empty())
4309 for (
Value *V : Nodes) {
4315 if (!IsFloatReduction) {
4317 IsFloatReduction =
true;
4331 DenseMap<Value *, Demand> Demands;
4332 auto DemandOf = [&](
Value *
V) -> Demand & {
4334 Demand &
D = Demands[
V];
4335 if (
D.Lanes.getBitWidth() !=
N)
4339 DemandOf(VecOpEE).Lanes.setBit(0);
4341 Demand DV = Demands.
lookup(V);
4342 if (DV.Lanes.isZero())
4345 ArrayRef<int>
Mask = SVI->getShuffleMask();
4346 Demand &
DS = DemandOf(SVI->getOperand(0));
4347 for (
unsigned I = 0,
E =
Mask.size();
I !=
E; ++
I) {
4349 if (!DV.Lanes[
I] || Mask[
I] < 0 ||
4350 (
unsigned)Mask[
I] >=
DS.Lanes.getBitWidth())
4352 if (
DS.Lanes[Mask[
I]] || DV.Duplicates[
I])
4353 DS.Duplicates.setBit(Mask[
I]);
4354 DS.Lanes.setBit(Mask[
I]);
4358 for (
Value *
Op : {
U->getOperand(0),
U->getOperand(1)}) {
4359 Demand &DOp = DemandOf(
Op);
4361 DOp.Duplicates |= DV.Duplicates | (DOp.Lanes & DV.Lanes);
4362 DOp.Lanes |= DV.Lanes;
4369 auto CoversChain = [&](
Value *
V) {
4370 SmallVector<Value *, 8> Worklist(1, VecOpEE);
4371 SmallPtrSet<Value *, 8> Seen;
4373 while (!Worklist.empty()) {
4376 for (
unsigned I = 0;
I !=
NumOps; ++
I) {
4380 if (!Nodes.contains(
Op))
4382 Worklist.push_back(
Op);
4390 struct ReductionCut {
4394 std::optional<ReductionCut> Cut;
4395 for (
Value *S : Sources) {
4396 auto It = Demands.
find(S);
4397 if (It == Demands.
end() || It->second.Lanes.isZero())
4399 if (!IsIdempotent && !It->second.Duplicates.isZero()) {
4404 Cut = ReductionCut{S, It->second.Lanes};
4411 if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
4415 Cut->Elts |= It->second.Lanes;
4418 for (
Value *V : Nodes) {
4421 auto It = Demands.
find(V);
4422 if (It == Demands.
end() || !It->second.Lanes.isAllOnes())
4424 if (!IsIdempotent && !It->second.Duplicates.isZero())
4426 if (!CoversChain(V))
4428 Cut = ReductionCut{
V, It->second.Lanes};
4433 if (!Cut || Cut->Elts.popcount() < 2)
4443 for (
Value *V : Nodes)
4447 bool IsPartialReduction = !Cut->Elts.isAllOnes();
4448 FixedVectorType *ReduceVecTy =
4453 SmallVector<int> ExtractMask;
4455 if (IsPartialReduction) {
4456 for (
unsigned I = 0,
E = Cut->Elts.getBitWidth();
I !=
E; ++
I)
4458 ExtractMask.push_back(
I);
4459 unsigned SubIdx = 0, SubLen;
4460 auto SK = Cut->Elts.isShiftedMask(SubIdx, SubLen)
4464 SubIdx, ReduceVecTy);
4467 IntrinsicCostAttributes ICA(
4468 ReducedOp, ReduceVecTy->getElementType(),
4472 IsFloatReduction ? CommonFMF : FastMathFlags());
4475 LLVM_DEBUG(
dbgs() <<
"Found reduction shuffle chain: " <<
I <<
"\n OldCost : "
4476 << OrigCost <<
" vs NewCost: " << NewCost <<
"\n");
4481 if (VecOpEE->
hasOneUse() ? (NewCost > OrigCost) : (NewCost >= OrigCost))
4484 Value *ReduceInput = Cut->Src;
4485 if (IsPartialReduction)
4488 Value *ReducedResult;
4489 if (IsFloatReduction) {
4491 *CommonBinOp, ReduceVecTy->getElementType(),
false,
4494 {Identity, ReduceInput}, CommonFMF);
4499 replaceValue(
I, *ReducedResult);
4508bool VectorCombine::foldCastFromReductions(Instruction &
I) {
4513 bool TruncOnly =
false;
4516 case Intrinsic::vector_reduce_add:
4517 case Intrinsic::vector_reduce_mul:
4520 case Intrinsic::vector_reduce_and:
4521 case Intrinsic::vector_reduce_or:
4522 case Intrinsic::vector_reduce_xor:
4529 Value *ReductionSrc =
I.getOperand(0);
4541 Type *ResultTy =
I.getType();
4544 ReductionOpc, ReductionSrcTy, std::nullopt,
CostKind);
4554 if (OldCost <= NewCost || !NewCost.
isValid())
4558 II->getIntrinsicID(), {Src});
4560 replaceValue(
I, *NewCast);
4588bool VectorCombine::foldSignBitReductionCmp(Instruction &
I) {
4590 IntrinsicInst *ReduceOp;
4591 const APInt *CmpVal;
4598 case Intrinsic::vector_reduce_or:
4599 case Intrinsic::vector_reduce_umax:
4600 case Intrinsic::vector_reduce_and:
4601 case Intrinsic::vector_reduce_umin:
4602 case Intrinsic::vector_reduce_add:
4613 unsigned BitWidth = VecTy->getScalarSizeInBits();
4617 unsigned NumElts = VecTy->getNumElements();
4626 case Intrinsic::vector_reduce_or:
4627 case Intrinsic::vector_reduce_umax:
4628 TreeOpcode = Instruction::Or;
4630 case Intrinsic::vector_reduce_and:
4631 case Intrinsic::vector_reduce_umin:
4632 TreeOpcode = Instruction::And;
4634 case Intrinsic::vector_reduce_add:
4635 TreeOpcode = Instruction::Add;
4643 SmallVector<Value *, 8> Worklist;
4644 SmallVector<Value *, 8> Sources;
4646 std::optional<bool> IsAShr;
4647 constexpr unsigned MaxSources = 8;
4652 while (!Worklist.
empty() && Worklist.
size() <= MaxSources &&
4653 Sources.
size() <= MaxSources) {
4662 bool ThisIsAShr = Shr->getOpcode() == Instruction::AShr;
4664 IsAShr = ThisIsAShr;
4665 else if (*IsAShr != ThisIsAShr)
4691 if (Sources.
empty() || Sources.
size() > MaxSources ||
4692 Worklist.
size() > MaxSources || !IsAShr)
4695 unsigned NumSources = Sources.
size();
4699 if (OrigIID == Intrinsic::vector_reduce_add &&
4707 (OrigIID == Intrinsic::vector_reduce_add) ? NumSources * NumElts : 1;
4710 NegativeVal.negate();
4742 TestsNegative =
false;
4743 }
else if (*CmpVal == NegativeVal) {
4744 TestsNegative =
true;
4748 IsEq = Pred == ICmpInst::ICMP_EQ;
4749 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeHigh) {
4751 TestsNegative = (RangeHigh == NegativeVal);
4752 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeHigh - 1) {
4754 TestsNegative = (RangeHigh == NegativeVal);
4755 }
else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeLow) {
4757 TestsNegative = (RangeLow == NegativeVal);
4758 }
else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeLow + 1) {
4760 TestsNegative = (RangeLow == NegativeVal);
4803 enum CheckKind :
unsigned {
4810 auto RequiresOr = [](CheckKind
C) ->
bool {
return C & 0b100; };
4812 auto IsNegativeCheck = [](CheckKind
C) ->
bool {
return C & 0b010; };
4814 auto Invert = [](CheckKind
C) {
return CheckKind(
C ^ 0b011); };
4818 case Intrinsic::vector_reduce_or:
4819 case Intrinsic::vector_reduce_umax:
4820 Base = TestsNegative ? AnyNeg : AllNonNeg;
4822 case Intrinsic::vector_reduce_and:
4823 case Intrinsic::vector_reduce_umin:
4824 Base = TestsNegative ? AllNeg : AnyNonNeg;
4826 case Intrinsic::vector_reduce_add:
4827 Base = TestsNegative ? AllNeg : AllNonNeg;
4842 return ArithCost <= MinMaxCost ? std::make_pair(Arith, ArithCost)
4843 : std::make_pair(MinMax, MinMaxCost);
4847 auto [NewIID, NewCost] = RequiresOr(
Check)
4848 ? PickCheaper(Intrinsic::vector_reduce_or,
4849 Intrinsic::vector_reduce_umax)
4850 : PickCheaper(
Intrinsic::vector_reduce_and,
4854 if (NumSources > 1) {
4855 unsigned CombineOpc =
4856 RequiresOr(
Check) ? Instruction::Or : Instruction::And;
4861 LLVM_DEBUG(
dbgs() <<
"Found sign-bit reduction cmp: " <<
I <<
"\n OldCost: "
4862 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4864 if (NewCost > OldCost)
4869 Type *ScalarTy = VecTy->getScalarType();
4872 if (NumSources == 1) {
4883 replaceValue(
I, *NewCmp);
4914bool VectorCombine::foldReductionZeroTest(Instruction &
I) {
4923 if (!
II || !
II->hasOneUse())
4926 auto ReduceID =
II->getIntrinsicID();
4927 if (ReduceID != Intrinsic::vector_reduce_or &&
4928 ReduceID != Intrinsic::vector_reduce_umax)
4931 Value *Vec =
II->getArgOperand(0);
4933 if (!VecTy || !VecTy->getElementType()->isIntegerTy())
4938 ? Intrinsic::vector_reduce_or
4953 LLVM_DEBUG(
dbgs() <<
"Found a reduction zero test: " <<
I <<
"\n OldCost: "
4954 << OldCost <<
" vs NewCost: " << NewCost <<
"\n");
4956 if (!OldCost.
isValid() || !NewCost.
isValid() || NewCost > OldCost)
4962 replaceValue(
I, *NewReduce);
4987bool VectorCombine::foldICmpEqZeroVectorReduce(Instruction &
I) {
4998 switch (
II->getIntrinsicID()) {
4999 case Intrinsic::vector_reduce_add:
5000 case Intrinsic::vector_reduce_or:
5001 case Intrinsic::vector_reduce_umin:
5002 case Intrinsic::vector_reduce_umax:
5003 case Intrinsic::vector_reduce_smin:
5004 case Intrinsic::vector_reduce_smax:
5010 Value *InnerOp =
II->getArgOperand(0);
5053 switch (
II->getIntrinsicID()) {
5054 case Intrinsic::vector_reduce_add: {
5059 unsigned NumElems = XTy->getNumElements();
5065 if (LeadingZerosX <= LostBits || LeadingZerosFX <= LostBits)
5073 case Intrinsic::vector_reduce_smin:
5074 case Intrinsic::vector_reduce_smax:
5084 LLVM_DEBUG(
dbgs() <<
"Found a reduction to 0 comparison with removable op: "
5100 case Intrinsic::vector_reduce_add:
5101 case Intrinsic::vector_reduce_or:
5107 case Intrinsic::vector_reduce_umin:
5108 case Intrinsic::vector_reduce_umax:
5109 case Intrinsic::vector_reduce_smin:
5110 case Intrinsic::vector_reduce_smax:
5122 NewReduceCost + (InnerOp->
hasOneUse() ? 0 : ExtCost);
5124 LLVM_DEBUG(
dbgs() <<
"Found a removable extension before reduction: "
5125 << *InnerOp <<
"\n OldCost: " << OldCost
5126 <<
" vs NewCost: " << NewCost <<
"\n");
5132 if (NewCost > OldCost)
5141 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::getNullValue(Ty));
5142 replaceValue(
I, *NewCmp);
5173bool VectorCombine::foldEquivalentReductionCmp(Instruction &
I) {
5176 const APInt *CmpVal;
5181 if (!
II || !
II->hasOneUse())
5184 const auto IsValidOrUmaxCmp = [&]() {
5193 bool IsPositive = CmpVal->
isAllOnes() && Pred == ICmpInst::ICMP_SGT;
5195 bool IsNegative = (CmpVal->
isZero() || CmpVal->
isOne() || *CmpVal == 2) &&
5196 Pred == ICmpInst::ICMP_SLT;
5197 return IsEquality || IsPositive || IsNegative;
5200 const auto IsValidAndUminCmp = [&]() {
5205 const auto LeadingOnes = CmpVal->
countl_one();
5212 bool IsNegative = CmpVal->
isZero() && Pred == ICmpInst::ICMP_SLT;
5221 ((*CmpVal)[0] || (*CmpVal)[1]) && Pred == ICmpInst::ICMP_SGT;
5222 return IsEquality || IsNegative || IsPositive;
5230 switch (OriginalIID) {
5231 case Intrinsic::vector_reduce_or:
5232 if (!IsValidOrUmaxCmp())
5234 AlternativeIID = Intrinsic::vector_reduce_umax;
5236 case Intrinsic::vector_reduce_umax:
5237 if (!IsValidOrUmaxCmp())
5239 AlternativeIID = Intrinsic::vector_reduce_or;
5241 case Intrinsic::vector_reduce_and:
5242 if (!IsValidAndUminCmp())
5244 AlternativeIID = Intrinsic::vector_reduce_umin;
5246 case Intrinsic::vector_reduce_umin:
5247 if (!IsValidAndUminCmp())
5249 AlternativeIID = Intrinsic::vector_reduce_and;
5262 if (ReductionOpc != Instruction::ICmp)
5273 <<
"\n OrigCost: " << OrigCost
5274 <<
" vs AltCost: " << AltCost <<
"\n");
5276 if (AltCost >= OrigCost)
5280 Type *ScalarTy = VecTy->getScalarType();
5283 Builder.
CreateICmp(Pred, NewReduce, ConstantInt::get(ScalarTy, *CmpVal));
5285 replaceValue(
I, *NewCmp);
5299 unsigned Depth = 0) {
5300 constexpr unsigned MaxLocalDepth = 2;
5301 if (
Depth > MaxLocalDepth)
5304 auto NumSignBits = [&](
const Value *
X) {
5307 if (NumSignBits(V) == V->getType()->getScalarSizeInBits())
5312 return NumSignBits(
A) >= 2 && NumSignBits(
B) >= 2 &&
5323bool VectorCombine::foldReduceAddCmpZero(Instruction &
I) {
5333 if (!VecTy || VecTy->getNumElements() < 2)
5339 if (!IsNonNegative && !IsNonPositive)
5344 unsigned NumElts = VecTy->getNumElements();
5346 if (
Log2_32(NumElts) >= NumSignBits)
5349 ICmpInst::Predicate NewPred;
5351 case ICmpInst::ICMP_EQ:
5352 case ICmpInst::ICMP_ULE:
5353 case ICmpInst::ICMP_SLE:
5354 case ICmpInst::ICMP_SGE:
5355 NewPred = ICmpInst::ICMP_EQ;
5357 case ICmpInst::ICMP_NE:
5358 case ICmpInst::ICMP_UGT:
5359 case ICmpInst::ICMP_SGT:
5360 case ICmpInst::ICMP_SLT:
5361 NewPred = ICmpInst::ICMP_NE;
5371 if (!IsNonNegative &&
5372 (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE))
5374 if (!IsNonPositive &&
5375 (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE))
5377 if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE ||
5378 Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) &&
5379 Log2_32(NumElts) >= NumSignBits - 1)
5383 Instruction::Add, VecTy, std::nullopt,
CostKind);
5385 Instruction::Or, VecTy, std::nullopt,
CostKind);
5387 Intrinsic::umax, VecTy, FastMathFlags(),
CostKind);
5390 bool UseOr = OrCost.
isValid() && (!UmaxCost.
isValid() || OrCost <= UmaxCost);
5392 if (AltCost > OrigCost)
5398 Intrinsic::vector_reduce_umax, {VecTy}, {Vec});
5399 Worklist.pushValue(NewReduce);
5401 NewPred, NewReduce, ConstantInt::getNullValue(VecTy->getScalarType()));
5402 replaceValue(
I, *NewCmp);
5411 constexpr unsigned MaxVisited = 32;
5414 bool FoundReduction =
false;
5417 while (!WorkList.
empty()) {
5419 for (
User *U :
I->users()) {
5421 if (!UI || !Visited.
insert(UI).second)
5423 if (Visited.
size() > MaxVisited)
5429 switch (
II->getIntrinsicID()) {
5430 case Intrinsic::vector_reduce_add:
5431 case Intrinsic::vector_reduce_mul:
5432 case Intrinsic::vector_reduce_and:
5433 case Intrinsic::vector_reduce_or:
5434 case Intrinsic::vector_reduce_xor:
5435 case Intrinsic::vector_reduce_smin:
5436 case Intrinsic::vector_reduce_smax:
5437 case Intrinsic::vector_reduce_umin:
5438 case Intrinsic::vector_reduce_umax:
5439 FoundReduction =
true;
5452 return FoundReduction;
5465bool VectorCombine::foldSelectShuffle(Instruction &
I,
bool FromReduction) {
5470 if (!Op0 || !Op1 || Op0 == Op1 || !Op0->isBinaryOp() || !Op1->isBinaryOp() ||
5471 VT != Op0->getType())
5478 SmallPtrSet<Instruction *, 4> InputShuffles({SVI0A, SVI0B, SVI1A, SVI1B});
5480 if (!
I ||
I->getOperand(0)->getType() != VT)
5482 return any_of(
I->users(), [&](User *U) {
5483 return U != Op0 && U != Op1 &&
5484 !(isa<ShuffleVectorInst>(U) &&
5485 (InputShuffles.contains(cast<Instruction>(U)) ||
5486 isInstructionTriviallyDead(cast<Instruction>(U))));
5489 if (checkSVNonOpUses(SVI0A) || checkSVNonOpUses(SVI0B) ||
5490 checkSVNonOpUses(SVI1A) || checkSVNonOpUses(SVI1B))
5498 for (
auto *U :
I->users()) {
5500 if (!SV ||
SV->getType() != VT)
5502 if ((
SV->getOperand(0) != Op0 &&
SV->getOperand(0) != Op1) ||
5503 (
SV->getOperand(1) != Op0 &&
SV->getOperand(1) != Op1))
5510 if (!collectShuffles(Op0) || !collectShuffles(Op1))
5514 if (FromReduction && Shuffles.
size() > 1)
5519 if (!FromReduction) {
5520 for (
size_t Idx = 0,
E = Shuffles.
size(); Idx !=
E; ++Idx) {
5521 for (
auto *U : Shuffles[Idx]->
users()) {
5536 int MaxV1Elt = 0, MaxV2Elt = 0;
5537 unsigned NumElts = VT->getNumElements();
5538 for (ShuffleVectorInst *SVN : Shuffles) {
5539 SmallVector<int>
Mask;
5540 SVN->getShuffleMask(Mask);
5544 Value *SVOp0 = SVN->getOperand(0);
5545 Value *SVOp1 = SVN->getOperand(1);
5550 for (
int &Elem : Mask) {
5556 if (SVOp0 == Op1 && SVOp1 == Op0) {
5560 if (SVOp0 != Op0 || SVOp1 != Op1)
5566 SmallVector<int> ReconstructMask;
5567 for (
unsigned I = 0;
I <
Mask.size();
I++) {
5570 }
else if (Mask[
I] <
static_cast<int>(NumElts)) {
5571 MaxV1Elt = std::max(MaxV1Elt, Mask[
I]);
5572 auto It =
find_if(
V1, [&](
const std::pair<int, int> &
A) {
5573 return Mask[
I] ==
A.first;
5579 V1.emplace_back(Mask[
I],
V1.size());
5582 MaxV2Elt = std::max<int>(MaxV2Elt, Mask[
I] - NumElts);
5583 auto It =
find_if(V2, [&](
const std::pair<int, int> &
A) {
5584 return Mask[
I] -
static_cast<int>(NumElts) ==
A.first;
5598 sort(ReconstructMask);
5599 OrigReconstructMasks.
push_back(std::move(ReconstructMask));
5606 if (
V1.empty() || V2.
empty() ||
5607 (MaxV1Elt ==
static_cast<int>(
V1.size()) - 1 &&
5608 MaxV2Elt ==
static_cast<int>(V2.
size()) - 1))
5620 if (InputShuffles.contains(SSV))
5622 return SV->getMaskValue(M);
5630 std::pair<int, int>
Y) {
5631 int MXA = GetBaseMaskValue(
A,
X.first);
5632 int MYA = GetBaseMaskValue(
A,
Y.first);
5636 return SortBase(SVI0A,
A,
B);
5638 stable_sort(V2, [&](std::pair<int, int>
A, std::pair<int, int>
B) {
5639 return SortBase(SVI1A,
A,
B);
5644 for (
const auto &Mask : OrigReconstructMasks) {
5645 SmallVector<int> ReconstructMask;
5646 for (
int M : Mask) {
5648 auto It =
find_if(V, [M](
auto A) {
return A.second ==
M; });
5649 assert(It !=
V.end() &&
"Expected all entries in Mask");
5650 return std::distance(
V.begin(), It);
5654 else if (M <
static_cast<int>(NumElts)) {
5657 ReconstructMask.
push_back(NumElts + FindIndex(V2, M));
5660 ReconstructMasks.
push_back(std::move(ReconstructMask));
5665 SmallVector<int> V1A, V1B, V2A, V2B;
5666 for (
unsigned I = 0;
I <
V1.size();
I++) {
5670 for (
unsigned I = 0;
I < V2.
size();
I++) {
5671 V2A.
push_back(GetBaseMaskValue(SVI1A, V2[
I].first));
5672 V2B.
push_back(GetBaseMaskValue(SVI1B, V2[
I].first));
5674 while (V1A.
size() < NumElts) {
5678 while (V2A.
size() < NumElts) {
5697 unsigned ElementSize = VT->getElementType()->getPrimitiveSizeInBits();
5698 unsigned MaxVectorSize =
5700 unsigned MaxElementsInVector = MaxVectorSize / ElementSize;
5701 if (MaxElementsInVector == 0)
5710 std::set<SmallVector<int, 4>> UniqueShuffles;
5715 unsigned NumFullVectors =
Mask.size() / MaxElementsInVector;
5716 if (NumFullVectors < 2)
5717 return C + ShuffleCost;
5718 SmallVector<int, 4> SubShuffle(MaxElementsInVector);
5719 unsigned NumUniqueGroups = 0;
5720 unsigned NumGroups =
Mask.size() / MaxElementsInVector;
5723 for (
unsigned I = 0;
I < NumFullVectors; ++
I) {
5724 for (
unsigned J = 0; J < MaxElementsInVector; ++J)
5725 SubShuffle[J] = Mask[MaxElementsInVector *
I + J];
5726 if (UniqueShuffles.insert(SubShuffle).second)
5727 NumUniqueGroups += 1;
5729 return C + ShuffleCost * NumUniqueGroups / NumGroups;
5735 SmallVector<int, 16>
Mask;
5736 SV->getShuffleMask(Mask);
5737 return AddShuffleMaskAdjustedCost(
C, Mask);
5740 auto AllShufflesHaveSameOperands =
5741 [](SmallPtrSetImpl<Instruction *> &InputShuffles) {
5742 if (InputShuffles.size() < 2)
5744 ShuffleVectorInst *FirstSV =
5751 std::next(InputShuffles.begin()), InputShuffles.end(),
5752 [&](Instruction *
I) {
5753 ShuffleVectorInst *SV = dyn_cast<ShuffleVectorInst>(I);
5754 return SV && SV->getOperand(0) == In0 && SV->getOperand(1) == In1;
5763 CostBefore += std::accumulate(Shuffles.begin(), Shuffles.end(),
5765 if (AllShufflesHaveSameOperands(InputShuffles)) {
5766 UniqueShuffles.clear();
5767 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5770 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5776 FixedVectorType *Op0SmallVT =
5778 FixedVectorType *Op1SmallVT =
5783 UniqueShuffles.clear();
5784 CostAfter += std::accumulate(ReconstructMasks.begin(), ReconstructMasks.end(),
5786 std::set<SmallVector<int>> OutputShuffleMasks({V1A, V1B, V2A, V2B});
5788 std::accumulate(OutputShuffleMasks.begin(), OutputShuffleMasks.end(),
5791 LLVM_DEBUG(
dbgs() <<
"Found a binop select shuffle pattern: " <<
I <<
"\n");
5793 <<
" vs CostAfter: " << CostAfter <<
"\n");
5794 if (CostBefore < CostAfter ||
5805 if (InputShuffles.contains(SSV))
5807 return SV->getOperand(
Op);
5811 GetShuffleOperand(SVI0A, 1), V1A);
5814 GetShuffleOperand(SVI0B, 1), V1B);
5817 GetShuffleOperand(SVI1A, 1), V2A);
5820 GetShuffleOperand(SVI1B, 1), V2B);
5825 I->copyIRFlags(Op0,
true);
5830 I->copyIRFlags(Op1,
true);
5832 for (
int S = 0,
E = ReconstructMasks.size(); S !=
E; S++) {
5835 replaceValue(*Shuffles[S], *NSV,
false);
5838 Worklist.pushValue(NSV0A);
5839 Worklist.pushValue(NSV0B);
5840 Worklist.pushValue(NSV1A);
5841 Worklist.pushValue(NSV1B);
5851bool VectorCombine::shrinkType(Instruction &
I) {
5852 Value *ZExted, *OtherOperand;
5858 Value *ZExtOperand =
I.getOperand(
I.getOperand(0) == OtherOperand ? 1 : 0);
5862 unsigned BW = SmallTy->getElementType()->getPrimitiveSizeInBits();
5864 if (
I.getOpcode() == Instruction::LShr) {
5881 Instruction::ZExt, BigTy, SmallTy,
5882 TargetTransformInfo::CastContextHint::None,
CostKind);
5887 for (User *U : ZExtOperand->
users()) {
5894 ShrinkCost += ZExtCost;
5909 ShrinkCost += ZExtCost;
5916 Instruction::Trunc, SmallTy, BigTy,
5917 TargetTransformInfo::CastContextHint::None,
CostKind);
5922 if (ShrinkCost > CurrentCost)
5926 Value *Op0 = ZExted;
5929 if (
I.getOperand(0) == OtherOperand)
5934 NewBinOpI->copyIRFlags(&
I);
5935 NewBinOpI->copyMetadata(
I);
5938 replaceValue(
I, *NewZExtr);
5944bool VectorCombine::foldInsExtVectorToShuffle(Instruction &
I) {
5945 Value *DstVec, *SrcVec;
5956 if (!DstVecTy || !SrcVecTy ||
5962 if (InsIdx >= NumDstElts || ExtIdx >= NumSrcElts || NumDstElts == 1)
5969 bool NeedExpOrNarrow = NumSrcElts != NumDstElts;
5971 if (NeedDstSrcSwap) {
5973 Mask[InsIdx] = ExtIdx % NumDstElts;
5977 std::iota(
Mask.begin(),
Mask.end(), 0);
5978 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
5991 SmallVector<int> ExtToVecMask;
5992 if (!NeedExpOrNarrow) {
5997 nullptr, {DstVec, SrcVec});
6003 ExtToVecMask[ExtIdx % NumDstElts] = ExtIdx;
6006 DstVecTy, SrcVecTy,
CostKind, ExtToVecMask);
6010 if (!Ext->hasOneUse())
6013 LLVM_DEBUG(
dbgs() <<
"Found a insert/extract shuffle-like pair: " <<
I
6014 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6017 if (OldCost < NewCost)
6020 if (NeedExpOrNarrow) {
6021 if (!NeedDstSrcSwap)
6034 replaceValue(
I, *Shuf);
6058bool VectorCombine::foldDeinterleaveInterleavePair(Instruction &
I) {
6075 if (
U.getUser()->isDroppable())
6079 if (!Extract || Extract->getNumIndices() != 1)
6082 unsigned Index = *Extract->idx_begin();
6083 if (Index >= Factor || CurrentUses[Index])
6091 IntrinsicInst *Interleave =
nullptr;
6092 unsigned NumVisited = 0;
6096 return CB->arg_size();
6097 return Inst->getNumOperands();
6100 auto IsSupportedElementwise = [&](
Instruction *Inst) {
6106 if (
II->hasOperandBundles() ||
6109 }
else if (!
isa<BinaryOperator, UnaryOperator, CastInst, CmpInst,
6110 SelectInst, FreezeInst>(Inst)) {
6116 for (
unsigned Op = 0,
E = GetNumDataOperands(Inst);
Op !=
E; ++
Op) {
6119 OperandTy->getElementCount() != ResultTy->getElementCount())
6131 NumVisited += Factor;
6133 for (Use *&CurrentUse : CurrentUses) {
6134 Use *NextUse = CurrentUse->getUser()->getSingleUndroppableUse();
6140 CurrentUse = NextUse;
6145 II &&
II->getIntrinsicID() == ExpectedInterleaveIID) {
6146 if (
II->hasOperandBundles())
6149 for (
unsigned Index = 0;
Index != Factor; ++
Index)
6150 if (CurrentUses[Index]->getUser() !=
II ||
6151 CurrentUses[Index]->getOperandNo() != Index)
6159 if (!IsSupportedElementwise(FirstInst))
6162 unsigned ChainOperand = CurrentUses.front()->getOperandNo();
6163 bool MismatchedUse =
any_of(CurrentUses, [&](Use *U) {
6165 return Inst != FirstInst && (
U->getOperandNo() != ChainOperand ||
6166 !FirstInst->isSameOperationAs(
6172 auto GetSplatOrScalar = [](
Value *
V) {
6179 for (
unsigned Op = 0,
E = GetNumDataOperands(FirstInst);
Op !=
E; ++
Op) {
6180 if (
Op == ChainOperand)
6183 Value *CommonValue = GetSplatOrScalar(FirstInst->getOperand(
Op));
6184 if (!CommonValue ||
any_of(CurrentUses, [&](Use *U) {
6186 return Inst != FirstInst &&
6200 ElementCount WideEC =
6203 auto CreateWideInstruction = [&](
Instruction *NarrowInst,
6206 assert(IsSupportedElementwise(NarrowInst) &&
6207 "Expected supported elementwise");
6211 return Builder.
CreateCast(Cast->getOpcode(), NewOperands[0],
6214 return Builder.
CreateCmp(
Cmp->getPredicate(), NewOperands[0],
6218 NewOperands[0], NewOperands[1], NewOperands[2],
"",
6230 for (
const ElementwiseStep &Step : Steps) {
6232 unsigned ChainOperand = Step.front()->getOperandNo();
6237 unsigned NumOperands = GetNumDataOperands(NarrowInst);
6238 SmallVector<Value *, 4> NewOperands;
6239 NewOperands.
reserve(NumOperands);
6241 for (
unsigned Op = 0;
Op != NumOperands; ++
Op) {
6244 if (
Op == ChainOperand)
6245 Operand = WideValue;
6251 auto *WideResultTy =
6254 CreateWideInstruction(NarrowInst, NewOperands, WideResultTy);
6263 WideValue = NewValue;
6267 replaceValue(*Interleave, *WideValue);
6275bool VectorCombine::foldInterleaveIntrinsics(Instruction &
I) {
6276 const APInt *SplatVal0, *SplatVal1;
6286 auto *ExtVTy = VectorType::getExtendedElementVectorType(VTy);
6287 unsigned Width = VTy->getElementType()->getIntegerBitWidth();
6296 LLVM_DEBUG(
dbgs() <<
"VC: The cost to cast from " << *ExtVTy <<
" to "
6297 << *
I.getType() <<
" is too high.\n");
6301 APInt NewSplatVal = SplatVal1->
zext(Width * 2);
6302 NewSplatVal <<= Width;
6303 NewSplatVal |= SplatVal0->
zext(Width * 2);
6305 ExtVTy->getElementCount(), ConstantInt::get(
F.getContext(), NewSplatVal));
6340bool VectorCombine::foldDeinterleaveIntrinsics(Instruction &
I) {
6341 if (foldDeinterleaveInterleavePair(
I))
6345 if (
DL->isBigEndian())
6348 using namespace PatternMatch;
6349 Value *DeinterleavedVal;
6360 unsigned HalfElementWidth = ElementWidth / 2;
6364 std::array<ExtractValueInst *, 2> OrigFields{};
6365 for (User *Usr :
I.users()) {
6368 if (!
E ||
E->getNumIndices() != 1)
6370 unsigned Idx = *
E->idx_begin();
6372 if (Idx >= 2 || OrigFields[Idx] || !
E->hasNUses(2))
6374 OrigFields[Idx] =
E;
6378 SmallVector<Instruction *, 2> MergeInsts;
6379 for (
auto *FieldUsr : OrigFields[0]->
users()) {
6387 auto MatchMerge = [&](void) ->
bool {
6390 return match(MergeInsts[0],
6394 match(MergeInsts[1],
6399 if (!MatchMerge()) {
6400 std::swap(MergeInsts[0], MergeInsts[1]);
6415 auto *NewFieldTy = VecTy->getWithNewBitWidth(HalfElementWidth);
6425 if (OldCost <= NewCost || !NewCost.
isValid()) {
6427 dbgs() <<
"VC: New deinterleave2 sequence cost (" << NewCost <<
")"
6428 <<
" is higher than that of the old one (" << OldCost <<
")\n");
6436 Intrinsic::vector_deinterleave2, {NewVecTy}, {NewVecCast});
6437 for (
auto [Idx, MergeInst] :
enumerate(MergeInsts)) {
6439 NewField = Builder.
CreateBitCast(NewField, MergeInst->getType());
6440 replaceValue(*MergeInst, *NewField);
6446bool VectorCombine::foldBitcastOfVPLoad(Instruction &
I) {
6447 const DataLayout &
DL =
I.getDataLayout();
6462 DL.getValueOrABITypeAlignment(
II->getPointerAlignment(), OrigVecTy);
6463 ElementCount OrigVecCnt = OrigVecTy->getElementCount();
6465 ElementCount NewVecCnt = NewVecTy->getElementCount();
6477 II->getMemoryPointerParam(),
false,
6483 {Intrinsic::vp_load, NewVecTy,
II->getMemoryPointerParam(),
false,
6487 <<
" NewCost=" << NewCost <<
"\n");
6488 if (NewCost > OldCost || !NewCost.
isValid())
6496 NewVecTy, Intrinsic::vp_load,
6497 {
II->getMemoryPointerParam(), NewMask, NewEVL});
6500 0, AttrBuilder(
II->getContext()).addAlignmentAttr(OrigAlign));
6501 replaceValue(*Cast, *NewVP);
6511bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &
I) {
6515 Type *Ty =
X->getType();
6516 Type *VecTy =
I.getOperand(0)->getType();
6530 if (CanUseBswap || CanUseFshl) {
6541 IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
6542 IntrinsicCostAttributes ICABFshl(Intrinsic::fshl, Ty, {
X,
X, HalfBW},
6544 IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
6549 if (!InnerCall->hasOneUse())
6552 else if (!InnerBitCast->hasOneUse())
6555 <<
"\n OldCost: " << OldCost
6556 <<
" vs NewCost: " << NewCost <<
"\n");
6557 if (NewCost.isValid() && NewCost < OldCost) {
6563 Worklist.pushValue(
Swap);
6565 replaceValue(
I, *BRev);
6574 Type *Ty =
I.getType();
6576 TypeSize ElementSize =
DL->getTypeStoreSize(Ty);
6579 Type *NewVecTy = VectorType::get(I8Ty, NewVecCnt);
6592 IntrinsicCostAttributes ICANew(Intrinsic::bitreverse, NewVecTy, {NewVecTy});
6595 InstructionCost NewCost = CastToVecCost + NewIntrinsicCost + CastToOrigCost;
6596 if (!InnerII->hasOneUse())
6599 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6601 if (!NewCost.
isValid() || NewCost >= OldCost)
6609 replaceValue(
I, *CastToOrig);
6619 unsigned RawNumElements = MaxIdx + 1u;
6623 return RawNumElements;
6627 return RawNumElements;
6632 return RawNumElements;
6637 if (ElemsPerReg == 0 || RawNumElements <= ElemsPerReg)
6638 return RawNumElements;
6640 return alignTo(RawNumElements, ElemsPerReg);
6644bool VectorCombine::shrinkLoadForShuffles(Instruction &
I) {
6646 if (!OldLoad || !OldLoad->isSimple())
6653 unsigned const OldNumElements = OldLoadTy->getNumElements();
6659 using IndexRange = std::pair<int, int>;
6660 auto GetIndexRangeInShuffles = [&]() -> std::optional<IndexRange> {
6661 IndexRange OutputRange = IndexRange(OldNumElements, -1);
6662 for (llvm::Use &Use :
I.uses()) {
6664 User *Shuffle =
Use.getUser();
6669 return std::nullopt;
6676 for (
int Index : Mask) {
6677 if (Index >= 0 && Index <
static_cast<int>(OldNumElements)) {
6678 OutputRange.first = std::min(Index, OutputRange.first);
6679 OutputRange.second = std::max(Index, OutputRange.second);
6684 if (OutputRange.second < OutputRange.first)
6685 return std::nullopt;
6691 if (std::optional<IndexRange> Indices = GetIndexRangeInShuffles()) {
6692 unsigned const NewNumElements =
6697 if (NewNumElements < OldNumElements) {
6702 Type *ElemTy = OldLoadTy->getElementType();
6704 Value *PtrOp = OldLoad->getPointerOperand();
6707 Instruction::Load, OldLoad->getType(), OldLoad->getAlign(),
6708 OldLoad->getPointerAddressSpace(),
CostKind);
6711 OldLoad->getPointerAddressSpace(),
CostKind);
6713 using UseEntry = std::pair<ShuffleVectorInst *, std::vector<int>>;
6715 unsigned const MaxIndex = NewNumElements * 2u;
6717 for (llvm::Use &Use :
I.uses()) {
6724 ArrayRef<int> OldMask = Shuffle->getShuffleMask();
6730 for (
int Index : OldMask) {
6731 if (Index >=
static_cast<int>(MaxIndex))
6745 dbgs() <<
"Found a load used only by shufflevector instructions: "
6746 <<
I <<
"\n OldCost: " << OldCost
6747 <<
" vs NewCost: " << NewCost <<
"\n");
6749 if (OldCost < NewCost || !NewCost.
isValid())
6755 NewLoad->copyMetadata(
I);
6758 for (UseEntry &Use : NewUses) {
6759 ShuffleVectorInst *Shuffle =
Use.first;
6760 std::vector<int> &NewMask =
Use.second;
6767 replaceValue(*Shuffle, *NewShuffle,
false);
6780bool VectorCombine::shrinkPhiOfShuffles(Instruction &
I) {
6782 if (!Phi ||
Phi->getNumIncomingValues() != 2u)
6786 ArrayRef<int> Mask0;
6787 ArrayRef<int> Mask1;
6800 auto const InputNumElements = InputVT->getNumElements();
6802 if (InputNumElements >= ResultVT->getNumElements())
6807 SmallVector<int, 16> NewMask;
6810 for (
auto [
M0,
M1] :
zip(Mask0, Mask1)) {
6811 if (
M0 >= 0 &&
M1 >= 0)
6813 else if (
M0 == -1 &&
M1 == -1)
6826 int MaskOffset = NewMask[0
u];
6827 unsigned Index = (InputNumElements + MaskOffset) % InputNumElements;
6830 for (
unsigned I = 0u;
I < InputNumElements; ++
I) {
6844 <<
"\n OldCost: " << OldCost <<
" vs NewCost: " << NewCost
6847 if (NewCost > OldCost)
6859 auto *NewPhi = Builder.
CreatePHI(NewShuf0->getType(), 2u);
6861 NewPhi->addIncoming(
Op,
Phi->getIncomingBlock(1u));
6867 replaceValue(*Phi, *NewShuf1);
6873bool VectorCombine::run() {
6887 auto Opcode =
I.getOpcode();
6895 if (IsFixedVectorType) {
6897 case Instruction::InsertElement:
6898 if (vectorizeLoadInsert(
I))
6901 case Instruction::ShuffleVector:
6902 if (widenSubvectorLoad(
I))
6913 if (scalarizeOpOrCmp(
I))
6915 if (scalarizeLoad(
I))
6917 if (scalarizeExtExtract(
I))
6919 if (foldInterleaveIntrinsics(
I))
6921 if (foldBitcastOfVPLoad(
I))
6925 if (foldDeinterleaveIntrinsics(
I))
6928 if (Opcode == Instruction::Store)
6929 if (foldInsertElementsToStores(
I))
6933 if (TryEarlyFoldsOnly)
6936 if (Opcode == Instruction::Call)
6937 if (foldBitOrderReverseAndSwap(
I))
6939 if (Opcode == Instruction::BitCast)
6940 if (foldBitOrderReverseAndSwap(
I))
6947 if (IsFixedVectorType) {
6949 case Instruction::InsertElement:
6950 if (foldInsExtFNeg(
I))
6952 if (foldInsExtBinop(
I))
6954 if (foldInsExtVectorToShuffle(
I))
6957 case Instruction::ShuffleVector:
6958 if (foldPermuteOfBinops(
I))
6960 if (foldShuffleOfBinops(
I))
6962 if (foldShuffleOfSelects(
I))
6964 if (foldShuffleOfCastops(
I))
6966 if (foldShuffleOfShuffles(
I))
6968 if (foldPermuteOfIntrinsic(
I))
6970 if (foldShufflesOfLengthChangingShuffles(
I))
6972 if (foldShuffleOfIntrinsics(
I))
6974 if (foldSelectShuffle(
I))
6976 if (foldShuffleToIdentity(
I))
6979 case Instruction::Load:
6980 if (shrinkLoadForShuffles(
I))
6983 case Instruction::BitCast:
6984 if (foldBitcastShuffle(
I))
6986 if (foldSelectsFromBitcast(
I))
6989 case Instruction::And:
6990 case Instruction::Or:
6991 case Instruction::Xor:
6992 if (foldBitOpOfCastops(
I))
6994 if (foldBitOpOfCastConstant(
I))
6997 case Instruction::PHI:
6998 if (shrinkPhiOfShuffles(
I))
7008 case Instruction::Call:
7009 if (foldShuffleFromReductions(
I))
7011 if (foldCastFromReductions(
I))
7014 case Instruction::ExtractElement:
7015 if (foldShuffleChainsToReduce(
I))
7018 case Instruction::ICmp:
7019 if (foldSignBitReductionCmp(
I))
7021 if (foldICmpEqZeroVectorReduce(
I))
7023 if (foldReductionZeroTest(
I))
7025 if (foldEquivalentReductionCmp(
I))
7027 if (foldReduceAddCmpZero(
I))
7030 case Instruction::FCmp:
7031 if (foldExtractExtract(
I))
7034 case Instruction::Or:
7035 if (foldConcatOfBoolMasks(
I))
7040 if (foldExtractExtract(
I))
7042 if (foldExtractedCmps(
I))
7044 if (foldBinopOfReductions(
I))
7053 bool MadeChange =
false;
7054 for (BasicBlock &BB :
F) {
7066 if (!
I->isDebugOrPseudoInst())
7067 MadeChange |= FoldInst(*
I);
7074 while (!Worklist.isEmpty()) {
7084 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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
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)
LLVM_ABI Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
ConstantInt * getTrue()
Get the constant value for i1 true.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Value * CreateIsNotNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg > -1.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Value * CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Value * CreateIsNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg < 0.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI Value * CreateNAryOp(unsigned Opc, ArrayRef< Value * > Ops, const Twine &Name="", MDNode *FPMathTag=nullptr)
Create either a UnaryOperator or BinaryOperator depending on Opc.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateFNegFMF(Value *V, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
InstructionWorklist - This is the worklist management logic for InstCombine and other simplification ...
void push(Instruction *I)
Push the instruction onto the worklist stack.
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void copyIRFlags(const Value *V, bool IncludeWrapFlags=true)
Convenience method to copy supported exact, fast-math, and (optionally) wrapping flags from V to this...
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void setNonNeg(bool b=true)
Set or clear the nneg flag on this instruction, which must be a zext instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
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.
LLVM_ABI bool willNotFreeBetween(const Instruction *Assume, const Instruction *CtxI)
Returns true, if no instruction between Assume and CtxI may free (including through synchronization).
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 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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
unsigned M1(unsigned Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI bool programUndefinedIfPoison(const Instruction *Inst)
LLVM_ABI 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.
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
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI Intrinsic::ID getReductionForBinop(Instruction::BinaryOps Opc)
Returns the reduction intrinsic id corresponding to the binary operation.
@ And
Bitwise or logical AND of integers.
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
constexpr unsigned BitWidth
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
LLVM_ABI Constant * getLosslessInvCast(Constant *C, Type *InvCastTo, unsigned CastOp, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)
Try to cast C to InvC losslessly, satisfying CastOp(InvC) equals C, or CastOp(InvC) is a refined valu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
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