45 bool CompareOpcodes) {
51 return (!GEP1 || GEP1->getNumOperands() == 2) &&
52 (!GEP2 || GEP2->getNumOperands() == 2) &&
53 (((!GEP1 ||
isConstant(GEP1->getOperand(1))) &&
57 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
65 return CommonAlignment;
75 const SCEV *PtrSCEVLowest =
nullptr;
76 const SCEV *PtrSCEVHighest =
nullptr;
79 for (
Value *Ptr : PointerOps) {
84 if (!PtrSCEVLowest && !PtrSCEVHighest) {
85 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
92 PtrSCEVLowest = PtrSCEV;
99 PtrSCEVHighest = PtrSCEV;
108 auto TryGetStride = [&](
const SCEV *Dist,
109 const SCEV *Multiplier) ->
const SCEV * {
111 if (M->getOperand(0) == Multiplier)
112 return M->getOperand(1);
113 if (M->getOperand(1) == Multiplier)
114 return M->getOperand(0);
117 if (Multiplier == Dist)
122 const SCEV *Stride =
nullptr;
123 if (
Size != 1 || SCEVs.
size() > 1) {
125 Stride = TryGetStride(Dist, Sz);
133 using DistOrdPair = std::pair<int64_t, int>;
135 std::set<DistOrdPair,
decltype(Compare)> Offsets(Compare);
136 bool IsConsecutive =
true;
137 for (
const auto [Idx, PtrSCEV] :
enumerate(SCEVs)) {
139 if (PtrSCEV != PtrSCEVLowest) {
141 const SCEV *Coeff = TryGetStride(Diff, Stride);
151 Dist = SC->getAPInt().getZExtValue();
156 auto Res = Offsets.emplace(Dist, Idx);
160 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
162 SortedIndices.
clear();
163 if (!IsConsecutive) {
166 for (
const auto [Idx, Pair] :
enumerate(Offsets))
167 SortedIndices[Idx] = Pair.second;
179 const unsigned Sz = PointerOps.
size();
184 std::optional<unsigned> Stride = 0;
187 Value *Ptr = Order.
empty() ? PointerOps[
I] : PointerOps[Order[
I]];
188 std::optional<int64_t> OptPos =
190 if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
192 unsigned Pos =
static_cast<unsigned>(*OptPos);
193 CompressMask[
I] = Pos;
200 if (Pos != *Stride *
I)
203 return Stride.has_value();
215 bool &IsMasked,
unsigned &InterleaveFactor,
217 InterleaveFactor = 0;
219 const size_t Sz = VL.
size();
226 if (AreAllUsersVectorized(V))
229 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy,
CostKind,
230 Mask.empty() ?
I : Mask[
I]);
233 if (ExtractCost <= ScalarCost)
239 Ptr0 = PointerOps.
front();
240 PtrN = PointerOps.
back();
242 Ptr0 = PointerOps[Order.
front()];
243 PtrN = PointerOps[Order.
back()];
245 std::optional<int64_t> Diff =
249 const size_t MaxRegSize =
253 if (*Diff / Sz >= MaxRegSize / 8)
257 Align CommonAlignment = LI->getAlign();
262 if (IsMasked && !
TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
263 LI->getPointerAddressSpace()))
269 assert(CompressMask.
size() >= 2 &&
"At least two elements are required");
273 auto [ScalarGEPCost, VectorGEPCost] =
275 Instruction::Load,
CostKind, ScalarTy, LoadVecTy);
292 LoadCost =
TTI.getMemIntrinsicInstrCost(
295 LI->getPointerAddressSpace()),
299 TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
300 LI->getPointerAddressSpace(),
CostKind);
302 if (IsStrided && !IsMasked && Order.
empty()) {
310 AlignedLoadVecTy = LoadVecTy;
311 if (
TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
313 LI->getPointerAddressSpace())) {
315 VectorGEPCost +
TTI.getInterleavedMemoryOpCost(
316 Instruction::Load, AlignedLoadVecTy,
317 CompressMask[1], {}, CommonAlignment,
318 LI->getPointerAddressSpace(),
CostKind, IsMasked);
319 if (InterleavedCost < GatherCost) {
320 InterleaveFactor = CompressMask[1];
321 LoadVecTy = AlignedLoadVecTy;
332 if (VectorGEPCost + LoadCost >= GatherCost)
336 if (!Order.
empty()) {
339 NewMask[
I] = CompressMask[Mask[
I]];
341 CompressMask.
swap(NewMask);
343 InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
344 return TotalVecCost < GatherCost;
357 unsigned InterleaveFactor;
361 CostKind, AreAllUsersVectorized, ReVec, IsMasked,
362 InterleaveFactor, CompressMask, LoadVecTy);
376 const size_t Sz = VL.
size();
382 std::optional<int64_t> Diff =
384 if (!Diff || *Diff <= 0)
387 const unsigned MaxRegSize =
390 const unsigned ScalarBits =
DL.getTypeSizeInBits(ScalarTy).getFixedValue();
391 if (ScalarBits == 0 ||
392 static_cast<uint64_t
>(*Diff) / Sz >= MaxRegSize / ScalarBits)
396 if (!
TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
404 Value *Ptr = Order.
empty() ? PointerOps[
I] : PointerOps[Order[
I]];
405 std::optional<int64_t> Off =
407 if (!Off || *Off <= Prev || *Off > *Diff)
409 ReuseShuffleIndices[*Off] =
static_cast<int>(
I);
420 all_of(VL, [](
const Value *V) {
return V->getType()->isPointerTy(); }) &&
421 "Expected list of pointer operands.");
426 std::pair<BasicBlock *, Value *>,
430 .try_emplace(std::make_pair(BBs.
front(),
433 .emplace_back(VL.
front(), 0U, 0U);
435 SortedIndices.
clear();
438 bool Found =
any_of(Bases.try_emplace(
Key).first->second,
439 [&, &Cnt = Cnt, &Ptr = Ptr](
auto &
Base) {
440 std::optional<int64_t> Diff =
441 getPointersDiff(ElemTy, std::get<0>(Base.front()),
447 Base.emplace_back(Ptr, *Diff, Cnt + 1);
453 if (Bases.size() > VL.
size() / 2 - 1)
457 Bases.find(
Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
461 if (Bases.size() == VL.
size())
464 if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
465 Bases.front().second.size() == VL.
size()))
470 auto ComparePointers = [MaxDepth](
Value *Ptr1,
Value *Ptr2) {
477 if (P1 == P2 ||
Depth > MaxDepth)
480 SecondPointers.
insert(P2);
486 "Unable to find matching root.");
489 for (
auto &
Base : Bases) {
490 for (
auto &Vec :
Base.second) {
491 if (Vec.size() > 1) {
493 int64_t InitialOffset = std::get<1>(Vec[0]);
494 bool AnyConsecutive =
496 return std::get<1>(
P.value()) ==
497 int64_t(
P.index()) + InitialOffset;
506 return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
510 for (
auto &
T : Bases)
511 for (
const auto &Vec :
T.second)
512 for (
const auto &
P : Vec)
516 "Expected SortedIndices to be the size of VL");
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 GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 MaybeAlign getAlign(Value *Ptr)
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
This file implements a map that provides insertion order iteration.
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
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.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
A cache of @llvm.assume calls within a function.
A parsed version of the target data layout string in and methods for querying it.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Class to represent fixed width SIMD vectors.
Information for memory intrinsic cost model.
This class represents an analyzed expression in the program.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI bool isNonConstantNegative() const
Return true if the specified scev is negated, but not a constant.
Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI const SCEV * getUDivExactExpr(SCEVUse LHS, SCEVUse RHS)
Get a canonical unsigned division expression, or something simpler if possible.
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 assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void swap(SmallVectorImpl &RHS)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
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.
LLVM Value Representation.
Base class of all SIMD vector types.
An efficient, type-erasing, non-owning reference to a callable.
A private "module" namespace for types and utilities used by this pass.
template Align computeCommonAlignment< StoreInst >(ArrayRef< Value * >)
std::pair< InstructionCost, InstructionCost > getGEPCosts(const TargetTransformInfo &TTI, ArrayRef< Value * > Ptrs, Value *BasePtr, unsigned Opcode, const TTI::TargetCostKind CostKind, Type *ScalarTy, VectorType *VecTy)
Calculate the scalar and the vector costs from vectorizing set of GEPs.
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Align computeCommonAlignment(ArrayRef< Value * > VL)
Calculates minimal alignment as a common alignment.
template Align computeCommonAlignment< LoadInst >(ArrayRef< Value * >)
const SCEV * calculateRtStride(ArrayRef< Value * > PointerOps, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< unsigned > &SortedIndices)
Checks if the provided list of pointers Pointers represents the strided pointers for type ElemTy.
Type * getWidenedType(Type *ScalarTy, unsigned VF)
InstructionCost getShuffleCost(const TargetTransformInfo &TTI, TTI::ShuffleKind Kind, VectorType *Tp, const TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args)
Returns the cost of the shuffle instructions with the given Kind, vector type Tp and optional Mask.
static bool buildCompressMask(ArrayRef< Value * > PointerOps, ArrayRef< unsigned > Order, Type *ScalarTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< int > &CompressMask)
Builds compress-like mask for shuffles for the given PointerOps, ordered with Order.
void inversePermutation(ArrayRef< unsigned > Indices, SmallVectorImpl< int > &Mask)
Compute the inverse permutation Mask of Indices.
bool isMaskedStoreCompress(ArrayRef< Value * > VL, ArrayRef< Value * > PointerOps, ArrayRef< unsigned > Order, const TargetTransformInfo &TTI, const DataLayout &DL, ScalarEvolution &SE, Align CommonAlignment, SmallVectorImpl< int > &ReuseShuffleIndices, FixedVectorType *&StoreVecTy)
Checks if the stores VL with pointers PointerOps can be lowered as a single masked store.
InstructionCost getScalarizationOverhead(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, const TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef< Value * > VL, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getScalarizationOverhead, but if ScalarTy is a FixedVectorTyp...
InstructionsState getSameOpcode(ArrayRef< Value * > VL, const TargetLibraryInfo &TLI)
bool isMaskedLoadCompress(ArrayRef< Value * > VL, ArrayRef< Value * > PointerOps, ArrayRef< unsigned > Order, const TargetTransformInfo &TTI, const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC, const DominatorTree &DT, const TargetLibraryInfo &TLI, const TargetTransformInfo::TargetCostKind CostKind, const function_ref< bool(Value *)> AreAllUsersVectorized, bool ReVec, bool &IsMasked, unsigned &InterleaveFactor, SmallVectorImpl< int > &CompressMask, VectorType *&LoadVecTy)
Checks if the VL can be transformed to a (masked)load + compress or (masked) interleaved load.
bool arePointersCompatible(Value *Ptr1, Value *Ptr2, const TargetLibraryInfo &TLI, unsigned MaxDepth, bool CompareOpcodes)
MaxDepth is the recursion limit for getUnderlyingObject.
bool isConstant(Value *V)
bool clusterSortPtrAccesses(ArrayRef< Value * > VL, ArrayRef< BasicBlock * > BBs, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, unsigned MaxDepth, SmallVectorImpl< unsigned > &SortedIndices)
Clusters VL pointers by (basic block, underlying object) pair and sorts each cluster by offset.
unsigned getFullVectorNumberOfElements(const TargetTransformInfo &TTI, Type *Ty, unsigned Sz, bool ReVec)
Returns the number of elements of the given type Ty, not less than Sz, which forms type,...
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
auto accumulate(R &&Range, E &&Init)
Wrapper for std::accumulate.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::optional< int64_t > getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB, Value *PtrB, const DataLayout &DL, ScalarEvolution &SE, bool StrictCheck=false, bool CheckType=true)
Returns the distance between the pointers PtrA and PtrB iff they are compatible and it is possible to...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
constexpr int PoisonMaskElem
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
This struct is a compact representation of a valid (non-zero power of two) alignment.
A MapVector that performs no allocations if smaller than a certain size.
Function object to check whether the first component of a container supported by std::get (like std::...
Function object to check whether the second component of a container supported by std::get (like std:...