57 R.getVPSingleValue()->replaceAllUsesWith(Trunc);
66 case Intrinsic::masked_udiv:
67 return Intrinsic::vp_udiv;
68 case Intrinsic::masked_sdiv:
69 return Intrinsic::vp_sdiv;
70 case Intrinsic::masked_urem:
71 return Intrinsic::vp_urem;
72 case Intrinsic::masked_srem:
73 return Intrinsic::vp_srem;
93 auto AdjustEndPtr = [&CurRecipe, &EVL](
VPValue *EndPtr) {
95 EVLEndPtr->insertBefore(&CurRecipe);
100 EVLEndPtr->setOperand(1, EVLAsVF);
104 auto GetVPReverse = [&CurRecipe, &EVL, Plan,
109 Intrinsic::experimental_vp_reverse, {V, Plan->
getTrue(), &EVL},
110 V->getScalarType(), {}, {},
DL);
111 Reverse->insertBefore(&CurRecipe);
115 if (
match(&CurRecipe,
120 if (
match(&CurRecipe,
124 Mask = GetVPReverse(Mask);
125 Addr = AdjustEndPtr(EndPtr);
128 LoadR->insertBefore(&CurRecipe);
132 LoadR->getScalarType(), {}, {},
DL);
135 if (
match(&CurRecipe,
140 NewLoad->setOperand(2, Mask ? Mask : Plan->
getTrue());
141 NewLoad->setOperand(3, &EVL);
149 StoredVal, EVL, Mask);
151 if (
match(&CurRecipe,
155 Mask = GetVPReverse(Mask);
156 Addr = AdjustEndPtr(EndPtr);
159 Intrinsic::vector_splice_right, {StoredVal,
Poison, &EVL},
171 NewStore->setOperand(3, Mask ? Mask : Plan->
getTrue());
172 NewStore->setOperand(4, &EVL);
177 if (Rdx->isConditional() &&
182 if (Interleave->getMask() &&
190 Intrinsic::vp_merge, {Mask ? Mask : Plan->
getTrue(),
LHS,
RHS, &EVL},
191 LHS->getScalarType(), {}, {},
DL);
202 if (
match(&CurRecipe,
207 LHS->getScalarType(), {}, {},
DL);
213 {IntrR->getOperand(0),
214 IntrR->getOperand(1),
215 Mask ? Mask : Plan->
getTrue(), &EVL},
216 IntrR->getScalarType(), {}, {},
DL);
238 for (
auto *R : UniqueExpressionRecipes)
241 EVLR->insertBefore(R);
242 R->replaceAllUsesWith(EVLR);
244 replace(ExpressionRecipes, R, EVLR);
249 ExpressionRecipes.
back()->replaceAllUsesWith(
NewExpr);
259 VPValue *HeaderMask =
nullptr, *EVL =
nullptr;
264 HeaderMask = R.getVPSingleValue();
278 NewR->insertBefore(R);
279 for (
auto [Old, New] :
280 zip_equal(R->definedValues(), NewR->definedValues()))
281 Old->replaceAllUsesWith(New);
294 Mask->getScalarType(), {}, {}, LogicalAnd->getDebugLoc());
295 Merge->insertBefore(LogicalAnd);
296 LogicalAnd->replaceAllUsesWith(
Merge);
310 [&Plan, &EVL](
auto *
X) {
312 Intrinsic::vector_splice_left,
313 {Plan.
getPoison(
X->getScalarType()),
X, EVL},
X->getScalarType(),
314 {}, {},
X->getDebugLoc());
325 R->getVPSingleValue()->getNumUsers() == 0) {
335 R->getVPSingleValue()->replaceAllUsesWith(
X);
349 Intrinsic::experimental_vp_reverse, {
X, Plan.
getTrue(), EVL},
350 X->getScalarType(), {}, {}, R->getDebugLoc());
351 VPReverse->insertBefore(R);
352 R->getVPSingleValue()->replaceAllUsesWith(VPReverse);
358 R->eraseFromParent();
396 MaxEVL = Builder.createScalarZExtOrTrunc(
399 Builder.setInsertPoint(Header, Header->getFirstNonPhi());
400 VPValue *PrevEVL = Builder.createScalarPhi(
414 Intrinsic::experimental_vp_splice,
416 R.getVPSingleValue()->getScalarType(), {}, {}, R.getDebugLoc());
418 R.getVPSingleValue()->replaceAllUsesWith(VPSplice);
431 if (match(&R, m_ComputeReductionResult(m_Select(m_Specific(HeaderMask),
432 m_VPValue(), m_VPValue()))))
433 return R.getOperand(0)->getDefiningRecipe()->getRegion() ==
434 Plan.getVectorLoopRegion();
443 VPValue *EVLMask = Builder.createICmp(
503 VPlan &Plan,
const std::optional<unsigned> &MaxSafeElements) {
515 auto *CurrentIteration =
517 CurrentIteration->insertBefore(*Header, Header->begin());
518 VPBuilder Builder(Header, Header->getFirstNonPhi());
521 VPPhi *AVLPhi = Builder.createScalarPhi(
525 if (MaxSafeElements) {
535 Builder.setInsertPoint(CanonicalIVIncrement);
538 OpVPEVL = Builder.createScalarZExtOrTrunc(
539 OpVPEVL, CanIVTy, CanonicalIVIncrement->getDebugLoc());
541 auto *NextIter = Builder.createAdd(
542 OpVPEVL, CurrentIteration, CanonicalIVIncrement->getDebugLoc(),
543 "current.iteration.next", CanonicalIVIncrement->getNoWrapFlags());
544 CurrentIteration->addBackedgeValue(NextIter);
548 "avl.next", {
true,
false});
556 CanonicalIV->replaceUsesWithIf(CurrentIteration,
557 [CanonicalIVIncrement](
VPUser &U,
unsigned) {
558 return &U != CanonicalIVIncrement;
573 assert(!CurrentIteration &&
574 "Found multiple CurrentIteration. Only one expected");
575 CurrentIteration = &PhiR;
579 if (!CurrentIteration)
590 CurrentIteration->
getDebugLoc(),
"current.iteration.iv");
599 CanIVInc->eraseFromParent();
617 if (!
match(EVLPhi->getBackedgeValue(),
630 [[maybe_unused]]
bool FoundAVLNext =
633 assert(FoundAVLNext &&
"Didn't find AVL backedge?");
641 [[maybe_unused]]
bool FoundIncrement =
match(
648 "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.
This file implements a set that has insertion order iteration characteristics.
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 bool optimizeExpressionRecipeToEVL(VPValue *HeaderMask, VPRecipeBase &CurRecipe, VPValue &EVL, SmallVector< VPRecipeBase * > &OldRecipes)
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.
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,...
A SetVector that performs no allocations if smaller than a certain size.
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.
VPPhi * createScalarPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", std::optional< VPIRFlags > Flags=std::nullopt, Type *ResultTy=nullptr)
Create a phi with IncomingValues, using the default flags for the result type, unless Flags is set.
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, DebugLoc DL)
static VPBuilder getToInsertAfter(VPRecipeBase *R)
Create a VPBuilder to insert after R.
A recipe for generating the phi node tracking the current scalar iteration index.
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
A recipe to combine multiple recipes into a single 'expression' recipe, which should be considered a ...
static VPIRFlags getDefaultFlags(unsigned Opcode, Type *ResultTy=nullptr)
Returns default flags for Opcode and scalar ResultTy 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_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.
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)
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.
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).
int_pred_ty< is_one, 1 > m_True()
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.
auto cast_if_present(const Y &Val)
cast_if_present<X> - Functionally identical to cast, except that a null value is accepted.
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.
constexpr from_range_t from_range
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...
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.
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...
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
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.
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,...