25#define DEBUG_TYPE "vplan"
44 while (!Worklist.
empty()) {
47 auto *OpR =
Op->getDefiningRecipe();
48 if (!OpR || OpR->mayHaveSideEffects() || EphRecipes.
contains(OpR))
51 auto *UR = dyn_cast<VPRecipeBase>(U);
52 return !UR || !EphRecipes.contains(UR);
67 for (
auto &R : *
A->getParent()) {
77 if (ParentA == ParentB)
78 return LocalComesBefore(
A,
B);
86 unsigned OverrideMaxNumRegs)
const {
89 unsigned AvailableRegs = OverrideMaxNumRegs > 0
91 :
TTI.getNumberOfRegisters(RegClass);
92 if (MaxUsers > AvailableRegs) {
95 unsigned Spills = MaxUsers - AvailableRegs;
101 << Spills <<
" spills of "
102 <<
TTI.getRegisterClassName(RegClass) <<
"\n");
142 if (!VPBB->getParent())
148 for (
VPValue *U : R.operands()) {
151 EndPoint[U] = Idx2Recipe.
size();
171 EndPoint[&WideIV] = Idx2Recipe.
size();
190 LLVM_DEBUG(
dbgs() <<
"LV(REG): Calculating max register usage:\n");
192 const auto &TTICapture =
TTI;
196 !TTICapture.isElementTypeLegalForScalableVector(Ty)))
204 OpenIntervals.
insert(CanIV);
210 for (
unsigned int Idx = 0, Sz = Idx2Recipe.
size(); Idx < Sz; ++Idx) {
214 VPValueList &
List = TransposeEnds[Idx];
220 if (
none_of(R->definedValues(),
221 [&Ends](
VPValue *Def) { return Ends.count(Def); }) &&
222 !R->mayHaveSideEffects())
232 for (
unsigned J = 0, E = VFs.
size(); J < E; ++J) {
240 for (
auto *VPV : OpenIntervals) {
251 if (VFs[J].isScalar() || VPV == CanIV ||
258 TTI.getRegisterClassForType(
false, VPV->getScalarType());
265 unsigned ScaleFactor =
268 if (ScaleFactor > 1) {
269 VF = VFs[J].divideCoefficientBy(ScaleFactor);
271 <<
" to " << VF <<
" for " << *R <<
"\n";);
275 unsigned ClassID =
TTI.getRegisterClassForType(
true, ScalarTy);
276 RegUsage[ClassID] += GetRegUsage(ScalarTy, VF);
281 auto &Entry = MaxUsages[J][Pair.first];
282 Entry = std::max(Entry, Pair.second);
287 << OpenIntervals.
size() <<
'\n');
291 for (
VPValue *DefV : R->definedValues())
293 OpenIntervals.
insert(DefV);
301 for (
unsigned Idx = 0,
End = VFs.
size(); Idx <
End; ++Idx) {
307 for (
auto *In : LoopInvariants) {
314 TTI.getRegisterClassForType(VF.
isVector(), In->getScalarType());
315 Invariant[ClassID] += GetRegUsage(In->getScalarType(), VF);
319 dbgs() <<
"LV(REG): VF = " << VFs[Idx] <<
'\n';
320 dbgs() <<
"LV(REG): Found max usage: " << MaxUsages[Idx].
size()
322 for (
const auto &pair : MaxUsages[Idx]) {
323 dbgs() <<
"LV(REG): RegisterClass: "
324 <<
TTI.getRegisterClassName(pair.first) <<
", " << pair.second
327 dbgs() <<
"LV(REG): Found invariant usage: " << Invariant.
size()
329 for (
const auto &pair : Invariant) {
330 dbgs() <<
"LV(REG): RegisterClass: "
331 <<
TTI.getRegisterClassName(pair.first) <<
", " << pair.second
352 if (VPI->getOpcode() != Instruction::GetElementPtr)
354 Ptr = VPI->getOperand(0);
357 return IRV ? IRV->getValue() :
nullptr;
364 return ObjA && ObjB &&
AA.isNoAlias(ObjA, ObjB);
374 const Loop *OuterLoop) {
378 if (!
GEP ||
GEP->getOpcode() != Instruction::GetElementPtr ||
380 !
GEP->getGEPNoWrapFlags().hasNoUnsignedSignedWrap() ||
385 if (!Idx || !Idx->hasNoUnsignedWrap())
392 std::optional<int64_t> Stride =
394 return Stride && *Stride != 0;
401 const Loop *OuterLoop) {
407 if (!R.mayReadOrWriteMemory())
419 VPBB, Latch, VPDT, PSE,
428 for (
auto [
I, StoreObj] :
enumerate(StoreObjects))
430 ArrayRef(StoreObjects).drop_front(
I + 1), LoadObjects))
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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")))
This file provides a LoopVectorizationPlanner class.
std::pair< uint64_t, uint64_t > Interval
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static bool provablyDistinctObjects(AAResults &AA, const Value *ObjA, const Value *ObjB)
Returns true if ObjA and ObjB are known and AA proves they don't alias.
static const Value * getBaseObject(VPValue *Ptr)
Returns the live-in IR value Ptr is based on, looking through GEPs, or nullptr if there is none.
static bool writesDisjointLocationsPerIteration(VPValue *Addr, Type *StoredTy, VPBasicBlock *VPBB, VPBasicBlock *Latch, const VPDominatorTree &VPDT, PredicatedScalarEvolution &PSE, const Loop *OuterLoop)
Returns true if a store of StoredTy to Addr in VPBB writes different locations on each iteration of O...
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:
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Implements a dense probed hash-table based set.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
bool properlyDominates(const DomTreeNodeBase< VPBlockBase > *A, const DomTreeNodeBase< VPBlockBase > *B) const
constexpr bool isVector() const
One or more elements.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Represents a single loop in the control flow graph.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
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.
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.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
const VPBasicBlock * getEntryBasicBlock() const
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...
A recipe for generating conditional branches on the bits of a mask.
A recipe for generating the phi node tracking the current scalar iteration index.
A recipe for converting Current into Start + Current * Step.
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
LLVM_ABI_FOR_TEST bool properlyDominates(const VPRecipeBase *A, const VPRecipeBase *B) const
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
const VPBlockBase * getEntry() const
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
const VPBlockBase * getExiting() const
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
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.
A recipe to compute a pointer to the last element of each part of a widened memory access for widened...
A recipe to compute the pointers for widened memory accesses of SourceElementTy, with the Stride expr...
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
const DataLayout & getDataLayout() const
VPSymbolicValue & getVectorTripCount()
The vector trip count.
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
LLVM Value Representation.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
bool match(Val *V, const Pattern &P)
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > m_ExtractLastPart(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
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.
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
LLVM_ABI_FOR_TEST const SCEV * getSCEVExprForVPValue(const VPValue *V, PredicatedScalarEvolution &PSE, const Loop *L=nullptr)
Return the SCEV expression for V.
unsigned getVFScaleFactor(VPRecipeBase *R)
Get the VF scaling factor applied to the recipe's output, if the recipe has one.
This is an optimization pass for GlobalISel generic memory operations.
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...
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.
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...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
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.
void collectEphemeralRecipesForVPlan(VPlan &Plan, DenseSet< VPRecipeBase * > &EphRecipes)
bool hasIrregularType(Type *Ty, const DataLayout &DL)
A helper function that returns true if the given type is irregular.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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< VPRegisterUsage, 8 > calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef< ElementCount > VFs, const TargetTransformInfo &TTI)
Estimate the register usage for Plan and vectorization factors in VFs by calculating the highest numb...
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
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool proveOuterLoopMemorySafety(VPlan &Plan, PredicatedScalarEvolution &PSE, AAResults &AA, const VPDominatorTree &VPDT, const Loop *OuterLoop)
Returns true if the memory accesses in outer loop plain CFG Plan can be vectorized.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ End
Run the machine verifier once, at the end of the pipeline.
A MapVector that performs no allocations if smaller than a certain size.
A struct that represents some properties of the register usage of a loop.
SmallMapVector< unsigned, unsigned, 4 > MaxLocalUsers
Holds the maximum number of concurrent live intervals in the loop.
InstructionCost spillCost(const TargetTransformInfo &TTI, TargetTransformInfo::TargetCostKind CostKind, unsigned OverrideMaxNumRegs=0) const
Calculate the estimated cost of any spills due to using more registers than the number available for ...
SmallMapVector< unsigned, unsigned, 4 > LoopInvariantRegs
Holds the number of loop invariant values that are used in the loop.