60 cl::desc(
"Use partial reduction intrinsics for "
61 "all supported unordered reductions."));
69 auto IsConsecutiveAccess = [&](
VPValue *Addr,
Type *AccessTy) {
78 if (!VPBB->getParent())
81 auto EndIter = Term ? Term->getIterator() : VPBB->end();
86 VPValue *VPV = Ingredient.getVPSingleValue();
107 IsConsecutiveAccess(VPI->getOperand(0), VPI->getScalarType());
109 nullptr , IsConsecutive,
110 *VPI, Ingredient.getDebugLoc());
112 bool IsConsecutive = IsConsecutiveAccess(
113 VPI->getOperand(1), VPI->getOperand(0)->getScalarType());
115 *
Store, Ingredient.getOperand(1), Ingredient.getOperand(0),
116 nullptr , IsConsecutive, *VPI, Ingredient.getDebugLoc());
119 Ingredient.operands(), *VPI,
120 Ingredient.getDebugLoc(),
GEP);
132 if (VectorID == Intrinsic::experimental_noalias_scope_decl)
137 if (VectorID == Intrinsic::assume ||
138 VectorID == Intrinsic::lifetime_end ||
139 VectorID == Intrinsic::lifetime_start ||
140 VectorID == Intrinsic::sideeffect ||
141 VectorID == Intrinsic::pseudoprobe) {
146 const bool IsSingleScalar = VectorID != Intrinsic::assume &&
147 VectorID != Intrinsic::pseudoprobe;
151 Ingredient.getDebugLoc());
154 *CI, VectorID,
drop_end(Ingredient.operands()), CI->getType(),
155 VPIRFlags(*CI), *VPI, CI->getDebugLoc());
159 CI->getOpcode(), Ingredient.getOperand(0), CI->getType(), CI,
163 *VPI, Ingredient.getDebugLoc());
167 "inductions must be created earlier");
176 "Only recpies with zero or one defined values expected");
177 Ingredient.eraseFromParent();
188 const Loop *L =
nullptr;
193 if (
A->getOpcode() != Instruction::Store ||
194 B->getOpcode() != Instruction::Store)
207 const APInt *Distance;
213 Type *TyA =
A->getOperand(0)->getScalarType();
214 uint64_t SizeA =
DL.getTypeStoreSize(TyA);
215 Type *TyB =
B->getOperand(0)->getScalarType();
216 uint64_t SizeB =
DL.getTypeStoreSize(TyB);
221 uint64_t MaxStoreSize = std::max(SizeA, SizeB);
223 auto VFs =
B->getParent()->getPlan()->vectorFactors();
234 : ExcludeRecipes(ExcludeRecipes.begin(), ExcludeRecipes.end()),
235 GroupLeader(GroupLeader), PSE(&PSE), L(&L) {}
244 return ExcludeRecipes.contains(
Store) ||
245 (
Store && isNoAliasViaDistance(
Store, &GroupLeader));
258 std::optional<SinkStoreInfo> SinkInfo = {}) {
259 bool CheckReads = SinkInfo.has_value();
263 if (SinkInfo && SinkInfo->shouldSkip(R))
267 if (!
R.mayWriteToMemory() && !(CheckReads &&
R.mayReadFromMemory()))
292template <
unsigned Opcode>
297 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
298 "Only Load and Store opcodes supported");
299 constexpr bool IsLoad = (Opcode == Instruction::Load);
302 RecipesByAddressAndType;
306 if (RepR.getOpcode() != Opcode || !FilterFn(&RepR))
310 VPValue *Addr = RepR.getOperand(IsLoad ? 0 : 1);
314 RecipesByAddressAndType[{AddrSCEV, LoadStoreTy}].push_back(&RepR);
319 for (
auto &Group :
Groups) {
334 auto InsertIfValidSinkCandidate = [ScalarVFOnly, &WorkList](
341 if (Candidate->getParent() == SinkTo ||
342 all_of(Candidate->operands(),
343 [](
VPValue *
Op) { return Op->isDefinedOutsideLoopRegions(); }) ||
355 WorkList.
insert({SinkTo, Candidate});
367 for (
auto &Recipe : *VPBB)
369 InsertIfValidSinkCandidate(VPBB,
Op);
373 for (
unsigned I = 0;
I != WorkList.
size(); ++
I) {
376 std::tie(SinkTo, SinkCandidate) = WorkList[
I];
381 auto UsersOutsideSinkTo =
383 return cast<VPRecipeBase>(U)->getParent() != SinkTo;
385 if (
any_of(UsersOutsideSinkTo, [SinkCandidate](
VPUser *U) {
386 return !U->usesFirstLaneOnly(SinkCandidate);
389 bool NeedsDuplicating = !UsersOutsideSinkTo.empty();
391 if (NeedsDuplicating) {
395 if (
auto *SinkCandidateRepR =
400 SinkCandidateRepR->getOpcode(), SinkCandidate->
operands(),
401 nullptr, *SinkCandidateRepR, *SinkCandidateRepR,
405 Clone = SinkCandidate->
clone();
415 InsertIfValidSinkCandidate(SinkTo,
Op);
424 if (EntryBB->getNumSuccessors() != 2)
429 if (!Succ0 || !Succ1)
432 if (Succ0->getNumSuccessors() + Succ1->getNumSuccessors() != 1)
434 if (Succ0->getSingleSuccessor() == Succ1)
436 if (Succ1->getSingleSuccessor() == Succ0)
453 if (!Region1->isReplicator())
455 auto *MiddleBasicBlock =
457 if (!MiddleBasicBlock || !MiddleBasicBlock->empty())
462 if (!Region2 || !Region2->isReplicator())
465 VPValue *Mask1 = Region1->getEntryBranchOnMask()->getOperand(0);
466 VPValue *Mask2 = Region2->getEntryBranchOnMask()->getOperand(0);
467 if (!Mask1 || Mask1 != Mask2)
470 assert(Mask1 && Mask2 &&
"both region must have conditions");
476 if (TransformedRegions.
contains(Region1))
483 if (!Then1 || !Then2)
491 std::optional<VPExecutionFrequency> Freq1 =
494 if (Freq1 && Freq2) {
495 if (Freq2->Freq < Freq1->Freq) {
498 Freq1.emplace(Freq1->Freq, Freq1->IsEstimated || Freq2->IsEstimated);
522 VPValue *Phi1ToMoveV = Phi1ToMove.getVPSingleValue();
528 if (Phi1ToMove.getVPSingleValue()->user_empty()) {
529 Phi1ToMove.eraseFromParent();
532 Phi1ToMove.moveBefore(*Merge2, Merge2->begin());
546 TransformedRegions.
insert(Region1);
549 return !TransformedRegions.
empty();
557 std::string RegionName = (
Twine(
"pred.") + Instr->getOpcodeName()).str();
558 assert(Instr->getParent() &&
"Predicated instruction not in any basic block");
559 auto *BlockInMask = PredRecipe->
getMask();
574 BOMRecipe->setExecutionFrequency(RecipeWithoutMask->getExecutionFrequency(),
576 RecipeWithoutMask->clearExecutionFrequency();
585 Region->setParent(ParentRegion);
591 RecipeWithoutMask->getDebugLoc());
592 Exiting->appendRecipe(PHIRecipe);
604 if (RepR.isPredicated())
622 if (ParentRegion && ParentRegion->
getExiting() == CurrentBlock)
634 if (!VPBB->getParent())
638 if (!PredVPBB || PredVPBB->getNumSuccessors() != 1 ||
647 R.moveBefore(*PredVPBB, PredVPBB->
end());
649 auto *ParentRegion = VPBB->getParent();
650 if (ParentRegion && ParentRegion->getExiting() == VPBB)
651 ParentRegion->setExiting(PredVPBB);
655 return !WorkList.
empty();
662 bool ShouldSimplify =
true;
663 while (ShouldSimplify) {
680 if (
IV.getTruncInst())
695 for (
auto *U : FindMyCast->
users()) {
697 if (UserCast && UserCast->getUnderlyingValue() == IRCast) {
698 FoundUserCast = UserCast;
705 FindMyCast = FoundUserCast;
707 if (FindMyCast != &
IV)
732 PhiR->replaceAllUsesWith(PhiR->getOperand(0));
734 PhiR->eraseFromParent();
800 Def->user_empty() || !Def->getUnderlyingValue() ||
801 (RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
814 Def->getUnderlyingInstr()->getOpcode(), Def->operands(),
816 Def->getUnderlyingInstr());
817 Clone->insertAfter(Def);
818 Def->replaceAllUsesWith(Clone);
819 Def->eraseFromParent();
834 PtrIV->replaceAllUsesWith(PtrAdd);
841 if (HasOnlyVectorVFs &&
none_of(WideIV->users(), [WideIV](
VPUser *U) {
842 return U->usesScalars(WideIV);
851 WrapFlags = {
static_cast<bool>(WideIV->getNoWrapFlagsOrNone().HasNUW),
854 Plan, ID.getKind(), ID.getInductionOpcode(),
856 WideIV->getTruncInst(), WideIV->getStartValue(), WideIV->getStepValue(),
857 WideIV->getDebugLoc(), Builder, WrapFlags);
860 if (!HasOnlyVectorVFs) {
862 "plans containing a scalar VF cannot also include scalable VFs");
863 WideIV->replaceAllUsesWith(Steps);
866 WideIV->replaceUsesWithIf(Steps,
867 [WideIV, HasScalableVF](
VPUser &U,
unsigned) {
869 return U.usesFirstLaneOnly(WideIV);
870 return U.usesScalars(WideIV);
886 return (IntOrFpIV && IntOrFpIV->getTruncInst()) ? nullptr : WideIV;
891 if (!Def || Def->getNumOperands() != 2)
899 auto IsWideIVInc = [&]() {
900 auto &ID = WideIV->getInductionDescriptor();
903 VPValue *IVStep = WideIV->getStepValue();
904 switch (ID.getInductionOpcode()) {
905 case Instruction::Add:
907 case Instruction::FAdd:
909 case Instruction::FSub:
912 case Instruction::Sub: {
932 return IsWideIVInc() ? WideIV :
nullptr;
956 VPValue *FirstActiveLane =
B.createFirstActiveLane(Mask,
DL);
958 B.createScalarZExtOrTrunc(FirstActiveLane, CanonicalIVType,
DL);
959 VPValue *EndValue =
B.createAdd(CanonicalIV, FirstActiveLane,
DL);
964 if (Incoming != WideIV) {
966 EndValue =
B.createAdd(EndValue, One,
DL);
971 VPValue *Start = WideIV->getStartValue();
972 VPValue *Step = WideIV->getStepValue();
973 EndValue =
B.createDerivedIV(
975 Start, EndValue, Step);
989 if (WideIntOrFp && WideIntOrFp->getTruncInst())
999 Start, VectorTC, Step);
1031 assert(EndValue &&
"Must have computed the end value up front");
1036 if (Incoming != WideIV)
1048 auto *Zero = Plan.
getZero(StepTy);
1049 return B.createPtrAdd(EndValue,
B.createSub(Zero, Step),
1054 return B.createNaryOp(
1055 ID.getInductionBinOp()->getOpcode() == Instruction::FAdd
1057 : Instruction::FAdd,
1058 {EndValue, Step}, {ID.getInductionBinOp()->getFastMathFlags()});
1075 const SCEV *Start, *Step;
1093 VPValue *ExitCount = Builder.createOverflowingOp(
1096 return Builder.createDerivedIV(Kind,
nullptr, StartVPV, ExitCount,
1105 VPBuilder VectorPHBuilder(VectorPH, VectorPH->getFirstNonPhi());
1112 &WideIV, VectorPHBuilder, ResumeTC))
1113 EndValues[&WideIV] = EndValue;
1123 R.getVPSingleValue()->replaceAllUsesWith(EndValue);
1124 R.eraseFromParent();
1133 for (
auto [Idx, PredVPBB] :
enumerate(ExitVPBB->getPredecessors())) {
1135 if (PredVPBB == MiddleVPBB) {
1137 Plan, ExitIRI->getOperand(Idx), EndValues, PSE);
1140 Plan, ExitIRI->getOperand(Idx), PSE, ResumeTC, L);
1143 Plan, ExitIRI->getOperand(Idx), PSE);
1146 ExitIRI->setOperand(Idx, Escape);
1160 const auto &[V, Inserted] = SCEV2VPV.
try_emplace(ExpR.getSCEV(), &ExpR);
1164 ExpR.replaceAllUsesWith(V->second);
1168 ExpR.eraseFromParent();
1198 return Plan.
getZero(Def->getScalarType());
1215 return Def->getOperand(1);
1255 return Plan.
getZero(Def->getScalarType());
1259 Def->getScalarType() ==
A->getScalarType())
1269 if (Def->getScalarType() ==
A->getScalarType())
1279 A->getScalarType() == Def->getScalarType())
1285 return Def->getOperand(0);
1291 return BuildVector->getOperand(BuildVector->getNumOperands() - 1);
1307 return BuildVector->getOperand(BuildVector->getNumOperands() - 2);
1313 return BuildVector->getOperand(Idx);
1317 if (Def->getNumOperands() == 1) {
1318 return Def->getOperand(0);
1322 return Phi->getOperand(0);
1328 if (Def->getNumOperands() == 1 &&
1334 A->getScalarType() == Def->getScalarType())
1346 return Def->getOperand(1);
1358 return VPR->getOperand(0);
1364 return Steps->getOperand(0);
1382 Def->replaceAllUsesWith(V);
1391 RepR && RepR->isPredicated() && RepR->getOpcode() == Instruction::Store &&
1395 RepR->getUnderlyingInstr(), RepR->operandsWithoutMask(),
1396 RepR->isSingleScalar(),
nullptr, *RepR, *RepR,
1397 RepR->getDebugLoc());
1398 Unmasked->insertBefore(RepR);
1412 bool CanCreateNewRecipe =
1418 if (CanCreateNewRecipe &&
1421 return Builder.createLogicalAnd(
X,
Y);
1424 if (CanCreateNewRecipe &&
1429 (!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
1430 !Def->getOperand(1)->hasMoreThanOneUniqueUser()))
1431 return Builder.createLogicalAnd(
X, Builder.createOr(
Y, Z));
1434 if (CanCreateNewRecipe &&
1438 return Builder.createLogicalOr(Z,
Y);
1442 if (CanCreateNewRecipe &&
1444 return Builder.createNot(
C);
1448 Def->setOperand(0,
C);
1449 Def->setOperand(1,
Y);
1450 Def->setOperand(2,
X);
1455 if (CanCreateNewRecipe &&
1459 Y->getScalarType()->isIntegerTy(1))
1460 return Builder.createOr(
Y, Builder.createLogicalAnd(
X, Z));
1464 if (CanCreateNewRecipe &&
1470 return Builder.createSelect(Builder.createLogicalAnd(Mask0, Mask1),
X,
Y,
1471 Def->getDebugLoc());
1477 Type *TruncTy = Def->getScalarType();
1478 Type *XTy =
X->getScalarType();
1481 unsigned ExtOpcode =
1485 if (
auto *UnderlyingExt =
Y->getUnderlyingValue()) {
1487 Ext->setUnderlyingValue(UnderlyingExt);
1491 auto *Trunc = Builder.createWidenCast(Instruction::Trunc,
X, TruncTy);
1500 return Builder.createSub(Plan.
getZero(
X->getScalarType()),
X,
1501 Def->getDebugLoc(),
"", NW);
1504 if (CanCreateNewRecipe &&
1512 return Builder.createSub(
X,
Y, Def->getDebugLoc(),
"", NW);
1519 Def->getDebugLoc());
1526 MulR->hasNoSignedWrap() &&
1528 return Builder.createNaryOp(
1531 Def->getDebugLoc());
1536 return Builder.createNaryOp(
1549 return match(U, m_Not(m_Specific(Cmp))) ||
1550 (match(U, m_Select(m_Specific(Cmp), m_VPValue(),
1552 U->getOperand(1) != Cmp && U->getOperand(2) != Cmp);
1559 R->setOperand(1,
Y);
1560 R->setOperand(2,
X);
1564 R->replaceAllUsesWith(Cmp);
1569 if (!Cmp->getDebugLoc() && Def->getDebugLoc())
1570 Cmp->setDebugLoc(Def->getDebugLoc());
1583 if (
Op->getNumUsers() > 1 ||
1587 }
else if (!UnpairedCmp) {
1588 UnpairedCmp =
Op->getDefiningRecipe();
1592 UnpairedCmp =
nullptr;
1599 if (NewOps.
size() < Def->getNumOperands())
1606 if (CanCreateNewRecipe &&
1615 X->getScalarType() != Def->getScalarType())
1616 return Builder.createWidenCast(Instruction::Trunc,
X, Def->getScalarType());
1623 Def->getScalarType()->isIntegerTy(1)) {
1624 Def->setOperand(1, Plan.
getTrue());
1625 Def->setOperand(0,
Y);
1635 Def->replaceUsesWithIf(Def->getOperand(0), [Def](
VPUser &U,
unsigned) {
1636 return U.usesFirstLaneOnly(Def);
1646 "broadcast operand must be single-scalar");
1647 Def->setOperand(0, Z);
1652 Def->replaceUsesWithIf(
1653 X, [Def](
const VPUser &U,
unsigned) {
return U.usesScalars(Def); });
1665 return Builder.createNaryOp(Instruction::ExtractElement, {
X, LaneToExtract},
1666 Def->getDebugLoc());
1678 IVInc->getNumUsers() == 2) {
1684 if ((Phi->getNumUsers() == 1 || (Phi->getNumUsers() == 2 && Inc)) &&
1686 Def->replaceAllUsesWith(IVInc);
1688 Inc->replaceAllUsesWith(Phi);
1689 Phi->setOperand(0,
Y);
1698 Def->replaceUsesWithIf(StartV, [](
const VPUser &U,
unsigned Idx) {
1700 return PhiR && PhiR->isInLoop();
1717 [[maybe_unused]]
unsigned InitWorklistSize = Worklist.
size();
1719 while (!Worklist.
empty()) {
1720 assert(Worklist.
size() < InitWorklistSize * 2 &&
1721 "Worklist is growing large, possible cycle?");
1728 Def->replaceAllUsesWith(New);
1729 Def->eraseFromParent();
1734 Def->eraseFromParent();
1752 R.getVPSingleValue()->replaceAllUsesWith(
X);
1768 while (!Worklist.
empty()) {
1777 R->replaceAllUsesWith(
1778 Builder.createLogicalAnd(HeaderMask, Builder.createLogicalAnd(
X,
Y)));
1782static std::optional<Instruction::BinaryOps>
1785 case Intrinsic::masked_udiv:
1786 return Instruction::UDiv;
1787 case Intrinsic::masked_sdiv:
1788 return Instruction::SDiv;
1789 case Intrinsic::masked_urem:
1790 return Instruction::URem;
1791 case Intrinsic::masked_srem:
1792 return Instruction::SRem;
1809 if (RepR && (RepR->isSingleScalar() || RepR->isPredicated()))
1813 if (RepR && RepR->getOpcode() == Instruction::Store &&
1816 RepOrWidenR->getUnderlyingInstr(), RepOrWidenR->operands(),
1817 true ,
nullptr , *RepR ,
1818 *RepR , RepR->getDebugLoc());
1819 Clone->insertBefore(RepOrWidenR);
1821 VPValue *ExtractOp = Clone->getOperand(0);
1827 Clone->setOperand(0, ExtractOp);
1828 RepR->eraseFromParent();
1840 VPValue *SafeDivisor = Builder.createSelect(
1841 IntrR->getOperand(2), IntrR->getOperand(1),
1843 VPValue *Clone = Builder.createNaryOp(
1844 *
Opc, {IntrR->getOperand(0), SafeDivisor},
1847 IntrR->eraseFromParent();
1856 auto IntroducesBCastOf = [](
const VPValue *
Op) {
1865 return !U->usesScalars(
Op);
1869 if (
any_of(RepOrWidenR->users(), IntroducesBCastOf(RepOrWidenR)) &&
1872 make_filter_range(Op->users(), not_equal_to(RepOrWidenR)),
1873 IntroducesBCastOf(Op)))
1877 bool LiveInNeedsBroadcast =
1878 isa<VPIRValue>(Op) && !isa<VPConstant>(Op);
1879 auto *OpR = dyn_cast<VPReplicateRecipe>(Op);
1880 return LiveInNeedsBroadcast || (OpR && OpR->isSingleScalar());
1888 Clone->insertBefore(RepOrWidenR);
1889 RepOrWidenR->replaceAllUsesWith(Clone);
1891 RepOrWidenR->eraseFromParent();
1924 if (Blend.isNormalized() || !
match(Blend.getMask(0),
m_False()))
1925 UniqueValues.
insert(Blend.getIncomingValue(0));
1926 for (
unsigned I = 1;
I != Blend.getNumIncomingValues(); ++
I)
1928 UniqueValues.
insert(Blend.getIncomingValue(
I));
1930 if (UniqueValues.
size() == 1) {
1931 Blend.replaceAllUsesWith(*UniqueValues.
begin());
1932 Blend.eraseFromParent();
1936 if (Blend.isNormalized())
1942 unsigned StartIndex = 0;
1943 for (
unsigned I = 0;
I != Blend.getNumIncomingValues(); ++
I) {
1955 OperandsWithMask.
push_back(Blend.getIncomingValue(StartIndex));
1957 for (
unsigned I = 0;
I != Blend.getNumIncomingValues(); ++
I) {
1958 if (
I == StartIndex)
1960 OperandsWithMask.
push_back(Blend.getIncomingValue(
I));
1961 OperandsWithMask.
push_back(Blend.getMask(
I));
1966 OperandsWithMask, Blend, Blend.getDebugLoc());
1967 NewBlend->insertBefore(&Blend);
1969 VPValue *DeadMask = Blend.getMask(StartIndex);
1971 Blend.eraseFromParent();
1976 if (NewBlend->getNumOperands() == 3 &&
1978 VPValue *Inc0 = NewBlend->getOperand(0);
1979 VPValue *Inc1 = NewBlend->getOperand(1);
1980 VPValue *OldMask = NewBlend->getOperand(2);
1981 NewBlend->setOperand(0, Inc1);
1982 NewBlend->setOperand(1, Inc0);
1983 NewBlend->setOperand(2, NewMask);
2010 APInt MaxVal = AlignedTC - 1;
2013 unsigned NewBitWidth =
2019 bool MadeChange =
false;
2044 "canonical IV is not expected to have a truncation");
2049 NewWideIV->insertBefore(WideIV);
2056 Cmp->replaceAllUsesWith(
2057 VPBuilder(Cmp).createICmp(Cmp->getPredicate(), NewWideIV, NewBTC));
2071 return any_of(
Cond->getDefiningRecipe()->operands(), [&Plan, BestVF, BestUF,
2073 return isConditionTrueViaVFAndUF(C, Plan, BestVF, BestUF, PSE);
2087 const SCEV *VectorTripCount =
2092 "Trip count SCEV must be computable");
2107 bool MadeChange =
false;
2115 for (
VPBasicBlock *VPBB : {PreheaderVPBB, ExitingVPBB}) {
2124 Builder.setInsertPoint(Extract);
2127 Start = Builder.createAdd(
2132 Extract->eraseFromParent();
2147 auto *Term = &ExitingVPBB->
back();
2153 bool MatchedCanIVInc =
2159 if (MatchedCanIVInc ||
2167 const SCEV *VectorTripCount =
2173 "Trip count SCEV must be computable");
2192 Term->setOperand(1, Plan.
getTrue());
2197 {}, Term->getDebugLoc());
2199 Term->eraseFromParent();
2207 assert(Plan.
hasVF(BestVF) &&
"BestVF is not available in Plan");
2208 assert(Plan.
hasUF(BestUF) &&
"BestUF is not available in Plan");
2224 RecurKind RK = PhiR.getRecurrenceKind();
2231 RecWithFlags->dropPoisonGeneratingFlags();
2237struct VPCSEDenseMapInfo :
public DenseMapInfo<VPSingleDefRecipe *> {
2246 return GEP->getSourceElementType();
2249 .Case<VPVectorPointerRecipe, VPWidenGEPRecipe>(
2250 [](
auto *
I) {
return I->getSourceElementType(); })
2251 .
Default([](
auto *) {
return nullptr; });
2255 static bool canHandle(
const VPSingleDefRecipe *Def) {
2264 if (!
C || (!
C->first && (
C->second == Instruction::InsertValue ||
2265 C->second == Instruction::ExtractValue)))
2271 if (
Def->mayWriteToMemory())
2273 return !
Def->mayReadFromMemory() ||
2278 static unsigned getHashValue(
const VPSingleDefRecipe *Def) {
2281 getGEPSourceElementType(Def),
Def->getScalarType(),
2284 if (RFlags->hasPredicate())
2287 return hash_combine(Result, SIVSteps->getInductionOpcode());
2296 static bool isEqual(
const VPSingleDefRecipe *L,
const VPSingleDefRecipe *R) {
2297 if (
L->getVPRecipeID() !=
R->getVPRecipeID() ||
2300 getGEPSourceElementType(L) != getGEPSourceElementType(R) ||
2302 !
equal(
L->operands(),
R->operands()))
2306 "must have valid opcode info for both recipes");
2308 if (LFlags->hasPredicate() &&
2309 LFlags->getPredicate() !=
2313 if (LSIV->getInductionOpcode() !=
2328 const VPRegionBlock *RegionL =
L->getRegion();
2329 const VPRegionBlock *RegionR =
R->getRegion();
2332 L->getParent() !=
R->getParent())
2334 return L->getScalarType() ==
R->getScalarType();
2353 if (R.mayWriteToMemory())
2356 if (!Def || !VPCSEDenseMapInfo::canHandle(Def))
2359 auto [It, Inserted] =
2360 (IsLoad ? LoadCSEMap : CSEMap).try_emplace(Def, Def);
2365 if (!VPDT.
dominates(V->getParent(), VPBB))
2370 if (EarlierLoad->getAlign() <
Load->getAlign()) {
2377 EarlierLoad->intersect(*
Load);
2382 Def->replaceAllUsesWith(V);
2393 bool Sinking =
false) {
2422 "Expected vector prehader's successor to be the vector loop region");
2427 return !Op->isDefinedOutsideLoopRegions();
2433 R.moveBefore(*Preheader, Preheader->
end());
2454 assert(!RepR->isPredicated() &&
2455 "Expected prior transformation of predicated replicates to "
2456 "replicate regions");
2461 if (!RepR->isSingleScalar())
2465 if (RepR->getOpcode() == Instruction::Store &&
2466 !RepR->getOperand(1)->isDefinedOutsideLoopRegions())
2474 if (
any_of(Def->users(), [&SinkBB, &LoopRegion](
VPUser *U) {
2475 auto *UserR = cast<VPRecipeBase>(U);
2476 VPBasicBlock *Parent = UserR->getParent();
2478 if (SinkBB && SinkBB != Parent)
2483 return UserR->isPhi() || Parent->getEnclosingLoopRegion() ||
2484 Parent->getSinglePredecessor() != LoopRegion;
2494 assert((!R.mayWriteToMemory() ||
2495 (RepR && RepR->getOpcode() == Instruction::Store &&
2496 RepR->getOperand(1)->isDefinedOutsideLoopRegions())) &&
2497 "The only recipes that may write to memory are expected to be "
2498 "stores with invariant pointer-operand");
2506 "Defining block must dominate sink block");
2531 VPValue *ResultVPV = R.getVPSingleValue();
2533 unsigned NewResSizeInBits = MinBWs.
lookup(UI);
2534 if (!NewResSizeInBits)
2547 (void)OldResSizeInBits;
2555 VPW->dropPoisonGeneratingFlags();
2557 assert((OldResSizeInBits != NewResSizeInBits ||
2559 "Only ICmps should not need extending the result.");
2572 unsigned OpSizeInBits =
Op->getScalarType()->getScalarSizeInBits();
2573 if (OpSizeInBits == NewResSizeInBits)
2575 assert(OpSizeInBits > NewResSizeInBits &&
"nothing to truncate");
2576 auto [ProcessedIter, Inserted] = ProcessedTruncs.
try_emplace(
Op);
2582 Builder.setInsertPoint(&R);
2583 ProcessedIter->second =
2584 Builder.createWidenCast(Instruction::Trunc,
Op, NewResTy);
2586 Op = ProcessedIter->second;
2590 NWR->insertBefore(&R);
2595 VPValue *Replacement = NWR->getVPSingleValue();
2602 R.eraseFromParent();
2608 std::optional<VPDominatorTree> VPDT;
2616 bool SimplifiedPhi =
false;
2626 assert(VPBB->getNumSuccessors() == 2 &&
2627 "Two successors expected for BranchOnCond");
2628 unsigned RemovedIdx;
2639 "There must be a single edge between VPBB and its successor");
2644 SimplifiedPhi =
true;
2648 if (!PhiR || PhiR->getNumIncoming() != 1)
2650 PhiR->replaceAllUsesWith(PhiR->getOperand(0));
2651 PhiR->eraseFromParent();
2656 VPBB->back().eraseFromParent();
2668 if (Reachable.contains(
B))
2679 for (
VPValue *Def : R.definedValues())
2680 Def->replaceAllUsesWith(&Tmp);
2681 R.eraseFromParent();
2685 return SimplifiedPhi;
2711 auto GetSimplifiedLiveInViaSCEV = [&](
VPValue *VPV) ->
VPValue * {
2720 if (
VPValue *SimplifiedLiveIn = GetSimplifiedLiveInViaSCEV(LiveIn))
2721 LiveIn->replaceAllUsesWith(SimplifiedLiveIn);
2732 "expected to run before loop regions are created");
2734 auto CanUseVersionedStride = [&VPDT, Header = Header, &Plan](
VPUser &U,
2741 return VPDT.
dominates(Header, R->getParent());
2745 Value *StrideV = Stride->getValue();
2746 const APInt *StrideConst;
2753 CanUseVersionedStride);
2767 CanUseVersionedStride);
2769 RewriteMap[StrideV] = StrideExpr;
2774 const SCEV *ScevExpr = ExpSCEV.getSCEV();
2777 if (NewSCEV != ScevExpr) {
2779 ExpSCEV.replaceAllUsesWith(NewExp);
2790 auto CollectPoisonGeneratingInstrsInBackwardSlice([&](
VPRecipeBase *Root) {
2795 while (!Worklist.
empty()) {
2798 if (!Visited.
insert(CurRec).second)
2820 RecWithFlags->isDisjoint()) {
2823 Builder.createAdd(
A,
B, RecWithFlags->getDebugLoc());
2824 New->setUnderlyingValue(RecWithFlags->getUnderlyingValue());
2825 RecWithFlags->replaceAllUsesWith(New);
2826 RecWithFlags->eraseFromParent();
2829 RecWithFlags->dropPoisonGeneratingFlags();
2834 assert((!Instr || !Instr->hasPoisonGeneratingFlags()) &&
2835 "found instruction with poison generating flags not covered by "
2836 "VPRecipeWithIRFlags");
2841 if (
VPRecipeBase *OpDef = Operand->getDefiningRecipe())
2863 VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
2864 if (AddrDef && WidenRec->isConsecutive() && WidenRec->getMask() &&
2865 match(WidenRec->getMask(), m_UnlessHdrMask))
2866 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
2868 VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
2869 if (AddrDef && InterleaveRec->getMask() &&
2870 match(InterleaveRec->getMask(), m_UnlessHdrMask))
2871 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
2881 const bool &EpilogueAllowed) {
2882 if (InterleaveGroups.empty())
2893 IRMemberToRecipe[&MemR->getIngredient()] = MemR;
2900 for (
const auto *IG : InterleaveGroups) {
2903 for (
auto *Member : IG->members())
2905 StartMember = Member;
2913 for (
unsigned I = 0;
I < IG->getFactor(); ++
I) {
2919 StoredValues.
push_back(StoreR->getStoredValue());
2926 bool NeedsMaskForGaps =
2927 (IG->requiresScalarEpilogue() && !EpilogueAllowed) ||
2928 (!StoredValues.
empty() && !IG->isFull());
2931 auto *InsertPos = IRMemberToRecipe.
lookup(IRInsertPos);
2935 "Dead member in non-load group?");
2940 InsertPos->getAsRecipe()))
2941 InsertPos = MemberR;
2942 IRInsertPos = &InsertPos->getIngredient();
2952 VPValue *Addr = Start->getAddr();
2954 if (IG->getIndex(StartMember) != 0 ||
2962 assert(IG->getIndex(IRInsertPos) != 0 &&
2963 "index of insert position shouldn't be zero");
2967 IG->getIndex(IRInsertPos),
2971 Addr =
B.createNoWrapPtrAdd(InsertPos->getAddr(), OffsetVPV, NW);
2977 if (IG->isReverse()) {
2980 -(int64_t)IG->getFactor(), NW, InsertPosR->
getDebugLoc());
2981 ReversePtr->insertBefore(InsertPosR);
2985 IG, Addr, StoredValues, InsertPos->getMask(), NeedsMaskForGaps,
2987 VPIG->insertBefore(InsertPosR);
2990 for (
unsigned i = 0; i < IG->getFactor(); ++i)
2993 if (!Member->getType()->isVoidTy()) {
3065 VPValue *UncountableCondition =
nullptr;
3072 Worklist.
push_back(UncountableCondition);
3073 while (!Worklist.
empty()) {
3077 if (V->isDefinedOutsideLoopRegions())
3083 if (V->getNumUsers() > 1)
3115 if (Recipes.
empty() ||
3119 return UncountableCondition;
3176 for (
auto &Exit : Exits) {
3177 if (Exit.EarlyExitingVPBB == LatchVPBB)
3181 cast<VPIRPhi>(&R)->removeIncomingValueFor(Exit.EarlyExitingVPBB);
3182 Exit.EarlyExitingVPBB->getTerminator()->eraseFromParent();
3196 "loop with side effects",
3197 "EarlyExitSideEffectsCond", ORE, TheLoop);
3212 assert(
Load &&
"Couldn't find exactly one load");
3215 "Uncountable exit condition load is conditional.");
3229 DL.getTypeStoreSize(
Load->getScalarType()).getFixedValue());
3235 "load used by the exit condition that may "
3237 "EarlyExitSideEffectsFaultingLoad", ORE,
3250 "load used by the exit condition with an "
3251 "unsupported memory access pattern",
3252 "EarlyExitSideEffectsBadLoadAccessPattern", ORE,
3260 "load used by the exit condition with an "
3261 "unsupported memory access pattern",
3262 "EarlyExitSideEffectsBadLoadAccessPattern", ORE,
3272 while (InsertIt != HeaderVPBB->
end() &&
3274 erase(ConditionRecipes, &*InsertIt);
3277 for (
auto *Recipe :
reverse(ConditionRecipes))
3278 Recipe->moveBefore(*HeaderVPBB, InsertIt);
3282 VPBuilder MaskBuilder(HeaderVPBB, InsertIt);
3284 Type *IVScalarTy =
IV->getScalarType();
3290 "uncountable.exit.mask");
3295 if (R.mayReadOrWriteMemory() && &R !=
Load) {
3297 if (!VPDT.
dominates(R.getParent(), LatchVPBB)) {
3299 "Early exit loop with side effects contains unsupported "
3300 "conditional memory operations",
3301 "EarlyExitSideEffectsUnsupportedConditionalMemOps", ORE, TheLoop);
3312 "Expected BranchOnCond terminator for MiddleVPBB");
3323 auto Phis = ScalarPH->
phis();
3328 "Early exit loop with side effects contains "
3329 "unsupported reductions, inductions or recurrences",
3330 "EarlyExitSideEffectsReductions", ORE, TheLoop);
3338 "Continuing from different IV");
3360 "Auto-vectorization of early exit loops with potentially "
3361 "faulting loads is not supported",
3362 "EarlyExitFaultingLoads", ORE, TheLoop);
3366 VPBuilder LatchBuilder(LatchVPBB->getTerminator());
3368 for (
auto [EarlyExitingVPBB, ExitBlock] :
3372 VPValue *CondOfEarlyExitingVPBB;
3373 [[maybe_unused]]
bool Matched =
3374 match(EarlyExitingVPBB->getTerminator(),
3376 assert(Matched &&
"Terminator must be BranchOnCond");
3380 VPBuilder EarlyExitingBuilder(EarlyExitingVPBB->getTerminator());
3381 auto *CondToEarlyExit = EarlyExitingBuilder.
createNaryOp(
3383 TrueSucc == ExitBlock
3384 ? CondOfEarlyExitingVPBB
3385 : EarlyExitingBuilder.
createNot(CondOfEarlyExitingVPBB));
3391 "exit condition must dominate the latch");
3399 assert(!Exits.
empty() &&
"must have at least one early exit");
3406 for (
const auto &[Num, VPB] :
enumerate(RPOT))
3409 return RPOIdx[
A.EarlyExitingVPBB] < RPOIdx[
B.EarlyExitingVPBB];
3415 for (
unsigned I = 0;
I + 1 < Exits.
size(); ++
I)
3416 for (
unsigned J =
I + 1; J < Exits.
size(); ++J)
3418 Exits[
I].EarlyExitingVPBB) &&
3419 "RPO sort must place dominating exits before dominated ones");
3425 VPValue *Combined = Exits[0].CondToExit;
3445 "Unexpected terminator");
3446 VPValue *IsLatchExitTaken = LatchExitingBranch->getOperand(0);
3447 DebugLoc LatchDL = LatchExitingBranch->getDebugLoc();
3448 LatchExitingBranch->eraseFromParent();
3451 {IsAnyExitTaken, IsLatchExitTaken}, LatchDL);
3452 LatchVPBB->clearSuccessors();
3457 LatchVPBB->setSuccessors({MiddleVPBB, MiddleVPBB, HeaderVPBB});
3458 MiddleVPBB->clearPredecessors();
3459 MiddleVPBB->setPredecessors({LatchVPBB, LatchVPBB});
3461 LatchVPBB, MiddleVPBB, ORE,
3462 TheLoop, PSE, DT, AC);
3467 for (
unsigned Idx = 0; Idx != Exits.
size(); ++Idx) {
3471 VectorEarlyExitVPBBs[Idx] = VectorEarlyExitVPBB;
3479 Exits.
size() == 1 ? VectorEarlyExitVPBBs[0]
3482 LatchVPBB->setSuccessors({DispatchVPBB, MiddleVPBB, HeaderVPBB});
3514 for (
auto [Exit, VectorEarlyExitVPBB] :
3515 zip_equal(Exits, VectorEarlyExitVPBBs)) {
3516 auto &[EarlyExitingVPBB, EarlyExitVPBB,
_] = Exit;
3528 ExitIRI->getIncomingValueForBlock(EarlyExitingVPBB);
3529 VPValue *NewIncoming = IncomingVal;
3531 VPBuilder EarlyExitBuilder(VectorEarlyExitVPBB);
3536 ExitIRI->removeIncomingValueFor(EarlyExitingVPBB);
3537 ExitIRI->addIncoming(NewIncoming);
3540 EarlyExitingVPBB->getTerminator()->eraseFromParent();
3574 bool IsLastDispatch = (
I + 2 == Exits.
size());
3576 IsLastDispatch ? VectorEarlyExitVPBBs.
back()
3582 VectorEarlyExitVPBBs[
I]->setPredecessors({CurrentBB});
3585 CurrentBB = FalseBB;
3600 VPValue *VecOp = Red->getVecOp();
3603 if (Red->isPartialReduction())
3607 auto IsExtendedRedValidAndClampRange =
3620 "getExtendedReductionCost only supports integer types");
3621 ExtRedCost = Ctx.TTI.getExtendedReductionCost(
3622 Opcode, ExtOpc == Instruction::CastOps::ZExt, RedTy, SrcVecTy,
3623 Red->getFastMathFlagsOrNone(),
CostKind);
3624 return ExtRedCost.
isValid() && ExtRedCost < ExtCost + RedCost;
3632 IsExtendedRedValidAndClampRange(
3653 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3654 Opcode != Instruction::FAdd)
3658 if (Red->isPartialReduction())
3664 auto IsMulAccValidAndClampRange =
3676 (Ext0->getOpcode() != Ext1->getOpcode() ||
3677 Ext0->getOpcode() == Instruction::CastOps::FPExt))
3681 !Ext0 || Ext0->getOpcode() == Instruction::CastOps::ZExt;
3683 MulAccCost = Ctx.TTI.getMulAccReductionCost(IsZExt, Opcode, RedTy,
3690 ExtCost += Ext0->computeCost(VF, Ctx);
3692 ExtCost += Ext1->computeCost(VF, Ctx);
3694 ExtCost += OuterExt->computeCost(VF, Ctx);
3696 return MulAccCost.
isValid() &&
3697 MulAccCost < ExtCost + MulCost + RedCost;
3702 VPValue *VecOp = Red->getVecOp();
3740 Builder.createWidenCast(Instruction::CastOps::Trunc, ValB, NarrowTy);
3742 ValB = ExtB = Builder.createWidenCast(ExtOpc, Trunc, WideTy);
3743 Mul->setOperand(1, ExtB);
3753 ExtendAndReplaceConstantOp(RecipeA, RecipeB,
B,
Mul);
3758 IsMulAccValidAndClampRange(
Mul, RecipeA, RecipeB,
nullptr)) {
3765 if (!
Sub && IsMulAccValidAndClampRange(
Mul,
nullptr,
nullptr,
nullptr))
3782 ExtendAndReplaceConstantOp(Ext0, Ext1,
B,
Mul);
3791 (Ext->getOpcode() == Ext0->getOpcode() || Ext0 == Ext1) &&
3792 Ext0->getOpcode() == Ext1->getOpcode() &&
3793 IsMulAccValidAndClampRange(
Mul, Ext0, Ext1, Ext) &&
Mul->hasOneUse()) {
3795 Ext0->getOpcode(), Ext0->getOperand(0), Ext->getScalarType(),
nullptr,
3796 *Ext0, *Ext0, Ext0->getDebugLoc());
3797 NewExt0->insertBefore(Ext0);
3802 Ext->getScalarType(),
nullptr, *Ext1,
3803 *Ext1, Ext1->getDebugLoc());
3806 auto *NewMul =
Mul->cloneWithOperands({NewExt0, NewExt1});
3807 NewMul->insertBefore(
Mul);
3808 Ext->replaceAllUsesWith(NewMul);
3809 Ext->eraseFromParent();
3810 Mul->eraseFromParent();
3824 if (Red->isPartialReduction())
3828 auto IP = std::next(Red->getIterator());
3829 auto *VPBB = Red->getParent();
3839 Red->replaceAllUsesWith(AbstractR);
3861 return CommonMetadata;
3864template <
unsigned Opcode>
3869 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
3870 "Only Load and Store opcodes supported");
3871 [[maybe_unused]]
constexpr bool IsLoad = (Opcode == Instruction::Load);
3878 for (
auto Recipes :
Groups) {
3879 if (Recipes.size() < 2)
3884 "Expected all recipes in group to have the same load-store type");
3891 VPValue *MaskI = RecipeI->getMask();
3897 bool HasComplementaryMask =
false;
3902 VPValue *MaskJ = RecipeJ->getMask();
3911 if (HasComplementaryMask) {
3912 assert(Group.
size() >= 2 &&
"must have at least 2 entries");
3922template <
typename InstType>
3940 for (
auto &Group :
Groups) {
3960 return R->isSingleScalar() == IsSingleScalar;
3962 "all members in group must agree on IsSingleScalar");
3967 LoadWithMinAlign->getUnderlyingInstr(), {EarliestLoad->getOperand(0)},
3968 IsSingleScalar,
nullptr, *EarliestLoad, CommonMetadata);
3970 UnpredicatedLoad->insertBefore(EarliestLoad);
3974 Load->replaceAllUsesWith(UnpredicatedLoad);
3975 Load->eraseFromParent();
3984 if (!StoreLoc || !StoreLoc->AATags.Scope)
3991 SinkStoreInfo SinkInfo(StoresToSink, *StoresToSink[0], PSE, L);
4003 for (
auto &Group :
Groups) {
4016 VPValue *SelectedValue = Group[0]->getOperand(0);
4019 bool IsSingleScalar = Group[0]->isSingleScalar();
4020 for (
unsigned I = 1;
I < Group.size(); ++
I) {
4021 assert(IsSingleScalar == Group[
I]->isSingleScalar() &&
4022 "all members in group must agree on IsSingleScalar");
4023 VPValue *Mask = Group[
I]->getMask();
4025 SelectedValue = Builder.createSelect(
4028 Value->getScalarType()));
4036 StoreWithMinAlign->getUnderlyingInstr(),
4037 {SelectedValue, LastStore->getOperand(1)}, IsSingleScalar,
4038 nullptr, *LastStore, CommonMetadata);
4039 UnpredicatedStore->insertBefore(*InsertBB, LastStore->
getIterator());
4043 Store->eraseFromParent();
4058 VPValue *OpV,
unsigned Idx,
bool IsScalable) {
4063 if (Member0Op == OpV)
4073 return !IsScalable && !W->getMask() && W->isConsecutive() &&
4076 return IR->getInterleaveGroup()->isFull() &&
IR->getVPValue(Idx) == OpV;
4091 if (R->getScalarType() != WideMember0->getScalarType())
4093 if (R->hasPredicate() && R->getPredicate() != WideMember0->getPredicate())
4097 for (
unsigned Idx = 0; Idx != WideMember0->getNumOperands(); ++Idx) {
4100 OpsI.
push_back(
Op->getDefiningRecipe()->getOperand(Idx));
4105 if (
any_of(
enumerate(OpsI), [WideMember0, Idx, IsScalable](
const auto &
P) {
4106 const auto &[OpIdx, OpV] =
P;
4107 return !
canNarrowLoad(WideMember0, Idx, OpV, OpIdx, IsScalable);
4118static std::optional<ElementCount>
4122 if (!InterleaveR || InterleaveR->
getMask())
4123 return std::nullopt;
4125 Type *GroupElementTy =
nullptr;
4129 return Op->getScalarType() == GroupElementTy;
4131 return std::nullopt;
4135 return Op->getScalarType() == GroupElementTy;
4137 return std::nullopt;
4141 if (IG->getFactor() != IG->getNumMembers())
4142 return std::nullopt;
4148 assert(
Size.isScalable() == VF.isScalable() &&
4149 "if Size is scalable, VF must be scalable and vice versa");
4150 return Size.getKnownMinValue();
4154 unsigned MinVal = VF.getKnownMinValue();
4156 if (IG->getFactor() == MinVal && GroupSize == GetVectorBitWidthForVF(VF))
4159 return std::nullopt;
4167 return RepR && RepR->isSingleScalar();
4181 if (V->isDefinedOutsideLoopRegions()) {
4184 return M->isDefinedOutsideLoopRegions() &&
4185 M->getScalarType() == V->getScalarType();
4187 "expected distinct loop-invariant values of matching scalar type");
4202 for (
unsigned Idx = 0,
E = WideMember0->getNumOperands(); Idx !=
E; ++Idx) {
4204 for (
VPValue *Member : Members)
4205 OpsI.
push_back(Member->getDefiningRecipe()->getOperand(Idx));
4206 WideMember0->setOperand(
4215 auto *LI =
cast<LoadInst>(LoadGroup->getInterleaveGroup()->getInsertPos());
4217 *LI, LoadGroup->getAddr(), LoadGroup->getMask(),
true,
4218 *LoadGroup, LoadGroup->getDebugLoc());
4224 assert(RepR->isSingleScalar() && RepR->getOpcode() == Instruction::Load &&
4225 "must be a single scalar load");
4226 NarrowedOps.
insert(RepR);
4231 VPValue *PtrOp = WideLoad->getAddr();
4233 PtrOp = VecPtr->getOperand(0);
4238 nullptr, {}, *WideLoad);
4239 N->insertBefore(WideLoad);
4244std::unique_ptr<VPlan>
4264 "unexpected branch-on-count");
4267 std::optional<ElementCount> VFToOptimize;
4281 if (R.mayWriteToMemory() && !InterleaveR)
4287 return any_of(V->users(), [&](VPUser *U) {
4288 auto *UR = cast<VPRecipeBase>(U);
4289 return UR->getParent()->getParent() != VectorLoop;
4306 std::optional<ElementCount> NarrowedVF =
4308 if (!NarrowedVF || (VFToOptimize && NarrowedVF != VFToOptimize))
4310 VFToOptimize = NarrowedVF;
4313 if (InterleaveR->getStoredValues().empty())
4318 auto *Member0 = InterleaveR->getStoredValues()[0];
4328 VPRecipeBase *DefR = Op.value()->getDefiningRecipe();
4331 auto *IR = dyn_cast<VPInterleaveRecipe>(DefR);
4332 return IR && IR->getInterleaveGroup()->isFull() &&
4333 IR->getVPValue(Op.index()) == Op.value();
4342 VFToOptimize->isScalable()))
4347 if (StoreGroups.empty())
4351 bool RequiresScalarEpilogue =
4362 std::unique_ptr<VPlan> NewPlan;
4364 NewPlan = std::unique_ptr<VPlan>(Plan.
duplicate());
4365 Plan.
setVF(*VFToOptimize);
4366 NewPlan->removeVF(*VFToOptimize);
4373 for (
auto *StoreGroup : StoreGroups) {
4375 NarrowedOps, Preheader);
4381 StoreGroup->getDebugLoc());
4388 Type *CanIVTy = VectorLoop->getCanonicalIVType();
4394 if (VFToOptimize->isScalable()) {
4397 Step = PHBuilder.createOverflowingOp(Instruction::Mul, {VScale,
UF},
4405 materializeVectorTripCount(Plan, VectorPH,
false,
4406 RequiresScalarEpilogue, Step);
4411 removeDeadRecipes(Plan);
4414 "All VPVectorPointerRecipes should have been removed");
4432 "Cannot handle loops with uncountable early exits");
4439 assert(RecurSplice &&
"expected FirstOrderRecurrenceSplice");
4446 if (
any_of(RecurSplice->users(),
4447 [](
VPUser *U) { return !cast<VPRecipeBase>(U)->getRegion(); }) &&
4528 {},
"vector.recur.extract.for.phi");
4531 ExitPhi->replaceUsesOfWith(ExtractR, PenultimateElement);
4545 VPValue *WidenIVCandidate = BinOp->getOperand(0);
4546 VPValue *InvariantCandidate = BinOp->getOperand(1);
4548 std::swap(WidenIVCandidate, InvariantCandidate);
4562 auto *ClonedOp = BinOp->
clone();
4563 if (ClonedOp->getOperand(0) == WidenIV) {
4564 ClonedOp->setOperand(0, ScalarIV);
4566 assert(ClonedOp->getOperand(1) == WidenIV &&
"one operand must be WideIV");
4567 ClonedOp->setOperand(1, ScalarIV);
4581 return std::nullopt;
4586 return std::nullopt;
4598 auto CheckSentinel = [&SE](
const SCEV *IVSCEV,
4599 bool UseMax) -> std::optional<APSInt> {
4601 for (
bool Signed : {
true,
false}) {
4610 return std::nullopt;
4618 PhiR->getRecurrenceKind()))
4627 VPValue *BackedgeVal = PhiR->getBackedgeValue();
4641 !
match(FindLastSelect,
4650 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression, PSE,
4655 "IVOfExpressionToSink not being an AddRec must imply "
4656 "FindLastExpression not being an AddRec.");
4665 bool UseMax = *StepDirection;
4666 std::optional<APSInt> SentinelVal = CheckSentinel(IVSCEV, UseMax);
4667 bool UseSigned = SentinelVal && SentinelVal->isSigned();
4674 if (IVOfExpressionToSink) {
4675 const SCEV *FindLastExpressionSCEV =
4677 if (std::optional<bool> NewUseMax =
4679 if (
auto NewSentinel =
4680 CheckSentinel(FindLastExpressionSCEV, *NewUseMax)) {
4683 SentinelVal = *NewSentinel;
4684 UseSigned = NewSentinel->isSigned();
4685 UseMax = *NewUseMax;
4686 IVSCEV = FindLastExpressionSCEV;
4687 IVOfExpressionToSink =
nullptr;
4697 if (AR->hasNoSignedWrap())
4699 else if (AR->hasNoUnsignedWrap())
4709 VPValue *NewFindLastSelect = BackedgeVal;
4711 if (!SentinelVal || IVOfExpressionToSink) {
4714 DebugLoc DL = FindLastSelect->getDefiningRecipe()->getDebugLoc();
4715 VPBuilder LoopBuilder(FindLastSelect->getDefiningRecipe());
4716 if (
match(FindLastSelect,
4718 SelectCond = LoopBuilder.
createNot(SelectCond);
4725 if (SelectCond !=
Cond || IVOfExpressionToSink) {
4728 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression,
4737 VPIRFlags Flags(MinMaxKind,
false,
false,
4743 NewFindLastSelect, Flags, ExitDL);
4746 VPValue *VectorRegionExitingVal = ReducedIV;
4747 if (IVOfExpressionToSink)
4748 VectorRegionExitingVal =
4750 ReducedIV, IVOfExpressionToSink);
4753 VPValue *StartVPV = PhiR->getStartValue();
4760 NewRdxResult = MiddleBuilder.
createSelect(Cmp, VectorRegionExitingVal,
4770 AnyOfPhi->insertAfter(PhiR);
4777 OrVal, VectorRegionExitingVal, StartVPV, ExitDL);
4790 PhiR->hasUsesOutsideReductionChain());
4791 NewPhiR->insertBefore(PhiR);
4792 PhiR->replaceAllUsesWith(NewPhiR);
4793 PhiR->eraseFromParent();
4800struct ReductionExtend {
4801 Type *SrcType =
nullptr;
4802 ExtendKind Kind = ExtendKind::PR_None;
4808struct ExtendedReductionOperand {
4812 ReductionExtend ExtendA, ExtendB;
4820struct VPPartialReductionChain {
4823 VPWidenRecipe *ReductionBinOp =
nullptr;
4825 ExtendedReductionOperand ExtendedOp;
4832 unsigned AccumulatorOpIdx;
4833 unsigned ScaleFactor;
4836 VPBlendRecipe *Blend =
nullptr;
4841static std::optional<unsigned>
4845 "Expected a non-normalized blend with two incoming values");
4851 return std::nullopt;
4852 return FirstIncomingHasOneUse ? 0 : 1;
4864 if (!
Op->hasOneUse() ||
4870 auto *Trunc = Builder.createWidenCast(Instruction::CastOps::Trunc,
4871 Op->getOperand(1), NarrowTy);
4873 Op->setOperand(1, Builder.createWidenCast(ExtOpc, Trunc, WideTy));
4882 auto *
Sub =
Op->getOperand(0)->getDefiningRecipe();
4884 assert(Ext->getOpcode() ==
4886 "Expected both the LHS and RHS extends to be the same");
4887 bool IsSigned = Ext->getOpcode() == Instruction::SExt;
4890 auto *FreezeX = Builder.insert(
new VPWidenRecipe(Instruction::Freeze, {
X}));
4891 auto *FreezeY = Builder.insert(
new VPWidenRecipe(Instruction::Freeze, {
Y}));
4892 auto *
Max = Builder.insert(
4894 {FreezeX, FreezeY}, SrcTy));
4895 auto *Min = Builder.insert(
4897 {FreezeX, FreezeY}, SrcTy));
4898 auto *AbsDiff = Builder.insert(
4901 return Builder.createWidenCast(Instruction::CastOps::ZExt, AbsDiff,
4902 Op->getScalarType());
4914 if (!
Mul->hasOneUse() ||
4915 (Ext->getOpcode() != MulLHS->getOpcode() && MulLHS != MulRHS) ||
4916 MulLHS->getOpcode() != MulRHS->getOpcode())
4919 auto *NewLHS = Builder.createWidenCast(
4920 MulLHS->getOpcode(), MulLHS->getOperand(0), Ext->getScalarType());
4921 auto *NewRHS = MulLHS == MulRHS
4923 : Builder.createWidenCast(MulRHS->getOpcode(),
4924 MulRHS->getOperand(0),
4925 Ext->getScalarType());
4926 auto *NewMul =
Mul->cloneWithOperands({NewLHS, NewRHS});
4927 Builder.insert(NewMul);
4928 Op->replaceAllUsesWith(NewMul);
4929 Op->eraseFromParent();
4930 Mul->eraseFromParent();
4939 VPValue *VecOp = Red->getVecOp();
4993static void transformToPartialReduction(
const VPPartialReductionChain &Chain,
5001 WidenRecipe->
getOperand(1 - Chain.AccumulatorOpIdx));
5004 ExtendedOp = optimizeExtendsForPartialReduction(ExtendedOp);
5020 if ((WidenRecipe->
getOpcode() == Instruction::Sub &&
5022 (WidenRecipe->
getOpcode() == Instruction::FSub &&
5027 if (WidenRecipe->
getOpcode() == Instruction::FSub) {
5039 Builder.insert(NegRecipe);
5040 ExtendedOp = NegRecipe;
5055 std::optional<unsigned> BlendReductionIdx =
5056 getBlendReductionUpdateValueIdx(Chain.Blend);
5057 assert(BlendReductionIdx &&
5059 "Expected blend to contain the reduction update");
5076 assert((!ExitValue || IsLastInChain) &&
5077 "if we found ExitValue, it must match RdxPhi's backedge value");
5088 PartialRed->insertBefore(WidenRecipe);
5098 E->insertBefore(WidenRecipe);
5099 PartialRed->replaceAllUsesWith(
E);
5112 auto *NewScaleFactor = Plan.
getConstantInt(32, Chain.ScaleFactor);
5113 StartInst->setOperand(2, NewScaleFactor);
5121 VPValue *OldStartValue = StartInst->getOperand(0);
5122 StartInst->setOperand(0, StartInst->getOperand(1));
5126 assert(RdxResult &&
"Could not find reduction result");
5129 unsigned SubOpc = Chain.RK ==
RecurKind::FSub ? Instruction::BinaryOps::FSub
5130 : Instruction::BinaryOps::Sub;
5136 [&NewResult](
VPUser &U,
unsigned Idx) {
return &
U != NewResult; });
5142 const VPPartialReductionChain &Link,
5145 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
5146 std::optional<unsigned> BinOpc = std::nullopt;
5148 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
5149 BinOpc = ExtendedOp.ExtendsUser->
getOpcode();
5151 std::optional<llvm::FastMathFlags>
Flags;
5155 auto GetLinkOpcode = [&Link]() ->
unsigned {
5158 return Instruction::Add;
5160 return Instruction::FAdd;
5162 return Link.ReductionBinOp->
getOpcode();
5167 GetLinkOpcode(), ExtendedOp.ExtendA.SrcType, ExtendedOp.ExtendB.SrcType,
5168 RdxType, VF, ExtendedOp.ExtendA.Kind, ExtendedOp.ExtendB.Kind, BinOpc,
5189static std::optional<ExtendedReductionOperand>
5192 "Op should be operand of UpdateR");
5200 if (
Op->hasOneUse() &&
5209 Type *RHSInputType =
Y->getScalarType();
5210 if (LHSInputType != RHSInputType ||
5211 LHSExt->getOpcode() != RHSExt->getOpcode())
5212 return std::nullopt;
5215 return ExtendedReductionOperand{
5217 {LHSInputType, getPartialReductionExtendKind(LHSExt)},
5221 std::optional<TTI::PartialReductionExtendKind> OuterExtKind;
5224 VPValue *CastSource = CastRecipe->getOperand(0);
5225 OuterExtKind = getPartialReductionExtendKind(CastRecipe);
5235 return ExtendedReductionOperand{
5242 if (!
Op->hasOneUse())
5243 return std::nullopt;
5248 return std::nullopt;
5258 return std::nullopt;
5262 ExtendKind LHSExtendKind = getPartialReductionExtendKind(LHSCast);
5265 const APInt *RHSConst =
nullptr;
5271 return std::nullopt;
5275 if (Cast && OuterExtKind &&
5276 getPartialReductionExtendKind(Cast) != OuterExtKind)
5277 return std::nullopt;
5279 Type *RHSInputType = LHSInputType;
5280 ExtendKind RHSExtendKind = LHSExtendKind;
5283 RHSExtendKind = getPartialReductionExtendKind(RHSCast);
5286 return ExtendedReductionOperand{
5287 MulOp, {LHSInputType, LHSExtendKind}, {RHSInputType, RHSExtendKind}};
5294static std::optional<SmallVector<VPPartialReductionChain>>
5301 return std::nullopt;
5311 VPValue *CurrentValue = ExitValue;
5312 while (CurrentValue != RedPhiR) {
5314 std::optional<unsigned> BlendReductionIdx;
5318 return std::nullopt;
5320 BlendReductionIdx = getBlendReductionUpdateValueIdx(Blend);
5321 if (!BlendReductionIdx)
5322 return std::nullopt;
5329 return std::nullopt;
5336 std::optional<ExtendedReductionOperand> ExtendedOp =
5337 matchExtendedReductionOperand(UpdateR,
Op);
5339 ExtendedOp = matchExtendedReductionOperand(UpdateR, PrevValue);
5341 return std::nullopt;
5349 return std::nullopt;
5351 Type *ExtSrcType = ExtendedOp->ExtendA.SrcType;
5354 return std::nullopt;
5356 VPPartialReductionChain Link(
5357 {UpdateR, *ExtendedOp, RK,
5362 CurrentValue = PrevValue;
5367 std::reverse(Chain.
begin(), Chain.
end());
5384 if (
auto Chains = getScaledReductions(&RedPhiR))
5385 ChainsByPhi.
try_emplace(&RedPhiR, std::move(*Chains));
5390 UnorderedReductions.
push_back(&RedPhiR);
5396 for (
auto *Rdx : UnorderedReductions) {
5412 ? std::make_optional(Rdx->getFastMathFlagsOrNone())
5416 Backedge->getOpcode(), ScalarTy,
nullptr,
5418 std::nullopt, CostCtx.
CostKind, FMF);
5419 return PRCost <= CurrentCost;
5425 Rdx->getRecurrenceKind(), Rdx->getFastMathFlagsOrNone(),
5426 Backedge->getUnderlyingInstr(), Rdx, OtherOp,
nullptr,
5429 Partial->insertBefore(Backedge);
5430 Backedge->replaceAllUsesWith(Partial);
5431 Backedge->eraseFromParent();
5434 if (ChainsByPhi.
empty())
5442 for (
const auto &[
_, Chains] : ChainsByPhi)
5443 for (
const VPPartialReductionChain &Chain : Chains) {
5444 PartialReductionOps.
insert(Chain.ExtendedOp.ExtendsUser);
5446 PartialReductionBlends.
insert(Chain.Blend);
5447 ScaledReductionMap[Chain.ReductionBinOp] = Chain.ScaleFactor;
5453 auto ExtendUsersValid = [&](
VPValue *Ext) {
5455 return PartialReductionOps.contains(cast<VPRecipeBase>(U));
5459 auto IsProfitablePartialReductionChainForVF =
5466 for (
const VPPartialReductionChain &Link : Chain) {
5467 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
5468 InstructionCost LinkCost = getPartialReductionLinkCost(CostCtx, Link, VF);
5472 PartialCost += LinkCost;
5473 RegularCost += Link.ReductionBinOp->
computeCost(VF, CostCtx);
5475 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
5476 RegularCost += ExtendedOp.ExtendsUser->
computeCost(VF, CostCtx);
5479 RegularCost += Extend->computeCost(VF, CostCtx);
5481 return PartialCost.
isValid() && PartialCost < RegularCost;
5489 for (
auto &[RedPhiR, Chains] : ChainsByPhi) {
5490 for (
const VPPartialReductionChain &Chain : Chains) {
5491 if (!
all_of(Chain.ExtendedOp.ExtendsUser->operands(), ExtendUsersValid)) {
5495 auto UseIsValid = [&, RedPhiR = RedPhiR](
VPUser *U) {
5497 return PhiR == RedPhiR;
5501 return Blend == Chain.Blend || PartialReductionBlends.
contains(Blend);
5503 return Chain.ScaleFactor == ScaledReductionMap.
lookup_or(R, 0) ||
5509 if (!
all_of(Chain.ReductionBinOp->users(), UseIsValid)) {
5518 auto *RepR = dyn_cast<VPReplicateRecipe>(U);
5519 return RepR && RepR->getOpcode() == Instruction::Store;
5530 return IsProfitablePartialReductionChainForVF(Chains, VF);
5536 for (
auto &[Phi, Chains] : ChainsByPhi)
5537 for (
const VPPartialReductionChain &Chain : Chains)
5538 transformToPartialReduction(Chain, Plan, Phi);
5552 if (VPI.getUnderlyingValue() &&
5563 auto ProcessSubset = [&](
VPlan &,
auto ProcessVPInst) {
5566 if (!ProcessVPInst(VPI))
5575 assert(New->getParent() &&
"New recipe must have been inserted");
5576 if (VPI->
getOpcode() == Instruction::Load)
5585 return ReplaceWith(VPI,
VPBuilder(VPI).insert(
5592 "lowerMemoryIdioms", ProcessSubset, Plan, [&](
VPInstruction *VPI) {
5594 VPI, FinalRedStoresBuilder))
5603 return ReplaceWith(VPI,
VPBuilder(VPI).insert(Histogram));
5616 "scalarizeMemOpsWithIrregularTypes", ProcessSubset, Plan,
5620 return Scalarize(VPI);
5627 "makeVPlanMemOpDecision", ProcessSubset, Plan, [&](
VPInstruction *VPI) {
5629 bool IsLoad = VPI->
getOpcode() == Instruction::Load;
5639 const SCEV *PtrSCEV =
5641 bool IsSingleScalarLoad =
5647 I, Ptr, IsSingleScalarLoad,
5656 "widenConsecutiveMemOps", ProcessSubset, Plan, [&](
VPInstruction *VPI) {
5658 bool IsLoad = VPI->
getOpcode() == Instruction::Load;
5662 std::optional<int64_t> Stride =
5664 if (Stride != 1 && Stride != -1)
5695 return ReplaceWith(VPI,
Load);
5704 auto *StoreR = Builder.createWidenStore(
5707 return ReplaceWith(VPI, StoreR);
5714 return ReplaceWith(VPI, Recipe);
5716 return Scalarize(VPI);
5736 if (VPI.mayHaveSideEffects())
5740 if (VPI.isMasked() && !VPI.isSafeToSpeculativelyExecute())
5745 if (VPI.getOpcode() == Instruction::Add &&
5754 VPI.getOpcode(), VPI.operandsWithoutMask(),
nullptr, VPI,
5755 VPI, VPI.getDebugLoc(),
I);
5756 Recipe->insertBefore(&VPI);
5757 VPI.replaceAllUsesWith(Recipe);
5758 VPI.eraseFromParent();
5768 switch (Param.ParamKind) {
5769 case VFParamKind::Vector:
5770 case VFParamKind::GlobalPredicate:
5772 case VFParamKind::OMP_Uniform:
5773 return SE->isSCEVable(Args[Param.ParamPos]->getScalarType()) &&
5774 SE->isLoopInvariant(
5775 vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
5777 case VFParamKind::OMP_Linear:
5778 return match(vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
5779 m_scev_AffineAddRec(
5780 m_SCEV(), m_scev_SpecificSInt(Param.LinearStepOrPos),
5781 m_SpecificLoop(L)));
5798 const auto *It =
find_if(Mappings, [&](
const VFInfo &Info) {
5799 return Info.Shape.VF == VF && (!MaskRequired || Info.isMasked()) &&
5802 if (It == Mappings.end())
5809struct CallWideningDecision {
5810 enum class KindTy { Scalarize,
Intrinsic, VectorVariant };
5811 CallWideningDecision(KindTy Kind,
Function *Variant =
nullptr)
5834 return CallWideningDecision::KindTy::Scalarize;
5844 return CallWideningDecision::KindTy::Scalarize;
5848 false, VF, CostCtx);
5863 return CallWideningDecision::KindTy::Intrinsic;
5867 if (VecFunc && ScalarCost >= VecCallCost)
5868 return {CallWideningDecision::KindTy::VectorVariant, VecFunc};
5870 return CallWideningDecision::KindTy::Scalarize;
5880 if (!VPI.getUnderlyingValue() || VPI.getOpcode() != Instruction::Call)
5885 VPI.op_begin() + CI->arg_size());
5887 CallWideningDecision Decision =
5896 switch (Decision.Kind) {
5897 case CallWideningDecision::KindTy::Intrinsic: {
5901 VPI, VPI.getDebugLoc());
5904 case CallWideningDecision::KindTy::VectorVariant: {
5909 Ops.push_back(Mask);
5911 Ops.push_back(VPI.getOperand(VPI.getNumOperandsWithoutMask() - 1));
5916 case CallWideningDecision::KindTy::Scalarize:
5922 VPI.replaceAllUsesWith(Replacement);
5923 VPI.eraseFromParent();
5939 if (VPI.getOpcode() != Instruction::Trunc)
5968 !
TTI.isTruncateFree(
5969 toVectorTy(VPI.getOperand(0)->getScalarType(), VF),
5973 IsNarrowingProfitable,
Range))
5979 WideIV->getPHINode(), WideIV->getStartValue(), WideIV->getStepValue(),
5980 WideIV->getVFValue(), WideIV->getInductionDescriptor(), Trunc,
5982 NarrowIV->insertBefore(*HeaderVPBB, HeaderVPBB->
getFirstNonPhi());
5983 VPI.replaceAllUsesWith(NarrowIV);
5984 VPI.eraseFromParent();
6006 if (!MemR || MemR->isConsecutive())
6009 VPValue *Ptr = MemR->getAddr();
6021 VPValue *StoredValue =
nullptr;
6025 StoredValue = StoreR->getStoredValue();
6027 IntrinID = Intrinsic::experimental_vp_strided_store;
6031 IntrinID = Intrinsic::experimental_vp_strided_load;
6034 Align Alignment = MemR->getAlign();
6037 if (!Ctx.TTI.isLegalStridedLoadStore(VectorTy, Alignment))
6042 IntrinID, VectorTy, MemR->isMasked(), Alignment, Ctx);
6043 return StridedLoadStoreCost < CurrentCost;
6054 Ctx.invalidateWideningDecision(&MemR->getIngredient(), VF);
6059 I32VF = Builder.createScalarZExtOrTrunc(
6073 "Stride type from SCEV must match the index type");
6074 VPValue *CanIV = Builder.createScalarZExtOrTrunc(
6077 auto *
Offset = Builder.createOverflowingOp(
6078 Instruction::Mul, {CanIV, StrideInBytes},
6079 {AddRecPtr->hasNoUnsignedWrap(),
false});
6083 VPValue *BasePtr = Builder.createNoWrapPtrAdd(StartVPV,
Offset, NWFlags);
6086 VPValue *NewPtr = Builder.createVectorPointer(
6090 VPValue *Mask = MemR->getMask();
6095 Ops.push_back(StoredValue);
6096 Ops.append({NewPtr, StrideInBytes, Mask, I32VF});
6098 auto *StridedR = Builder.createWidenMemIntrinsic(
6101 *MemR, R.getDebugLoc());
6104 R.eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool isEqual(const Function &Caller, const Function &Callee)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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")))
iv Induction Variable Users
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Legalize the Machine IR a function s Machine IR
This file provides utility analysis objects describing memory locations.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
This is the interface for a metadata-based scoped no-alias analysis.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of different VPlan-related auxiliary helpers.
This file contains the declarations of the Vectorization Plan base classes:
static const X86InstrFMA3Group Groups[]
static const uint32_t IV[8]
Helper for extra no-alias checks via known-safe recipe and SCEV.
SinkStoreInfo(ArrayRef< VPReplicateRecipe * > ExcludeRecipes, VPReplicateRecipe &GroupLeader, PredicatedScalarEvolution &PSE, const Loop &L)
SinkStoreInfo(VPReplicateRecipe &GroupLeader)
bool shouldSkip(VPRecipeBase &R) const
Return true if R should be skipped during alias checking, either because it's in the exclude set or b...
Class for arbitrary precision integers.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
APInt abs() const
Get the absolute value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
int32_t exactLogBase2() const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
static APSInt getMinValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the minimum integer value with the given bit width and signedness.
static APSInt getMaxValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the maximum integer value with the given bit width and signedness.
@ NoAlias
The two locations do not alias at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
Get the last element.
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
const T & front() const
Get the first element.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
This class represents a function call, abstracting a target machine's calling convention.
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
This class represents a range of values.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
static DebugLoc getUnknown()
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static constexpr ElementCount getScalable(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
Convenience struct for specifying and reasoning about fast-math flags.
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags noUnsignedWrap()
bool hasNoUnsignedWrap() const
GEPNoWrapFlags withoutNoUnsignedWrap() const
static GEPNoWrapFlags none()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
A struct for saving information about induction variables.
InductionKind
This enum represents the kinds of inductions that we support.
@ IK_PtrInduction
Pointer induction var. Step = C.
@ IK_IntInduction
Integer induction variable. Step = C.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
The group of interleaved loads/stores sharing the same stride and close to each other.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
static bool getDecisionAndClampRange(const std::function< bool(ElementCount)> &Predicate, VFRange &Range)
Test a Predicate on a Range of VF's.
Represents a single loop in the control flow graph.
This class implements a map that also provides access to all stored values in a deterministic order.
ValueT lookup(const KeyT &Key) const
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Representation for a specific memory location.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Post-order traversal of a graph.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
LLVM_ABI const SCEV * getSCEV(Value *V)
Returns the SCEV expression of V, in the context of the current SCEV predicate.
static LLVM_ABI unsigned getOpcode(RecurKind Kind)
Returns the opcode corresponding to the RecurrenceKind.
unsigned getOpcode() const
static bool isFindLastRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
RegionT * getParent() const
Get the parent of the Region.
This class represents a constant integer value.
ConstantInt * getValue() const
static const SCEV * rewrite(const SCEV *Scev, ScalarEvolution &SE, ValueToSCEVMapTy &Map)
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
const DataLayout & getDataLayout() const
Return the DataLayout associated with the module this SCEV instance is operating on.
LLVM_ABI bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
ConstantRange getSignedRange(const SCEV *S)
Determine the signed range for a particular SCEV.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagNone)
Return the SCEV object corresponding to -V.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, SCEVUse LHS, SCEVUse RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getElementCount(Type *Ty, ElementCount EC, SCEV::NoWrapFlags Flags=SCEV::FlagNone)
static LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Provides information about what library functions are available for the current target.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionalit...
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
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.
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 isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static SmallVector< VFInfo, 8 > getMappings(const CallInst &CI)
Retrieve all the VFInfo instances associated to the CallInst CI.
bool isLegalMaskedLoadOrStore(bool IsLoad, Type *ScalarTy, Align Alignment, unsigned AddressSpace) const
Returns true if the target machine supports a masked load (if IsLoad) or masked store of scalar type ...
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
iterator begin()
Recipe iterator methods.
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
iterator getFirstNonPhi()
Return the position of the first non-phi node recipe in the block.
VPBasicBlock * splitAt(iterator SplitAt)
Split current block at SplitAt by inserting a new block between the current block and its successors ...
const VPRecipeBase & front() const
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
const VPRecipeBase & back() const
A recipe for vectorizing a phi-node as a sequence of mask-based select instructions.
VPValue * getIncomingValue(unsigned Idx) const
Return incoming value number Idx.
VPValue * getMask(unsigned Idx) const
Return mask number Idx.
unsigned getNumIncomingValues() const
Return the number of incoming values, taking into account when normalized the first incoming value wi...
void setMask(unsigned Idx, VPValue *V)
Set mask number Idx to V.
bool isNormalized() const
A normalized blend is one that has an odd number of operands, whereby the first operand does not have...
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
void setSuccessors(ArrayRef< VPBlockBase * > NewSuccs)
Set each VPBasicBlock in NewSuccss as successor of this VPBlockBase.
VPRegionBlock * getParent()
const VPBasicBlock * getExitingBasicBlock() const
size_t getNumSuccessors() const
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
const VPBlocksTy & getPredecessors() const
VPBlockBase * getSinglePredecessor() const
const VPBasicBlock * getEntryBasicBlock() const
VPBlockBase * getSingleSuccessor() const
const VPBlocksTy & getSuccessors() const
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop latch, using isHeader().
static VPBasicBlock * getPlainCFGMiddleBlock(const VPlan &Plan)
Returns the middle block of Plan in plain CFG form (before regions are formed).
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBases IfTrue and IfFalse after BlockPtr.
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
static std::pair< VPBasicBlock *, VPBasicBlock * > getPlainCFGHeaderAndLatch(const VPlan &Plan)
Returns the header and latch of the outermost loop of Plan in plain CFG form (before regions are form...
static void transferSuccessors(VPBlockBase *Old, VPBlockBase *New)
Transfer successors from Old to New. New must have no successors.
static SmallVector< VPBasicBlock * > blocksInSingleSuccessorChainBetween(VPBasicBlock *FirstBB, VPBasicBlock *LastBB)
Returns the blocks between FirstBB and LastBB, where FirstBB to LastBB forms a single-sucessor chain.
A recipe for generating conditional branches on the bits of a mask.
VPlan-based builder utility analogous to IRBuilder.
VPInstruction * createFirstActiveLane(ArrayRef< VPValue * > Masks, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPWidenStoreRecipe * createWidenStore(StoreInst &Store, VPValue *Addr, VPValue *StoredVal, VPValue *Mask, bool Consecutive, const VPIRMetadata &Metadata, DebugLoc DL)
Create a recipe widening Store, storing StoredVal to Addr with Mask (may be null).
VPInstruction * createAdd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", VPRecipeWithIRFlags::WrapFlagsTy WrapFlags={false, false})
VPInstruction * createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createLogicalOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPWidenLoadRecipe * createWidenLoad(LoadInst &Load, VPValue *Addr, VPValue *Mask, bool Consecutive, const VPIRMetadata &Metadata, DebugLoc DL)
Create a recipe widening Load, loading from Addr with Mask (may be null).
VPInstruction * createNot(VPValue *Operand, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createAnyOfReduction(VPValue *ChainOp, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL=DebugLoc::getUnknown())
Create an AnyOf reduction pattern: or-reduce ChainOp, freeze the result, then select between TrueVal ...
void setInsertPoint(const VPInsertPoint &IP)
Set the current insert point.
VPInstruction * createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createScalarCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy, DebugLoc DL, std::optional< VPIRFlags > Flags=std::nullopt, const VPIRMetadata &Metadata={})
VPInstruction * createFreeze(VPValue *Op, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, DebugLoc DL)
static VPBuilder getToInsertAfter(VPRecipeBase *R)
Create a VPBuilder to insert after R.
VPDerivedIVRecipe * createDerivedIV(InductionDescriptor::InductionKind Kind, FPMathOperator *FPBinOp, VPValue *Start, VPValue *Current, VPValue *Step, const VPIRFlags::WrapFlagsTy &Flags={})
Convert Current to Start + Current * Step.
VPWidenCastRecipe * createWidenCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
VPInstruction * createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
Create a new ICmp VPInstruction with predicate Pred and operands A and B.
VPInstruction * createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", std::optional< VPIRFlags > Flags=std::nullopt)
Create a select of TrueVal and FalseVal based on Cond, using the default flags for the result type,...
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, Instruction *Inst=nullptr, const VPIRFlags &Flags={}, const VPIRMetadata &MD={}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", Type *ResultTy=nullptr)
Create an N-ary operation with Opcode, Operands and set Inst as its underlying Instruction.
static VPSingleDefRecipe * createSingleScalarOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPValue *Mask, const VPIRFlags &Flags, const VPIRMetadata &Metadata, DebugLoc DL, Instruction *UV)
Create a single-scalar recipe with Opcode and Operands without inserting it.
unsigned getNumDefinedValues() const
Returns the number of values defined by the VPDef.
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
VPValue * getVPValue(unsigned I)
Returns the VPValue with index I defined by the VPDef.
ArrayRef< VPRecipeValue * > definedValues()
Returns an ArrayRef of the values defined by the VPDef.
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
bool properlyDominates(const VPRecipeBase *A, const VPRecipeBase *B) const
Recipe to expand a SCEV expression.
A recipe to combine multiple recipes into a single 'expression' recipe, which should be considered a ...
A recipe representing a sequence of load -> update -> store as part of a histogram operation.
A special type of VPBasicBlock that wraps an existing IR basic block.
Class to record and manage LLVM IR flags.
static LLVM_ABI_FOR_TEST VPIRFlags getDefaultFlags(unsigned Opcode, Type *ResultTy=nullptr)
Returns default flags for Opcode and scalar ResultTy for opcodes that support it, asserts otherwise.
LLVM_ABI_FOR_TEST FastMathFlags getFastMathFlagsOrNone() const
This is a concrete Recipe that models a single VPlan-level instruction.
unsigned getNumOperandsWithoutMask() const
Returns the number of operands, excluding the mask if the VPInstruction is masked.
@ ExtractLane
Extracts a single lane (first operand) from a set of vector operands.
@ ExtractPenultimateElement
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
@ BuildVector
Creates a fixed-width vector containing all operands.
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
unsigned getOpcode() const
VPValue * getMask() const
Returns the mask for the VPInstruction.
const InterleaveGroup< Instruction > * getInterleaveGroup() const
VPValue * getMask() const
Return the mask used by this recipe.
ArrayRef< VPValue * > getStoredValues() const
Return the VPValues stored by this interleave group.
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
VPRegionBlock * getRegion()
VPBasicBlock * getParent()
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
void moveBefore(VPBasicBlock &BB, iplist< VPRecipeBase >::iterator I)
Unlink this recipe and insert into BB before I.
void insertBefore(VPRecipeBase *InsertPos)
Insert an unlinked recipe into a basic block immediately before the specified recipe.
void insertAfter(VPRecipeBase *InsertPos)
Insert an unlinked Recipe into a basic block immediately after the specified Recipe.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Helper class to create VPRecipies from IR instructions.
VPHistogramRecipe * widenIfHistogram(VPInstruction *VPI)
If VPI represents a histogram operation (as determined by LoopVectorizationLegality) make that safe f...
bool prefersVectorizedAddressing() const
Returns true if the target prefers vectorized addressing.
VPRecipeBase * tryToWidenMemory(VPInstruction *VPI, VFRange &Range)
Check if the load or store instruction VPI should widened for Range.Start and potentially masked.
bool replaceWithFinalIfReductionStore(VPInstruction *VPI, VPBuilder &FinalRedStoresBuilder)
If VPI is a store of a reduction into an invariant address, delete it.
VPSingleDefRecipe * handleReplication(VPInstruction *VPI, VFRange &Range)
Build a replicating or single-scalar recipe for VPI.
bool isPredicatedInst(Instruction *I) const
Returns true if I needs to be predicated (i.e.
Type * getScalarType() const
Returns the scalar type of this VPRecipeValue.
A recipe for handling reduction phis.
bool isOrdered() const
Returns true, if the phi is part of an ordered reduction.
void setVFScaleFactor(unsigned ScaleFactor)
Set the VFScaleFactor for this reduction phi.
unsigned getVFScaleFactor() const
Get the factor that the VF of this recipe's output should be scaled by, or 1 if it isn't scaled.
bool isInLoop() const
Returns true if the phi is part of an in-loop reduction.
RecurKind getRecurrenceKind() const
Returns the recurrence kind of the reduction.
A recipe to represent inloop, ordered or partial reduction operations.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
const VPBlockBase * getEntry() const
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
void setExiting(VPBlockBase *ExitingBlock)
Set ExitingBlock as the exiting VPBlockBase of this VPRegionBlock.
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
const VPBlockBase * getExiting() const
VPRegionValue * getHeaderMask() const
Return the header mask of the region, or null if not set.
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
bool isSingleScalar() const
Returns true if the recipe produces a single scalar value.
static InstructionCost computeCallCost(Function *CalledFn, Type *ResultTy, ArrayRef< const VPValue * > ArgOps, bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx)
Return the cost of scalarizing a call to CalledFn with argument operands ArgOps for a given VF.
operand_range operandsWithoutMask()
Return the recipe's operands, excluding the mask of a predicated recipe.
bool isPredicated() const
VPValue * getMask()
Return the mask of a predicated VPReplicateRecipe.
Lightweight SCEV-to-VPlan expander.
VPValue * expand(const SCEV *S)
Expand S into recipes and live-ins using the builder.
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Instruction * getUnderlyingInstr()
Returns the underlying instruction.
VPSingleDefRecipe * clone() override=0
Clone the current recipe.
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
void setOperand(unsigned I, VPValue *New)
unsigned getNumOperands() const
VPValue * getOperand(unsigned N) const
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Value * getLiveInIRValue() const
Return the underlying IR value for a VPIRValue.
bool isDefinedOutsideLoopRegions() const
Returns true if the VPValue is defined outside any loop.
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
bool hasMoreThanOneUniqueUser() const
Returns true if the value has more than one unique user.
Value * getUnderlyingValue() const
Return the underlying Value attached to this VPValue.
VPUser * getSingleUser()
Return the single user of this value, or nullptr if there is not exactly one user.
void replaceAllUsesWith(VPValue *New)
void replaceUsesWithIf(VPValue *New, llvm::function_ref< bool(VPUser &U, unsigned Idx)> ShouldReplace)
Go through the uses list for this VPValue and make each use point to New if the callback ShouldReplac...
A recipe to compute a pointer to the last element of each part of a widened memory access for widened...
A recipe for widening Call instructions using library calls.
static InstructionCost computeCallCost(Function *Variant, VPCostContext &Ctx)
Return the cost of widening a call using the vector function Variant.
VPWidenCastRecipe is a recipe to create vector cast instructions.
Instruction::CastOps getOpcode() const
A recipe for handling GEP instructions.
Base class for widened induction (VPWidenIntOrFpInductionRecipe and VPWidenPointerInductionRecipe),...
PHINode * getPHINode() const
Returns the underlying PHINode if one exists, or null otherwise.
VPValue * getStepValue()
Returns the step value of the induction.
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
TruncInst * getTruncInst()
Returns the first defined value as TruncInst, if it is one or nullptr otherwise.
A recipe for widening vector intrinsics.
static InstructionCost computeCallCost(Intrinsic::ID ID, ArrayRef< const VPValue * > Operands, const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx)
Compute the cost of a vector intrinsic with ID and Operands.
static InstructionCost computeMemIntrinsicCost(Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment, VPCostContext &Ctx)
Helper function for computing the cost of vector memory intrinsic.
A common mixin class for widening memory operations.
virtual VPRecipeBase * getAsRecipe()=0
Return a VPRecipeBase* to the current object.
A recipe for widened phis.
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenRecipe.
VPWidenRecipe * clone() override
Clone the current recipe.
unsigned getOpcode() const
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
VPIRValue * getLiveIn(Value *V) const
Return the live-in VPIRValue for V, if there is one or nullptr otherwise.
bool hasVF(ElementCount VF) const
const DataLayout & getDataLayout() const
LLVMContext & getContext() const
VPBasicBlock * getEntry()
bool hasScalableVF() const
VPValue * getTripCount() const
The trip count of the original loop.
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
iterator_range< SmallSetVector< ElementCount, 2 >::iterator > vectorFactors() const
Returns an iterator range over all VFs of the plan.
VPIRValue * getFalse()
Return a VPIRValue wrapping i1 false.
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
VPIRValue * getAllOnesValue(Type *Ty)
Return a VPIRValue wrapping the AllOnes value of type Ty.
VPRegionBlock * createReplicateRegion(VPBlockBase *Entry, VPBlockBase *Exiting, const std::string &Name="")
Create a new replicate region with Entry, Exiting and Name.
auto getLiveIns() const
Return the list of live-in VPValues available in the VPlan.
bool hasUF(unsigned UF) const
ArrayRef< VPIRBasicBlock * > getExitBlocks() const
Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of the original scalar loop.
VPSymbolicValue & getVectorTripCount()
The vector trip count.
VPValue * getBackedgeTakenCount() const
VPIRValue * getOrAddLiveIn(Value *V)
Gets the live-in VPIRValue for V or adds a new live-in (if none exists yet) for V.
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
void setVF(ElementCount VF)
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
void resetTripCount(VPValue *NewTripCount)
Resets the trip count for the VPlan.
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
VPBasicBlock * createVPBasicBlock(const Twine &Name, VPRecipeBase *Recipe=nullptr)
Create a new VPBasicBlock with Name and containing Recipe if present.
VPIRValue * getTrue()
Return a VPIRValue wrapping i1 true.
VPBasicBlock * getVectorPreheader() const
Returns the preheader of the vector loop region, if one exists, or null otherwise.
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
bool hasScalarVFOnly() const
VPBasicBlock * getScalarPreheader() const
Return the VPBasicBlock for the preheader of the scalar loop.
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
LLVM_ABI_FOR_TEST VPlan * duplicate()
Clone the current VPlan, update all VPValues of the new VPlan and cloned recipes to refer to the clon...
VPIRValue * getConstantInt(Type *Ty, uint64_t Val, bool IsSigned=false)
Return a VPIRValue wrapping a ConstantInt with the given type and value.
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
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.
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM)
Return A unsign-divided by B, rounded by the given rounding mode.
std::variant< std::monostate, Loc::Single, Loc::Multi, Loc::MMI, Loc::EntryValue > Variant
Alias for the std::variant specialization base class of DbgVariable.
void reportVectorizationFailure(const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag, OptimizationRemarkEmitter *ORE, const Loop *TheLoop, Instruction *I=nullptr)
Reports a vectorization failure: print DebugMsg for debugging purposes along with the corresponding o...
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
match_unless< Pattern > m_Unless(const Pattern &P)
Match if the inner matcher does NOT match.
match_isa< To... > m_Isa()
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
auto m_Cmp()
Matches any compare instruction and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::URem > m_URem(const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Freeze > m_Freeze(const OpTy &Op)
Matches FreezeInst.
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.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_deferred< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto match_fn(const Pattern &P)
A match functor that can be used as a UnaryPredicate in functional algorithms like all_of.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
SpecificCmpClass_match< LHS, RHS, CmpInst > m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::UDiv > m_UDiv(const LHS &L, const RHS &R)
SelectLike_match< CondTy, LTy, RTy > m_SelectLike(const CondTy &C, const LTy &TrueC, const RTy &FalseC)
Matches a value that behaves like a boolean-controlled select, i.e.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
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::FAdd, true > m_c_FAdd(const LHS &L, const RHS &R)
Matches FAdd with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)
Matches a Mul with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
specificloop_ty m_SpecificLoop(const Loop *L)
bool match(const SCEV *S, const Pattern &P)
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ExtractLastLane, VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > > m_ExtractLastLaneOfLastPart(const Op0_t &Op0)
AllRecipe_commutative_match< Instruction::And, Op0_t, Op1_t > m_c_BinaryAnd(const Op0_t &Op0, const Op1_t &Op1)
Match a binary AND operation.
AllRecipe_match< Instruction::Or, Op0_t, Op1_t > m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
Match a binary OR operation.
VPInstruction_match< VPInstruction::AnyOf > m_AnyOf()
AllRecipe_commutative_match< Instruction::Or, Op0_t, Op1_t > m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ComputeReductionResult, Op0_t > m_ComputeReductionResult(const Op0_t &Op0)
auto m_WidenAnyExtend(const Op0_t &Op0)
match_bind< VPIRValue > m_VPIRValue(VPIRValue *&V)
Match a VPIRValue.
VPInstruction_match< VPInstruction::WideActiveLaneMask, Op0_t, Op1_t, Op2_t > m_WideActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
auto m_VPPhi(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::BranchOnTwoConds > m_BranchOnTwoConds()
AllRecipe_match< Opcode, Op0_t, Op1_t > m_Binary(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::LastActiveLane, Op0_t > m_LastActiveLane(const Op0_t &Op0)
auto m_WidenIntrinsic(const T &...Ops)
canonical_widen_iv_match m_CanonicalWidenIV()
VPInstruction_match< VPInstruction::ExitingIVValue, Op0_t > m_ExitingIVValue(const Op0_t &Op0)
VPInstruction_match< Instruction::ExtractElement, Op0_t, Op1_t > m_ExtractElement(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ExtractLastLane, Op0_t > m_ExtractLastLane(const Op0_t &Op0)
int_pred_ty< is_zero_int, 1 > m_False()
match_bind< VPSingleDefRecipe > m_VPSingleDefRecipe(VPSingleDefRecipe *&V)
Match a VPSingleDefRecipe, capturing if we match.
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
auto m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1)
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExtractVectorForPart, Op0_t, Op1_t > m_ExtractVectorForPart(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > m_ExtractLastPart(const Op0_t &Op0)
VPRecipeBase * findUserOf(VPValue *V, const MatchT &P)
If V is used by a recipe matching pattern P, return it.
VPInstruction_match< VPInstruction::Broadcast, Op0_t > m_Broadcast(const Op0_t &Op0)
header_mask_match m_HeaderMask()
VPInstruction_match< VPInstruction::BuildVector > m_BuildVector()
BuildVector is matches only its opcode, w/o matching its operands as the number of operands is not fi...
VPInstruction_match< VPInstruction::ExtractPenultimateElement, Op0_t > m_ExtractPenultimateElement(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
VPInstruction_match< VPInstruction::FirstActiveLane, Op0_t > m_FirstActiveLane(const Op0_t &Op0)
int_pred_ty< is_one, 1 > m_True()
auto m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
VPInstruction_match< VPInstruction::ExtractLane, Op0_t, Op1_t > m_ExtractLane(const Op0_t &Op0, const Op1_t &Op1)
auto m_AnyNeg(const Op0_t &Op0)
VPInstruction_match< VPInstruction::Reverse, Op0_t > m_Reverse(const Op0_t &Op0)
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
bool cannotHoistOrSinkRecipe(const VPRecipeBase &R, bool Sinking=false)
Return true if we do not know how to (mechanically) hoist or sink R.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
std::optional< int64_t > getConstantStride(VPValue *Addr, Type *AccessTy, PredicatedScalarEvolution &PSE, const Loop *L)
If the pointer operand Addr of a memory access is an affine AddRec w.r.t.
VPInstruction * findComputeReductionResult(VPReductionPHIRecipe *PhiR)
Find the ComputeReductionResult recipe for PhiR, looking through selects inserted for predicated redu...
VPInstruction * findCanonicalIVIncrement(VPlan &Plan)
Find the canonical IV increment of Plan's vector loop region.
std::optional< MemoryLocation > getMemoryLocation(const VPRecipeBase &R)
Return a MemoryLocation for R with noalias metadata populated from R, if the recipe is supported and ...
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
VPIRValue * tryToFoldLiveIns(VPSingleDefRecipe &R, ArrayRef< VPValue * > Operands, const DataLayout &DL)
Try to fold R using InstSimplifyFolder.
SmallVector< std::pair< VPBasicBlock *, VPIRBasicBlock * > > getEarlyExits(const VPlan &Plan, const VPBlockBase *MiddleVPBB)
Returns the (early exiting block, exit block) pairs of Plan, i.e.
void recursivelyDeleteDeadRecipes(VPValue *V)
Recursively delete V and any of its operands that become dead.
bool doesGeneratePerAllLanes(const VPRecipeBase *R)
Returns true if R produces scalar values for all VF lanes.
bool isDeadRecipe(VPRecipeBase &R)
Returns true if R is dead, i.e.
VPRecipeBase * findRecipe(VPValue *Start, PredT Pred)
Search Start's users for a recipe satisfying Pred, looking through recipes with definitions.
LLVM_ABI_FOR_TEST bool isUniformAcrossVFsAndUFs(const VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
bool isUsedByLoadStoreAddress(const VPValue *V)
Returns true if V is used as part of the address of another load or store.
std::optional< std::pair< bool, unsigned > > getOpcodeOrIntrinsicID(const VPValue *V)
Get the instruction opcode or intrinsic ID for the recipe defining V.
VPValue * scalarizeVPWidenPointerInduction(VPWidenPointerInductionRecipe *PtrIV, VPlan &Plan, VPBuilder &Builder)
Scalarize a VPWidenPointerInductionRecipe by replacing it with a PtrAdd (IndStart,...
LLVM_ABI_FOR_TEST const SCEV * getSCEVExprForVPValue(const VPValue *V, PredicatedScalarEvolution &PSE, const Loop *L=nullptr)
Return the SCEV expression for V.
void pullOutPermutations(VPlan &Plan, Match_t Perm, Builder Build)
Removes the permutation pattern Perm from any elementwise operations in the plan, by constructing a n...
SmallVector< VPUser * > collectUsersRecursively(VPValue *V)
Collect all users of V, looking through recipes that define other values.
VPScalarIVStepsRecipe * createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind, Instruction::BinaryOps InductionOpcode, FPMathOperator *FPBinOp, Instruction *TruncI, VPValue *StartV, VPValue *Step, DebugLoc DL, VPBuilder &Builder, const VPIRFlags::WrapFlagsTy &Flags={})
Create a scalar-iv-steps recipe over Plan's canonical IV for an induction of Kind with InductionOpcod...
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.
SmallVector< VPBasicBlock * > vp_rpo_plain_cfg_loop_body(VPBasicBlock *Header)
Returns the VPBasicBlocks forming the loop body of a plain (pre-region) VPlan in reverse post-order s...
void stable_sort(R &&Range)
auto min_element(R &&Range)
Provide wrappers to std::min_element 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.
unsigned getLoadStoreAddressSpace(const Value *I)
A helper function that returns the address space of the pointer operand of load or store instruction.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
ReductionStyle getReductionStyle(bool InLoop, bool Ordered, unsigned ScaleFactor)
DenseMap< const Value *, const SCEV * > ValueToSCEVMapTy
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.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr from_range_t from_range
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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...
auto cast_or_null(const Y &Val)
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
iterator_range< df_iterator< VPBlockShallowTraversalWrapper< VPBlockBase * > > > vp_depth_first_shallow(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order.
constexpr auto bind_back(FnT &&Fn, BindArgsT &&...BindArgs)
C++23 bind_back.
bool isa_and_nonnull(const Y &Val)
iterator_range< df_iterator< VPBlockDeepTraversalWrapper< VPBlockBase * > > > vp_depth_first_deep(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order while traversing t...
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
auto dyn_cast_or_null(const Y &Val)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
constexpr size_t range_size(R &&Range)
Returns the size of the Range, i.e., the number of elements.
void sort(IteratorTy Start, IteratorTy End)
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
bool hasIrregularType(Type *Ty, const DataLayout &DL)
A helper function that returns true if the given type is irregular.
UncountableExitStyle
Different methods of handling early exits.
@ ReadOnly
No side effects to worry about, so we can process any uncountable exits in the loop and branch either...
@ MaskedHandleExitInScalarLoop
All memory operations other than the load(s) required to determine whether an uncountable exit occurr...
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
bool canConstantBeExtended(const APInt *C, Type *NarrowType, TTI::PartialReductionExtendKind ExtKind)
Check if a constant CI can be safely treated as having been extended from a narrower type with the gi...
T * find_singleton(R &&Range, Predicate P, bool AllowRepeats=false)
Return the single value in Range that satisfies P(<member of Range> *, AllowRepeats)->T * returning n...
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...
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
RecurKind
These are the kinds of recurrences that we support.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ FindIV
FindIV reduction with select(icmp(),x,y) where one of (x,y) is a loop induction variable (increasing ...
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
LLVM_ABI Value * getRecurrenceIdentity(RecurKind K, Type *Tp, FastMathFlags FMF)
Given information about an recurrence kind, return the identity for the @llvm.vector....
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L, ScalarEvolution &SE, DominatorTree &DT, AssumptionCache *AC=nullptr, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Return true if we can prove that the given load (which is assumed to be within the specified loop) wo...
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
VPBasicBlock * EarlyExitingVPBB
VPIRBasicBlock * EarlyExitVPBB
This struct is a compact representation of a valid (non-zero power of two) alignment.
An information struct used to provide DenseMap with the various necessary components for a given valu...
This reduction is unordered with the partial result scaled down by some factor.
Holds the VFShape for a specific scalar to vector function mapping.
Encapsulates information needed to describe a parameter.
A range of powers-of-2 vectorization factors with fixed start and adjustable end.
Struct to hold various analysis needed for cost computations.
const VFSelectionContext & Config
static bool isFreeScalarIntrinsic(Intrinsic::ID ID)
Returns true if ID is a pseudo intrinsic that is dropped via scalarization rather than widened.
bool isMaskRequired(Instruction *I) const
Forwards to LoopVectorizationCostModel::isMaskRequired.
PredicatedScalarEvolution & PSE
bool willBeScalarized(Instruction *I, ElementCount VF) const
Returns true if I is known to be scalarized at VF.
TargetTransformInfo::TargetCostKind CostKind
const TargetLibraryInfo & TLI
const TargetTransformInfo & TTI
A recipe for handling first-order recurrence phis.
A VPValue representing a live-in from the input IR or a constant.
Type * getType() const
Returns the type of the underlying IR value.
A recipe for widening load operations, using the address to load from and an optional mask.
A recipe for widening store operations, using the stored value, the address to store to and an option...