14#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
15#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
200 unsigned MaxTargetVectorWidthInBits,
201 std::optional<ScalarEvolution::LoopGuards> &LoopGuards)
202 : PSE(PSE), AC(AC), DT(DT), InnermostLoop(L),
203 SymbolicStrides(SymbolicStrides),
204 MaxTargetVectorWidthInBits(MaxTargetVectorWidthInBits),
205 LoopGuards(LoopGuards) {}
231 return MaxSafeVectorWidthInBits == UINT_MAX;
237 return MaxSafeVectorWidthInBits;
242 return MaxStoreLoadForwardSafeDistanceInBits ==
243 std::numeric_limits<uint64_t>::max();
268 assert(VectorStoreSize != 0 &&
"Expected non-zero vector store size");
269 const uint64_t NumItersForStoreLoadThroughMemory = 8 * TypeByteSize;
270 if (Distance / VectorStoreSize >= NumItersForStoreLoadThroughMemory)
272 if (
uint64_t R = Distance % VectorStoreSize)
273 return LoadElementSize > R;
274 return LoadElementSize > VectorStoreSize;
281 "Expected the distance, that prevent store-load forwarding, to be "
283 return MaxStoreLoadForwardSafeDistanceInBits;
289 return ShouldRetryWithRuntimeChecks &&
297 return RecordDependences ? &Dependences :
nullptr;
313 for (
unsigned I = 0;
I < InstMap.size(); ++
I)
314 OrderMap[InstMap[
I]] =
I;
326 auto I = Accesses.find({Ptr, IsWrite});
327 if (
I != Accesses.end())
337 std::pair<const SCEV *, const SCEV *>> &
339 return PointerBounds;
343 assert(DT &&
"requested DT, but it is not available");
347 assert(AC &&
"requested AC, but it is not available");
363 const Loop *InnermostLoop;
376 unsigned AccessIdx = 0;
387 uint64_t MaxSafeVectorWidthInBits = -1U;
391 uint64_t MaxStoreLoadForwardSafeDistanceInBits =
392 std::numeric_limits<uint64_t>::max();
396 bool ShouldRetryWithRuntimeChecks =
false;
406 bool RecordDependences =
true;
416 unsigned MaxTargetVectorWidthInBits = 0;
421 std::pair<const SCEV *, const SCEV *>>
425 std::optional<ScalarEvolution::LoopGuards> &LoopGuards;
448 unsigned CommonStride = 0);
453 void mergeInStatus(VectorizationSafetyStatus S);
455 struct DepDistanceStrideAndSizeInfo {
461 std::optional<uint64_t> CommonStride;
470 DepDistanceStrideAndSizeInfo(
const SCEV *Dist,
uint64_t MaxStride,
471 std::optional<uint64_t> CommonStride,
472 uint64_t TypeByteSize,
bool AIsWrite,
474 : Dist(Dist), MaxStride(MaxStride), CommonStride(CommonStride),
475 TypeByteSize(TypeByteSize), AIsWrite(AIsWrite), BIsWrite(BIsWrite) {}
486 std::variant<Dependence::DepType, DepDistanceStrideAndSizeInfo>
487 getDependenceDistanceStrideAndSize(
const MemAccessInfo &
A, Instruction *AInst,
493 bool areAccessesCompletelyBeforeOrAfter(
const SCEV *Src,
Type *SrcTy,
494 const SCEV *Sink,
Type *SinkTy);
533 std::pair<const RuntimeCheckingPtrGroup *, const RuntimeCheckingPtrGroup *>;
586 std::optional<ScalarEvolution::LoopGuards> &LoopGuards)
587 : DC(DC), SE(SE), LoopGuards(LoopGuards) {}
592 CanUseDiffCheck =
true;
606 Type *AccessTy,
bool WritePtr,
unsigned DepSetId,
608 bool NeedsFreeze,
bool IsForked);
626 if (!CanUseDiffCheck)
646 unsigned Depth = 0)
const;
663 unsigned PtrIdx1,
unsigned PtrIdx2);
685 void mergeStencilGroups();
702 std::optional<ScalarEvolution::LoopGuards> &LoopGuards;
709 bool CanUseDiffCheck =
true;
744 bool AllowPartial =
false);
765 return PtrRtChecking.get();
771 return PtrRtChecking->getNumberOfChecks();
795 bool isWrite)
const {
796 return DepChecker->getInstructionsForAccess(Ptr, isWrite);
802 return SymbolicStrides;
811 return HasStoreStoreDependenceInvolvingLoopInvariantAddress;
817 return HasLoadStoreDependenceInvolvingLoopInvariantAddress;
822 return StoresToInvariantAddresses;
840 bool canAnalyzeLoop();
854 void collectStridedAccess(
Value *LoadOrStoreInst);
859 void emitUnsafeDependenceRemark();
861 std::unique_ptr<PredicatedScalarEvolution> PSE;
868 std::unique_ptr<RuntimePointerChecking> PtrRtChecking;
874 std::unique_ptr<MemoryDepChecker> DepChecker;
879 std::optional<ScalarEvolution::LoopGuards> LoopGuards;
886 bool CanVecMem =
false;
887 bool HasConvergentOp =
false;
888 bool HasCompletePtrRtChecking =
false;
892 bool HasStoreStoreDependenceInvolvingLoopInvariantAddress =
false;
895 bool HasLoadStoreDependenceInvolvingLoopInvariantAddress =
false;
902 std::unique_ptr<OptimizationRemarkAnalysis> Report;
928 Value *Ptr, PredicatedScalarEvolution &PSE);
946getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
947 const Loop *Lp,
const DominatorTree &DT,
949 bool ShouldCheckWrap =
true,
950 SmallVectorImpl<const SCEVPredicate *> *Predicates =
nullptr);
956getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
957 const Loop *Lp,
const DominatorTree &DT,
959 bool ShouldCheckWrap =
true);
968 const DataLayout &
DL, ScalarEvolution &SE,
969 bool StrictCheck =
false,
bool CheckType =
true);
982 const DataLayout &
DL, ScalarEvolution &SE,
983 SmallVectorImpl<unsigned> &SortedIndices);
988 ScalarEvolution &SE,
bool CheckType =
true);
1007 const Loop *Lp,
const SCEV *PtrExpr, Type *AccessTy,
const SCEV *BTC,
1008 const SCEV *MaxBTC, ScalarEvolution *SE,
1009 DenseMap<std::pair<const SCEV *, const SCEV *>,
1011 DominatorTree *DT, AssumptionCache *AC,
1012 std::optional<ScalarEvolution::LoopGuards> &LoopGuards);
1014 const Loop *Lp,
const SCEV *PtrExpr,
const SCEV *EltSizeSCEV,
1015 const SCEV *BTC,
const SCEV *MaxBTC, ScalarEvolution *SE,
1016 DenseMap<std::pair<const SCEV *, const SCEV *>,
1018 DominatorTree *DT, AssumptionCache *AC,
1019 std::optional<ScalarEvolution::LoopGuards> &LoopGuards);
1038 : SE(SE), AA(AA), DT(DT), LI(LI), TTI(TTI), TLI(TLI), AC(AC) {}
1045 FunctionAnalysisManager::Invalidator &Inv);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
static LLVM_ATTRIBUTE_ALWAYS_INLINE bool CheckType(MVT::SimpleValueType VT, SDValue N, const TargetLowering *TLI, const DataLayout &DL)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
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.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
An instruction for reading from memory.
This analysis provides dependence information for the memory accesses of a loop.
LoopAccessInfoManager Result
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
LoopAccessInfoManager(ScalarEvolution &SE, AAResults &AA, DominatorTree &DT, LoopInfo &LI, TargetTransformInfo *TTI, const TargetLibraryInfo *TLI, AssumptionCache *AC)
LLVM_ABI const LoopAccessInfo & getInfo(Loop &L, bool AllowPartial=false)
Drive the analysis of memory accesses in the loop.
const MemoryDepChecker & getDepChecker() const
the Memory Dependence Checker which can determine the loop-independent and loop-carried dependences b...
ArrayRef< StoreInst * > getStoresToInvariantAddresses() const
Return the list of stores to invariant addresses.
const OptimizationRemarkAnalysis * getReport() const
The diagnostics report generated for the analysis.
const RuntimePointerChecking * getRuntimePointerChecking() const
bool canVectorizeMemory() const
Return true we can analyze the memory accesses in the loop and there are no memory dependence cycles.
unsigned getNumRuntimePointerChecks() const
Number of memchecks required to prove independence of otherwise may-alias pointers.
const SymbolicStrideMap & getSymbolicStrides() const
If an access has a symbolic strides, this maps the pointer value to the stride symbol.
LLVM_ABI bool isInvariant(Value *V) const
Returns true if value V is loop invariant.
bool hasLoadStoreDependenceInvolvingLoopInvariantAddress() const
Return true if the loop has memory dependence involving a load and a store to an invariant address,...
LLVM_ABI void print(raw_ostream &OS, unsigned Depth=0) const
Print the information about the memory accesses in the loop.
static LLVM_ABI bool blockNeedsPredication(const BasicBlock *BB, const Loop *TheLoop, const DominatorTree *DT)
Return true if the block BB needs to be predicated in order for the loop to be vectorized.
const PredicatedScalarEvolution & getPSE() const
Used to add runtime SCEV checks.
LLVM_ABI LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetTransformInfo *TTI, const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT, LoopInfo *LI, AssumptionCache *AC, bool AllowPartial=false)
SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const
Return the list of instructions that use Ptr to read or write memory.
bool hasAllowPartial() const
Return true if, when runtime pointer checking does not have complete results, it instead has partial ...
bool hasStoreStoreDependenceInvolvingLoopInvariantAddress() const
Return true if the loop has memory dependence involving two stores to an invariant address,...
bool hasConvergentOp() const
Return true if there is a convergent operation in the loop.
Represents a single loop in the control flow graph.
Checks memory dependences among accesses to the same underlying object to determine whether there vec...
DominatorTree * getDT() const
ArrayRef< unsigned > getOrderForAccess(Value *Ptr, bool IsWrite) const
Return the program order indices for the access location (Ptr, IsWrite).
bool isSafeForAnyStoreLoadForwardDistances() const
Return true if there are no store-load forwarding dependencies.
LLVM_ABI bool areDepsSafe(const DepCandidates &AccessSets, ArrayRef< MemAccessInfo > CheckDeps)
Check whether the dependencies between the accesses are safe, and records the dependence information ...
bool isSafeForAnyVectorWidth() const
Return true if the number of elements that are safe to operate on simultaneously is not bounded.
static bool isStoreLoadForwardingConflict(uint64_t Distance, uint64_t VectorStoreSize, uint64_t TypeByteSize, uint64_t LoadElementSize=0)
Returns true if a memory dependence at byte distance Distance between a store (with element size Type...
DenseMap< std::pair< const SCEV *, const SCEV * >, std::pair< const SCEV *, const SCEV * > > & getPointerBounds()
PointerIntPair< Value *, 1, bool > MemAccessInfo
const SmallVectorImpl< Instruction * > & getMemoryInstructions() const
The vector of memory access instructions.
EquivalenceClasses< MemAccessInfo > DepCandidates
Set of potential dependent memory accesses.
bool shouldRetryWithRuntimeChecks() const
In same cases when the dependency check fails we can still vectorize the loop with a dynamic array ac...
const Loop * getInnermostLoop() const
uint64_t getMaxSafeVectorWidthInBits() const
Return the number of elements that are safe to operate on simultaneously, multiplied by the size of t...
bool isSafeForVectorization() const
No memory dependence was encountered that would inhibit vectorization.
AssumptionCache * getAC() const
const SmallVectorImpl< Dependence > * getDependences() const
Returns the memory dependences.
LLVM_ABI SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const
Find the set of instructions that read or write via Ptr.
VectorizationSafetyStatus
Type to keep track of the status of the dependence check.
@ PossiblySafeWithRtChecks
LLVM_ABI void addAccess(StoreInst *SI)
Register the location (instructions are given increasing numbers) of a write access.
PredicatedScalarEvolution & getPSE() const
uint64_t getStoreLoadForwardSafeDistanceInBits() const
Return safe power-of-2 number of elements, which do not prevent store-load forwarding,...
DenseMap< Instruction *, unsigned > generateInstructionOrderMap() const
Generate a mapping between the memory instructions and their indices according to program order.
MemoryDepChecker(PredicatedScalarEvolution &PSE, AssumptionCache *AC, DominatorTree *DT, const Loop *L, const SymbolicStrideMap &SymbolicStrides, unsigned MaxTargetVectorWidthInBits, std::optional< ScalarEvolution::LoopGuards > &LoopGuards)
PointerIntPair - This class implements a pair of a pointer and small integer.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
A set of analyses that are preserved following a run of a transformation pass.
Holds information about the memory runtime legality checks to verify that a group of pointers do not ...
RuntimePointerChecking(MemoryDepChecker &DC, ScalarEvolution *SE, std::optional< ScalarEvolution::LoopGuards > &LoopGuards)
bool Need
This flag indicates if we need to add the runtime check.
void reset()
Reset the state of the pointer runtime information.
unsigned getNumberOfChecks() const
Returns the number of run-time checks required according to needsChecking.
LLVM_ABI void printChecks(raw_ostream &OS, const SmallVectorImpl< RuntimePointerCheck > &Checks, unsigned Depth=0) const
Print Checks.
LLVM_ABI bool insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, Type *AccessTy, bool WritePtr, unsigned DepSetId, unsigned ASId, PredicatedScalarEvolution &PSE, bool NeedsFreeze, bool IsForked)
Insert a pointer and calculate the start and end SCEVs.
LLVM_ABI bool needsChecking(const RuntimeCheckingPtrGroup &M, const RuntimeCheckingPtrGroup &N) const
Decide if we need to add a check between two groups of pointers, according to needsChecking.
LLVM_ABI void print(raw_ostream &OS, unsigned Depth=0) const
Print the list run-time memory checks necessary.
std::optional< ArrayRef< PointerDiffInfo > > getDiffChecks() const
SmallVector< RuntimeCheckingPtrGroup, 2 > CheckingGroups
Holds a partitioning of pointers into "check groups".
friend struct RuntimeCheckingPtrGroup
static LLVM_ABI bool arePointersInSamePartition(const SmallVectorImpl< int > &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2)
Check if pointers are in the same partition.
LLVM_ABI void generateChecks(MemoryDepChecker::DepCandidates &DepCands)
Generate the checks and store it.
SmallVector< PointerInfo, 2 > Pointers
Information about the pointers that may require checking.
ScalarEvolution * getSE() const
const SmallVectorImpl< RuntimePointerCheck > & getChecks() const
Returns the checks that generateChecks created.
const PointerInfo & getPointerInfo(unsigned PtrIdx) const
Return PointerInfo for pointer at index PtrIdx.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Provides information about what library functions are available for the current target.
Value handle that tracks a Value across RAUW.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
Abstract Attribute helper functions.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::pair< const SCEV *, const SCEV * > getStartAndEndForAccess(const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy, const SCEV *BTC, const SCEV *MaxBTC, ScalarEvolution *SE, DenseMap< std::pair< const SCEV *, const SCEV * >, std::pair< const SCEV *, const SCEV * > > *PointerBounds, DominatorTree *DT, AssumptionCache *AC, std::optional< ScalarEvolution::LoopGuards > &LoopGuards)
Calculate Start and End points of memory access using exact backedge taken count BTC if computable or...
LLVM_ABI const SCEV * replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const SymbolicStrideMap &PtrToStride, Value *Ptr)
Return the SCEV corresponding to a pointer with the symbolic stride replaced with constant one,...
std::pair< const RuntimeCheckingPtrGroup *, const RuntimeCheckingPtrGroup * > RuntimePointerCheck
A memcheck which made up of a pair of grouped pointers.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
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 bool sortPtrAccesses(ArrayRef< Value * > VL, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< unsigned > &SortedIndices)
Attempt to sort the pointers in VL and return the sorted indices in SortedIndices,...
LLVM_ABI bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType=true)
Returns true if the memory operations A and B are consecutive.
ArrayRef(const T &OneElt) -> ArrayRef< T >
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI std::optional< int64_t > getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy, Value *Ptr, PredicatedScalarEvolution &PSE)
If AR is an affine AddRec for Lp with a constant step, return the step in units of AccessTy's allocat...
IR Values for the lower and upper bounds of a pointer evolution.
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Instruction * getDestination(const MemoryDepChecker &DepChecker) const
Return the destination instruction of the dependence.
DepType Type
The type of the dependence.
unsigned Destination
Index of the destination of the dependence in the InstMap vector.
Dependence(unsigned Source, unsigned Destination, DepType Type)
LLVM_ABI bool isPossiblyBackward() const
May be a lexically backward dependence type (includes Unknown).
Instruction * getSource(const MemoryDepChecker &DepChecker) const
Return the source instruction of the dependence.
LLVM_ABI bool isForward() const
Lexically forward dependence.
LLVM_ABI bool isBackward() const
Lexically backward dependence.
LLVM_ABI void print(raw_ostream &OS, unsigned Depth, const SmallVectorImpl< Instruction * > &Instrs) const
Print the dependence.
unsigned Source
Index of the source of the dependence in the InstMap vector.
DepType
The type of the dependence.
@ BackwardVectorizableButPreventsForwarding
@ ForwardButPreventsForwarding
static LLVM_ABI const char * DepName[]
String version of the types.
PointerDiffInfo(const SCEV *SrcStart, const SCEV *SinkStart, unsigned AccessSize, bool NeedsFreeze)
unsigned AddressSpace
Address space of the involved pointers.
LLVM_ABI bool addPointer(unsigned Index, const RuntimePointerChecking &RtCheck)
Tries to add the pointer recorded in RtCheck at index Index to this pointer checking group.
bool NeedsFreeze
Whether the pointer needs to be frozen after expansion, e.g.
LLVM_ABI RuntimeCheckingPtrGroup(unsigned Index, const RuntimePointerChecking &RtCheck)
Create a new pointer checking group containing a single pointer, with index Index in RtCheck.
const SCEV * High
The SCEV expression which represents the upper bound of all the pointers in this group.
SmallVector< unsigned, 2 > Members
Indices of all the pointers that constitute this grouping.
const SCEV * Low
The SCEV expression which represents the lower bound of all the pointers in this group.
const SCEV * Start
Holds the smallest byte address accessed by the pointer throughout all iterations of the loop.
const SCEV * Expr
SCEV for the access.
bool NeedsFreeze
True if the pointer expressions needs to be frozen after expansion.
bool IsWritePtr
Holds the information if this pointer is used for writing to memory.
unsigned DependencySetId
Holds the id of the set of pointers that could be dependent because of a shared underlying object.
bool IsForked
True if this entry represents one arm of a forked pointer.
PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, const SCEV *Expr, bool NeedsFreeze, bool IsForked)
unsigned AliasSetId
Holds the id of the disjoint alias set to which this pointer belongs.
const SCEV * End
Holds the largest byte address accessed by the pointer throughout all iterations of the loop,...
TrackingVH< Value > PointerValue
Holds the pointer value that we need to check.
Collection of parameters shared beetween the Loop Vectorizer and the Loop Access Analysis.
static LLVM_ABI const unsigned MaxVectorWidth
Maximum SIMD width.
static LLVM_ABI unsigned VectorizeMemoryCheckThreshold
The maximum allowed number of runtime memory checks.
static LLVM_ABI unsigned RuntimeMemoryCheckThreshold
\When performing memory disambiguation checks at runtime do not make more than this number of compari...
static LLVM_ABI bool isInterleaveForced()
True if force-vector-interleave was specified by the user.
static LLVM_ABI unsigned VectorizationInterleave
Interleave factor as overridden by the user.
static LLVM_ABI ElementCount VectorizationFactor
VF as overridden by the user.
static LLVM_ABI bool HoistRuntimeChecks