49 if (ToPtr ==
cast<VectorType>(V->getType())->getElementType()->isPointerTy())
50 return Builder.CreateBitOrPointerCast(V, DstTy);
52 return Builder.CreateIntToPtr(
53 Builder.CreateBitCast(V,
DL.getIntPtrType(DstTy)), DstTy);
54 return Builder.CreateBitCast(
55 Builder.CreatePtrToInt(V,
DL.getIntPtrType(V->getType())), DstTy);
64 uint64_t ElementSize =
DL.getTypeAllocSize(ScalarTy).getFixedValue();
65 APInt Bytes = CI->getValue() * ElementSize;
66 return ConstantInt::get(CI->getContext(), IsReverse ? -Bytes : Bytes);
71 bool CompareOpcodes) {
77 return (!GEP1 || GEP1->getNumOperands() == 2) &&
78 (!GEP2 || GEP2->getNumOperands() == 2) &&
79 (((!GEP1 ||
isConstant(GEP1->getOperand(1))) &&
83 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
91 return CommonAlignment;
101 const SCEV *PtrSCEVLowest =
nullptr;
102 const SCEV *PtrSCEVHighest =
nullptr;
105 for (
Value *Ptr : PointerOps) {
110 if (!PtrSCEVLowest && !PtrSCEVHighest) {
111 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
118 PtrSCEVLowest = PtrSCEV;
125 PtrSCEVHighest = PtrSCEV;
134 auto TryGetStride = [&](
const SCEV *Dist,
135 const SCEV *Multiplier) ->
const SCEV * {
137 if (M->getOperand(0) == Multiplier)
138 return M->getOperand(1);
139 if (M->getOperand(1) == Multiplier)
140 return M->getOperand(0);
143 if (Multiplier == Dist)
148 const SCEV *Stride =
nullptr;
149 if (
Size != 1 || SCEVs.
size() > 1) {
151 Stride = TryGetStride(Dist, Sz);
159 using DistOrdPair = std::pair<int64_t, int>;
161 std::set<DistOrdPair,
decltype(Compare)> Offsets(Compare);
162 bool IsConsecutive =
true;
163 for (
const auto [Idx, PtrSCEV] :
enumerate(SCEVs)) {
165 if (PtrSCEV != PtrSCEVLowest) {
167 const SCEV *Coeff = TryGetStride(Diff, Stride);
177 Dist = SC->getAPInt().getZExtValue();
182 auto Res = Offsets.emplace(Dist, Idx);
186 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
188 SortedIndices.
clear();
189 if (!IsConsecutive) {
192 for (
const auto [Idx, Pair] :
enumerate(Offsets))
193 SortedIndices[Idx] = Pair.second;
205 const unsigned Sz = PointerOps.
size();
210 std::optional<unsigned> Stride = 0;
213 Value *Ptr = Order.
empty() ? PointerOps[
I] : PointerOps[Order[
I]];
214 std::optional<int64_t> OptPos =
216 if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
218 unsigned Pos =
static_cast<unsigned>(*OptPos);
219 CompressMask[
I] = Pos;
226 if (Pos != *Stride *
I)
229 return Stride.has_value();
241 bool &IsMasked,
unsigned &InterleaveFactor,
243 InterleaveFactor = 0;
245 const size_t Sz = VL.
size();
252 if (AreAllUsersVectorized(V))
255 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy,
CostKind,
256 Mask.empty() ?
I : Mask[
I]);
259 if (ExtractCost <= ScalarCost)
265 Ptr0 = PointerOps.
front();
266 PtrN = PointerOps.
back();
268 Ptr0 = PointerOps[Order.
front()];
269 PtrN = PointerOps[Order.
back()];
271 std::optional<int64_t> Diff =
275 const size_t MaxRegSize =
279 if (*Diff / Sz >= MaxRegSize / 8)
283 Align CommonAlignment = LI->getAlign();
288 if (IsMasked && !
TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
289 LI->getPointerAddressSpace()))
295 assert(CompressMask.
size() >= 2 &&
"At least two elements are required");
299 auto [ScalarGEPCost, VectorGEPCost] =
301 Instruction::Load,
CostKind, ScalarTy, LoadVecTy);
318 LoadCost =
TTI.getMemIntrinsicInstrCost(
321 LI->getPointerAddressSpace()),
325 TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
326 LI->getPointerAddressSpace(),
CostKind,
329 if (IsStrided && !IsMasked && Order.
empty()) {
337 AlignedLoadVecTy = LoadVecTy;
338 if (
TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
340 LI->getPointerAddressSpace())) {
342 VectorGEPCost +
TTI.getInterleavedMemoryOpCost(
343 Instruction::Load, AlignedLoadVecTy,
344 CompressMask[1], {}, CommonAlignment,
345 LI->getPointerAddressSpace(),
CostKind, IsMasked);
346 if (InterleavedCost < GatherCost) {
347 InterleaveFactor = CompressMask[1];
348 LoadVecTy = AlignedLoadVecTy;
359 if (VectorGEPCost + LoadCost >= GatherCost)
363 if (!Order.
empty()) {
366 NewMask[
I] = CompressMask[Mask[
I]];
368 CompressMask.
swap(NewMask);
370 InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
371 return TotalVecCost < GatherCost;
384 unsigned InterleaveFactor;
388 CostKind, AreAllUsersVectorized, ReVec, IsMasked,
389 InterleaveFactor, CompressMask, LoadVecTy);
399 const unsigned FirstLane = std::distance(VL.
begin(), FirstIt);
402 if (FirstLI->getFunction()->hasFnAttribute(Attribute::SanitizeMemTag))
404 Type *ScalarTy = FirstLI->getType();
405 Value *Ptr0 = FirstLI->getPointerOperand();
413 std::optional<int64_t> Dist =
416 if (!Dist || *Dist !=
static_cast<int64_t
>(Lane) - FirstLane)
423 const uint64_t EltSize =
DL.getTypeAllocSize(ScalarTy).getFixedValue();
428 bool Overflow =
false;
430 if (Overflow || Start.isNegative())
441 return std::distance(Scalars.
begin(), It) *
442 LI->getDataLayout().getTypeAllocSize(LI->getType()).getFixedValue();
456 const size_t Sz = VL.
size();
462 std::optional<int64_t> Diff =
464 if (!Diff || *Diff <= 0)
467 const unsigned MaxRegSize =
470 const unsigned ScalarBits =
DL.getTypeSizeInBits(ScalarTy).getFixedValue();
471 if (ScalarBits == 0 ||
472 static_cast<uint64_t
>(*Diff) / Sz >= MaxRegSize / ScalarBits)
476 if (!
TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
484 Value *Ptr = Order.
empty() ? PointerOps[
I] : PointerOps[Order[
I]];
485 std::optional<int64_t>
Off =
489 ReuseShuffleIndices[*
Off] =
static_cast<int>(
I);
500 all_of(VL, [](
const Value *V) {
return V->getType()->isPointerTy(); }) &&
501 "Expected list of pointer operands.");
506 std::pair<BasicBlock *, Value *>,
510 .try_emplace(std::make_pair(BBs.
front(),
513 .emplace_back(VL.
front(), 0U, 0U);
515 SortedIndices.
clear();
518 bool Found =
any_of(Bases.try_emplace(
Key).first->second,
519 [&, &Cnt = Cnt, &Ptr = Ptr](
auto &
Base) {
520 std::optional<int64_t> Diff =
521 getPointersDiff(ElemTy, std::get<0>(Base.front()),
527 Base.emplace_back(Ptr, *Diff, Cnt + 1);
533 if (Bases.size() > VL.
size() / 2 - 1)
537 Bases.find(
Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
541 if (Bases.size() == VL.
size())
544 if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
545 Bases.front().second.size() == VL.
size()))
550 auto ComparePointers = [MaxDepth](
Value *Ptr1,
Value *Ptr2) {
557 if (P1 == P2 ||
Depth > MaxDepth)
560 SecondPointers.
insert(P2);
566 "Unable to find matching root.");
569 for (
auto &
Base : Bases) {
570 for (
auto &Vec :
Base.second) {
571 if (Vec.size() > 1) {
573 int64_t InitialOffset = std::get<1>(Vec[0]);
574 bool AnyConsecutive =
576 return std::get<1>(
P.value()) ==
577 int64_t(
P.index()) + InitialOffset;
586 return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
590 for (
auto &
T : Bases)
591 for (
const auto &Vec :
T.second)
592 for (
const auto &
P : Vec)
596 "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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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.
This is the shared class of boolean and integer constants.
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.
Common base class shared among various IRBuilders.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
An instruction for reading from memory.
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 * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
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 SCEVUse getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI SCEVUse getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical multiply 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.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
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.
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, TTI::VectorInstrContext VIC)
Returns the cost of the shuffle instructions with the given Kind, vector type Tp and optional Mask.
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.
Value * createWidenedStridedCast(IRBuilderBase &Builder, Value *V, Type *DstTy, const DataLayout &DL)
Casts V between the widened strided access type and the entry vector type DstTy.
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)
ConstantInt * getStrideBytesIfConstant(Value *Stride, Type *ScalarTy, const DataLayout &DL, bool IsReverse)
Returns Stride scaled by the allocation size of ScalarTy, negated if IsReverse is set,...
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.
uint64_t getVectorLoadShift(ArrayRef< Value * > Scalars)
Returns the distance in bytes from the start of the vector load to the first load of Scalars: the lea...
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.
bool canWidenLoadsOverUndefLanes(ArrayRef< Value * > VL, const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC, const DominatorTree &DT, const TargetLibraryInfo &TLI)
Checks if the simple loads of VL, mixed with the undef and poison lanes, can be replaced by a single ...
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.
LLVM_ABI bool mustSuppressSpeculation(const LoadInst &LI)
Return true if speculation of the given load must be suppressed to avoid ordering or interfering with...
auto dyn_cast_or_null(const Y &Val)
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...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ, bool IgnoreFree=false)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, Align Alignment, const SimplifyQuery &Q, bool IgnoreFree=false)
Returns true if V is always a dereferenceable pointer with alignment greater or equal than requested.
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
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.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
@ End
Run the machine verifier once, at the end of the pipeline.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
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:...