57 R.getVPSingleValue()->replaceAllUsesWith(Trunc);
70 template <
typename OpTy>
bool match(
OpTy *V)
const {
81template <
typename Op0_t,
typename Op1_t>
89 case Intrinsic::masked_udiv:
90 return Intrinsic::vp_udiv;
91 case Intrinsic::masked_sdiv:
92 return Intrinsic::vp_sdiv;
93 case Intrinsic::masked_urem:
94 return Intrinsic::vp_urem;
95 case Intrinsic::masked_srem:
96 return Intrinsic::vp_srem;
116 auto AdjustEndPtr = [&CurRecipe, &EVL](
VPValue *EndPtr) {
118 EVLEndPtr->insertBefore(&CurRecipe);
123 EVLEndPtr->setOperand(1, EVLAsVF);
127 auto GetVPReverse = [&CurRecipe, &EVL, Plan,
132 Intrinsic::experimental_vp_reverse, {V, Plan->
getTrue(), &EVL},
133 V->getScalarType(), {}, {},
DL);
134 Reverse->insertBefore(&CurRecipe);
138 if (
match(&CurRecipe,
143 if (
match(&CurRecipe,
147 Mask = GetVPReverse(Mask);
148 Addr = AdjustEndPtr(EndPtr);
151 LoadR->insertBefore(&CurRecipe);
155 LoadR->getScalarType(), {}, {},
DL);
166 NewLoad->setOperand(2, Mask);
167 NewLoad->setOperand(3, &EVL);
175 StoredVal, EVL, Mask);
177 if (
match(&CurRecipe,
181 Mask = GetVPReverse(Mask);
182 Addr = AdjustEndPtr(EndPtr);
185 Intrinsic::vector_splice_right, {StoredVal,
Poison, &EVL},
193 if (Rdx->isConditional() &&
198 if (Interleave->getMask() &&
206 Intrinsic::vp_merge, {Mask ? Mask : Plan->
getTrue(),
LHS,
RHS, &EVL},
207 LHS->getScalarType(), {}, {},
DL);
220 if (
match(&CurRecipe,
225 LHS->getScalarType(), {}, {},
DL);
231 {IntrR->getOperand(0),
232 IntrR->getOperand(1),
233 Mask ? Mask : Plan->
getTrue(), &EVL},
234 IntrR->getScalarType(), {}, {},
DL);
243 VPValue *HeaderMask =
nullptr, *EVL =
nullptr;
248 HeaderMask = R.getVPSingleValue();
259 NewR->insertBefore(R);
260 for (
auto [Old, New] :
261 zip_equal(R->definedValues(), NewR->definedValues()))
262 Old->replaceAllUsesWith(New);
275 Mask->getScalarType(), {}, {}, LogicalAnd->getDebugLoc());
276 Merge->insertBefore(LogicalAnd);
277 LogicalAnd->replaceAllUsesWith(
Merge);
291 [&Plan, &EVL](
auto *
X) {
293 Intrinsic::vector_splice_left,
294 {Plan.
getPoison(
X->getScalarType()),
X, EVL},
X->getScalarType(),
295 {}, {},
X->getDebugLoc());
306 R->getVPSingleValue()->getNumUsers() == 0) {
316 R->getVPSingleValue()->replaceAllUsesWith(
X);
330 Intrinsic::experimental_vp_reverse, {
X, Plan.
getTrue(), EVL},
331 X->getScalarType(), {}, {}, R->getDebugLoc());
332 VPReverse->insertBefore(R);
333 R->getVPSingleValue()->replaceAllUsesWith(VPReverse);
339 R->eraseFromParent();
361 IsaPred<VPVectorEndPointerRecipe, VPScalarIVStepsRecipe,
362 VPWidenIntOrFpInductionRecipe,
363 VPWidenMemIntrinsicRecipe>;
364 if (match(U, m_Trunc(m_Specific(&Plan.getVF()))))
365 return all_of(cast<VPSingleDefRecipe>(U)->users(),
367 return IsAllowedUser(U);
369 "User of VF that we can't transform to EVL.");
379 "Only users of VFxUF should be VPWidenPointerInductionRecipe and the "
380 "increment of the canonical induction.");
396 MaxEVL = Builder.createScalarZExtOrTrunc(
400 Builder.setInsertPoint(Header, Header->getFirstNonPhi());
401 VPValue *PrevEVL = Builder.createScalarPhi(
415 Intrinsic::experimental_vp_splice,
416 {
V1, V2, Imm, Plan.
getTrue(), PrevEVL, &EVL},
417 R.getVPSingleValue()->getScalarType(), {}, {}, R.getDebugLoc());
419 R.getVPSingleValue()->replaceAllUsesWith(VPSplice);
432 if (match(&R, m_ComputeReductionResult(m_Select(m_Specific(HeaderMask),
433 m_VPValue(), m_VPValue()))))
434 return R.getOperand(0)->getDefiningRecipe()->getRegion() ==
435 Plan.getVectorLoopRegion();
444 VPValue *EVLMask = Builder.createICmp(
504 VPlan &Plan,
const std::optional<unsigned> &MaxSafeElements) {
516 auto *CurrentIteration =
518 CurrentIteration->insertBefore(*Header, Header->begin());
519 VPBuilder Builder(Header, Header->getFirstNonPhi());
522 VPPhi *AVLPhi = Builder.createScalarPhi(
526 if (MaxSafeElements) {
536 Builder.setInsertPoint(CanonicalIVIncrement);
540 OpVPEVL = Builder.createScalarZExtOrTrunc(
541 OpVPEVL, CanIVTy, I32Ty, CanonicalIVIncrement->getDebugLoc());
543 auto *NextIter = Builder.createAdd(
544 OpVPEVL, CurrentIteration, CanonicalIVIncrement->getDebugLoc(),
545 "current.iteration.next", CanonicalIVIncrement->getNoWrapFlags());
546 CurrentIteration->addBackedgeValue(NextIter);
550 "avl.next", {
true,
false});
558 CanonicalIV->replaceUsesWithIf(CurrentIteration,
559 [CanonicalIVIncrement](
VPUser &U,
unsigned) {
560 return &U != CanonicalIVIncrement;
575 assert(!CurrentIteration &&
576 "Found multiple CurrentIteration. Only one expected");
577 CurrentIteration = PhiR;
581 if (!CurrentIteration)
592 CurrentIteration->
getDebugLoc(),
"current.iteration.iv");
601 CanIVInc->eraseFromParent();
619 if (!
match(EVLPhi->getBackedgeValue(),
632 [[maybe_unused]]
bool FoundAVLNext =
635 assert(FoundAVLNext &&
"Didn't find AVL backedge?");
643 [[maybe_unused]]
bool FoundIncrement =
match(
650 "Expected BranchOnCond with ICmp comparing CanIV + VFxUF with vector "
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a LoopVectorizationPlanner class.
static RemoveMask_match< Op0_t, Op1_t > m_RemoveMask(const Op0_t &In, Op1_t &Out)
Match a specific mask In, or a combination of it (logical-and In, Out).
static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL)
After replacing the canonical IV with a EVL-based IV, fixup recipes that use VF to use the EVL instea...
static std::optional< Intrinsic::ID > getVPDivRemIntrinsic(Intrinsic::ID IntrID)
static VPRecipeBase * optimizeMaskToEVL(VPValue *HeaderMask, VPRecipeBase &CurRecipe, VPValue &EVL)
Try to optimize a CurRecipe masked by HeaderMask to a corresponding EVL-based recipe without the head...
This file contains the declarations of different VPlan-related auxiliary helpers.
This file contains the declarations of the Vectorization Plan base classes:
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
A parsed version of the target data layout string in and methods for querying it.
static DebugLoc getCompilerGenerated()
static DebugLoc getUnknown()
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.
This class represents an analyzed expression in the program.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
LLVM_ABI const SCEV * getElementCount(Type *Ty, ElementCount EC, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
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,...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
iterator begin()
Recipe iterator methods.
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
const VPBasicBlock * getExitingBasicBlock() const
const VPBasicBlock * getEntryBasicBlock() const
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
VPlan-based builder utility analogous to IRBuilder.
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, Type *SrcTy, DebugLoc DL)
static VPBuilder getToInsertAfter(VPRecipeBase *R)
Create a VPBuilder to insert after R.
VPPhi * createScalarPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", const VPIRFlags &Flags={}, Type *ResultTy=nullptr)
A recipe for generating the phi node tracking the current scalar iteration index.
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
static VPIRFlags getDefaultFlags(unsigned Opcode)
Returns default flags for Opcode for opcodes that support it, asserts otherwise.
This is a concrete Recipe that models a single VPlan-level instruction.
A recipe for interleaved memory operations with vector-predication intrinsics.
void addIncoming(VPValue *IncomingV)
Append IncomingV as an incoming value to the phi-like recipe.
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
VPBasicBlock * getParent()
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
void insertBefore(VPRecipeBase *InsertPos)
Insert an unlinked recipe into a basic block immediately before the specified recipe.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A recipe to represent inloop reduction operations with vector-predication intrinsics,...
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
const VPBlockBase * getEntry() const
VPInstruction * getOrCreateCanonicalIVIncrement()
Get the canonical IV increment instruction if it exists.
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.
VPBasicBlock * getPreheaderVPBB()
Returns the pre-header VPBasicBlock of the loop region.
VPRegionValue * getHeaderMask() const
Return the header mask of the region, or null if not set.
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
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.
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
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 for widening vector intrinsics.
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
const DataLayout & getDataLayout() const
LLVMContext & getContext() const
VPBasicBlock * getEntry()
VPValue * getTripCount() const
The trip count of the original loop.
VPIRValue * getFalse()
Return a VPIRValue wrapping i1 false.
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
VPSymbolicValue & getVectorTripCount()
The vector trip count.
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.
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
VPIRValue * getTrue()
Return a VPIRValue wrapping i1 true.
bool hasScalarVFOnly() const
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
VPIRValue * getConstantInt(Type *Ty, uint64_t Val, bool IsSigned=false)
Return a VPIRValue wrapping a ConstantInt with the given type and value.
self_iterator getIterator()
match_isa< To... > m_Isa()
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, TruncInst >, OpTy > m_TruncOrSelf(const OpTy &Op)
auto m_Poison()
Match an arbitrary poison constant.
match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)
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.
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)
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, 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.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
auto m_MaskedLoad(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedLoad Intrinsic.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
AllRecipe_commutative_match< Instruction::Or, Op0_t, Op1_t > m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::StepVector > m_StepVector()
VPInstruction_match< VPInstruction::LastActiveLane, Op0_t > m_LastActiveLane(const Op0_t &Op0)
specific_intval< 1 > m_True()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VectorEndPointerRecipe_match< Op0_t, Op1_t > m_VecEndPtr(const Op0_t &Op0, const Op1_t &Op1)
VPRecipeBase * findUserOf(VPValue *V, const MatchT &P)
If V is used by a recipe matching pattern P, return it.
VPInstruction_match< VPInstruction::ExplicitVectorLength, Op0_t > m_EVL(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
VPInstruction_match< VPInstruction::Reverse, Op0_t > m_Reverse(const Op0_t &Op0)
VPIRValue * tryToFoldLiveIns(VPSingleDefRecipe &R, ArrayRef< VPValue * > Operands, const DataLayout &DL)
Try to fold R using InstSimplifyFolder.
void recursivelyDeleteDeadRecipes(VPValue *V)
Recursively delete V and any of its operands that become dead.
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.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
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...
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)
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...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
RemoveMask_match(const Op0_t &In, Op1_t &Out)
bool match(OpTy *V) const
A recipe for widening load operations with vector-predication intrinsics, using the address to load f...
A recipe for widening store operations with vector-predication intrinsics, using the value to store,...