summaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/LoopAccessAnalysis.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Analysis/LoopAccessAnalysis.h')
-rw-r--r--include/llvm/Analysis/LoopAccessAnalysis.h177
1 files changed, 130 insertions, 47 deletions
diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h
index 871d35e99b748..ceee1be5e1e75 100644
--- a/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -228,7 +228,7 @@ public:
/// \brief The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
- unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
+ uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
/// \brief In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
@@ -284,7 +284,7 @@ private:
unsigned AccessIdx;
// We can access this many bytes in parallel safely.
- unsigned MaxSafeDepDistBytes;
+ uint64_t MaxSafeDepDistBytes;
/// \brief If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
@@ -321,7 +321,10 @@ private:
/// \brief Check whether the data dependence could prevent store-load
/// forwarding.
- bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
+ ///
+ /// \return false if we shouldn't vectorize at all or avoid larger
+ /// vectorization factors by limiting MaxSafeDepDistBytes.
+ bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);
};
/// \brief Holds information about the memory runtime legality checks to verify
@@ -363,10 +366,10 @@ public:
}
/// Insert a pointer and calculate the start and end SCEVs.
- /// \p We need Preds in order to compute the SCEV expression of the pointer
+ /// We need \p PSE in order to compute the SCEV expression of the pointer
/// according to the assumptions that we've made during the analysis.
/// The method might also version the pointer stride according to \p Strides,
- /// and change \p Preds.
+ /// and add new predicates to \p PSE.
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
unsigned ASId, const ValueToValueMap &Strides,
PredicatedScalarEvolution &PSE);
@@ -508,23 +511,53 @@ private:
/// PSE must be emitted in order for the results of this analysis to be valid.
class LoopAccessInfo {
public:
- LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
- const TargetLibraryInfo *TLI, AliasAnalysis *AA,
- DominatorTree *DT, LoopInfo *LI,
- const ValueToValueMap &Strides);
+ LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetLibraryInfo *TLI,
+ AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI);
+
+ // FIXME:
+ // Hack for MSVC 2013 which sems like it can't synthesize this even
+ // with default keyword:
+ // LoopAccessInfo(LoopAccessInfo &&LAI) = default;
+ LoopAccessInfo(LoopAccessInfo &&LAI)
+ : PSE(std::move(LAI.PSE)), PtrRtChecking(std::move(LAI.PtrRtChecking)),
+ DepChecker(std::move(LAI.DepChecker)), TheLoop(LAI.TheLoop),
+ NumLoads(LAI.NumLoads), NumStores(LAI.NumStores),
+ MaxSafeDepDistBytes(LAI.MaxSafeDepDistBytes), CanVecMem(LAI.CanVecMem),
+ StoreToLoopInvariantAddress(LAI.StoreToLoopInvariantAddress),
+ Report(std::move(LAI.Report)),
+ SymbolicStrides(std::move(LAI.SymbolicStrides)),
+ StrideSet(std::move(LAI.StrideSet)) {}
+ // LoopAccessInfo &operator=(LoopAccessInfo &&LAI) = default;
+ LoopAccessInfo &operator=(LoopAccessInfo &&LAI) {
+ assert(this != &LAI);
+
+ PSE = std::move(LAI.PSE);
+ PtrRtChecking = std::move(LAI.PtrRtChecking);
+ DepChecker = std::move(LAI.DepChecker);
+ TheLoop = LAI.TheLoop;
+ NumLoads = LAI.NumLoads;
+ NumStores = LAI.NumStores;
+ MaxSafeDepDistBytes = LAI.MaxSafeDepDistBytes;
+ CanVecMem = LAI.CanVecMem;
+ StoreToLoopInvariantAddress = LAI.StoreToLoopInvariantAddress;
+ Report = std::move(LAI.Report);
+ SymbolicStrides = std::move(LAI.SymbolicStrides);
+ StrideSet = std::move(LAI.StrideSet);
+ return *this;
+ }
/// Return true we can analyze the memory accesses in the loop and there are
/// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerChecking *getRuntimePointerChecking() const {
- return &PtrRtChecking;
+ return PtrRtChecking.get();
}
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks() const {
- return PtrRtChecking.getNumberOfChecks();
+ return PtrRtChecking->getNumberOfChecks();
}
/// Return true if the block BB needs to be predicated in order for the loop
@@ -535,7 +568,7 @@ public:
/// Returns true if the value V is uniform within the loop.
bool isUniform(Value *V) const;
- unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
+ uint64_t getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
unsigned getNumStores() const { return NumStores; }
unsigned getNumLoads() const { return NumLoads;}
@@ -563,23 +596,25 @@ public:
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
- const MemoryDepChecker &getDepChecker() const { return DepChecker; }
+ const MemoryDepChecker &getDepChecker() const { return *DepChecker; }
/// \brief Return the list of instructions that use \p Ptr to read or write
/// memory.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const {
- return DepChecker.getInstructionsForAccess(Ptr, isWrite);
+ return DepChecker->getInstructionsForAccess(Ptr, isWrite);
}
+ /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// the stride symbol.
+ const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; }
+
+ /// \brief Pointer has a symbolic stride.
+ bool hasStride(Value *V) const { return StrideSet.count(V); }
+
/// \brief Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
- /// \brief Used to ensure that if the analysis was run with speculating the
- /// value of symbolic strides, the client queries it with the same assumption.
- /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI.
- unsigned NumSymbolicStrides;
-
/// \brief Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
@@ -592,11 +627,12 @@ public:
/// should be re-written (and therefore simplified) according to PSE.
/// A user of LoopAccessAnalysis will need to emit the runtime checks
/// associated with this predicate.
- PredicatedScalarEvolution PSE;
+ const PredicatedScalarEvolution &getPSE() const { return *PSE; }
private:
- /// \brief Analyze the loop. Substitute symbolic strides using Strides.
- void analyzeLoop(const ValueToValueMap &Strides);
+ /// \brief Analyze the loop.
+ void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
+ const TargetLibraryInfo *TLI, DominatorTree *DT);
/// \brief Check if the structure of the loop allows it to be analyzed by this
/// pass.
@@ -604,25 +640,28 @@ private:
void emitAnalysis(LoopAccessReport &Message);
+ /// \brief Collect memory access with loop invariant strides.
+ ///
+ /// Looks for accesses like "a[i * StrideA]" where "StrideA" is loop
+ /// invariant.
+ void collectStridedAccess(Value *LoadOrStoreInst);
+
+ std::unique_ptr<PredicatedScalarEvolution> PSE;
+
/// We need to check that all of the pointers in this list are disjoint
- /// at runtime.
- RuntimePointerChecking PtrRtChecking;
+ /// at runtime. Using std::unique_ptr to make using move ctor simpler.
+ std::unique_ptr<RuntimePointerChecking> PtrRtChecking;
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
- MemoryDepChecker DepChecker;
+ std::unique_ptr<MemoryDepChecker> DepChecker;
Loop *TheLoop;
- const DataLayout &DL;
- const TargetLibraryInfo *TLI;
- AliasAnalysis *AA;
- DominatorTree *DT;
- LoopInfo *LI;
unsigned NumLoads;
unsigned NumStores;
- unsigned MaxSafeDepDistBytes;
+ uint64_t MaxSafeDepDistBytes;
/// \brief Cache the result of analyzeLoop.
bool CanVecMem;
@@ -634,15 +673,23 @@ private:
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
Optional<LoopAccessReport> Report;
+
+ /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// the stride symbol.
+ ValueToValueMap SymbolicStrides;
+
+ /// \brief Set of symbolic strides values.
+ SmallPtrSet<Value *, 8> StrideSet;
};
Value *stripIntegerCast(Value *V);
-///\brief Return the SCEV corresponding to a pointer with the symbolic stride
-/// replaced with constant one, assuming \p Preds is true.
+/// \brief Return the SCEV corresponding to a pointer with the symbolic stride
+/// replaced with constant one, assuming the SCEV predicate associated with
+/// \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
-/// to \p PtrToStride and therefore add a new predicate to \p Preds.
+/// to \p PtrToStride and therefore add further predicates to \p PSE.
///
/// If \p OrigPtr is not null, use it to look up the stride value instead of \p
/// Ptr. \p PtrToStride provides the mapping between the pointer value and its
@@ -651,13 +698,24 @@ const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr);
-/// \brief Check the stride of the pointer and ensure that it does not wrap in
-/// the address space, assuming \p Preds is true.
+/// \brief If the pointer has a constant stride return it in units of its
+/// element size. Otherwise return zero.
+///
+/// Ensure that it does not wrap in the address space, assuming the predicate
+/// associated with \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
-/// to \p PtrToStride and therefore add a new predicate to \p Preds.
-int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
- const ValueToValueMap &StridesMap);
+/// to \p PtrToStride and therefore add further predicates to \p PSE.
+/// The \p Assume parameter indicates if we are allowed to make additional
+/// run-time assumptions.
+int64_t getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
+ const ValueToValueMap &StridesMap = ValueToValueMap(),
+ bool Assume = false);
+
+/// \brief Returns true if the memory operations \p A and \p B are consecutive.
+/// This is a simple API that does not depend on the analysis pass.
+bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL,
+ ScalarEvolution &SE, bool CheckType = true);
/// \brief This analysis provides dependence information for the memory accesses
/// of a loop.
@@ -666,12 +724,12 @@ int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
/// querying the loop access info via LAA::getInfo. getInfo return a
/// LoopAccessInfo object. See this class for the specifics of what information
/// is provided.
-class LoopAccessAnalysis : public FunctionPass {
+class LoopAccessLegacyAnalysis : public FunctionPass {
public:
static char ID;
- LoopAccessAnalysis() : FunctionPass(ID) {
- initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry());
+ LoopAccessLegacyAnalysis() : FunctionPass(ID) {
+ initializeLoopAccessLegacyAnalysisPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
@@ -680,11 +738,8 @@ public:
/// \brief Query the result of the loop access information for the loop \p L.
///
- /// If the client speculates (and then issues run-time checks) for the values
- /// of symbolic strides, \p Strides provides the mapping (see
- /// replaceSymbolicStrideSCEV). If there is no cached result available run
- /// the analysis.
- const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides);
+ /// If there is no cached result available run the analysis.
+ const LoopAccessInfo &getInfo(Loop *L);
void releaseMemory() override {
// Invalidate the cache when the pass is freed.
@@ -706,6 +761,34 @@ private:
LoopInfo *LI;
};
+/// \brief This analysis provides dependence information for the memory
+/// accesses of a loop.
+///
+/// It runs the analysis for a loop on demand. This can be initiated by
+/// querying the loop access info via AM.getResult<LoopAccessAnalysis>.
+/// getResult return a LoopAccessInfo object. See this class for the
+/// specifics of what information is provided.
+class LoopAccessAnalysis
+ : public AnalysisInfoMixin<LoopAccessAnalysis> {
+ friend AnalysisInfoMixin<LoopAccessAnalysis>;
+ static char PassID;
+
+public:
+ typedef LoopAccessInfo Result;
+ Result run(Loop &, AnalysisManager<Loop> &);
+ static StringRef name() { return "LoopAccessAnalysis"; }
+};
+
+/// \brief Printer pass for the \c LoopAccessInfo results.
+class LoopAccessInfoPrinterPass
+ : public PassInfoMixin<LoopAccessInfoPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+
inline Instruction *MemoryDepChecker::Dependence::getSource(
const LoopAccessInfo &LAI) const {
return LAI.getDepChecker().getMemoryInstructions()[Source];