//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the interface for the loop memory dependence framework that // was originally developed for the Loop Vectorizer. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H #define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" namespace llvm { class Value; class DataLayout; class AliasAnalysis; class ScalarEvolution; class Loop; class SCEV; /// Optimization analysis message produced during vectorization. Messages inform /// the user why vectorization did not occur. class VectorizationReport { std::string Message; Instruction *Instr; public: VectorizationReport(Instruction *I = nullptr) : Message("loop not vectorized: "), Instr(I) {} template VectorizationReport &operator<<(const A &Value) { raw_string_ostream Out(Message); Out << Value; return *this; } Instruction *getInstr() { return Instr; } std::string &str() { return Message; } operator Twine() { return Message; } /// \brief Emit an analysis note with the debug location from the instruction /// in \p Message if available. Otherwise use the location of \p TheLoop. static void emitAnalysis(VectorizationReport &Message, const Function *TheFunction, const Loop *TheLoop); }; /// \brief Collection of parameters shared beetween the Loop Vectorizer and the /// Loop Access Analysis. struct VectorizerParams { /// \brief Maximum SIMD width. static const unsigned MaxVectorWidth; /// \brief VF as overridden by the user. static unsigned VectorizationFactor; /// \brief Interleave factor as overridden by the user. static unsigned VectorizationInterleave; /// \brief True if force-vector-interleave was specified by the user. static bool isInterleaveForced(); /// \\brief When performing memory disambiguation checks at runtime do not /// make more than this number of comparisons. static const unsigned RuntimeMemoryCheckThreshold; }; /// \brief Drive the analysis of memory accesses in the loop /// /// This class is responsible for analyzing the memory accesses of a loop. It /// collects the accesses and then its main helper the AccessAnalysis class /// finds and categorizes the dependences in buildDependenceSets. /// /// For memory dependences that can be analyzed at compile time, it determines /// whether the dependence is part of cycle inhibiting vectorization. This work /// is delegated to the MemoryDepChecker class. /// /// For memory dependences that cannot be determined at compile time, it /// generates run-time checks to prove independence. This is done by /// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the /// RuntimePointerCheck class. class LoopAccessInfo { public: /// This struct holds information about the memory runtime legality check that /// a group of pointers do not overlap. struct RuntimePointerCheck { RuntimePointerCheck() : Need(false) {} /// Reset the state of the pointer runtime information. void reset() { Need = false; Pointers.clear(); Starts.clear(); Ends.clear(); IsWritePtr.clear(); DependencySetId.clear(); AliasSetId.clear(); } /// Insert a pointer and calculate the start and end SCEVs. void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, unsigned ASId, ValueToValueMap &Strides); /// \brief Decide whether we need to issue a run-time check for pointer at /// index \p I and \p J to prove their independence. bool needsChecking(unsigned I, unsigned J) const; /// This flag indicates if we need to add the runtime check. bool Need; /// Holds the pointers that we need to check. SmallVector, 2> Pointers; /// Holds the pointer value at the beginning of the loop. SmallVector Starts; /// Holds the pointer value at the end of the loop. SmallVector Ends; /// Holds the information if this pointer is used for writing to memory. SmallVector IsWritePtr; /// Holds the id of the set of pointers that could be dependent because of a /// shared underlying object. SmallVector DependencySetId; /// Holds the id of the disjoint alias set to which this pointer belongs. SmallVector AliasSetId; }; LoopAccessInfo(Function *F, Loop *L, ScalarEvolution *SE, const DataLayout *DL, const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT) : TheFunction(F), TheLoop(L), SE(SE), DL(DL), TLI(TLI), AA(AA), DT(DT), NumLoads(0), NumStores(0), MaxSafeDepDistBytes(-1U) {} /// Return true we can analyze the memory accesses in the loop and there are /// no memory dependence cycles. Replaces symbolic strides using Strides. bool canVectorizeMemory(ValueToValueMap &Strides); RuntimePointerCheck *getRuntimePointerCheck() { return &PtrRtCheck; } /// Return true if the block BB needs to be predicated in order for the loop /// to be vectorized. static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, DominatorTree *DT); /// Returns true if the value V is uniform within the loop. bool isUniform(Value *V); unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } unsigned getNumStores() const { return NumStores; } unsigned getNumLoads() const { return NumLoads;} /// \brief Add code that checks at runtime if the accessed arrays overlap. /// /// Returns a pair of instructions where the first element is the first /// instruction generated in possibly a sequence of instructions and the /// second value is the final comparator value or NULL if no check is needed. std::pair addRuntimeCheck(Instruction *Loc); private: void emitAnalysis(VectorizationReport &Message); /// We need to check that all of the pointers in this list are disjoint /// at runtime. RuntimePointerCheck PtrRtCheck; Function *TheFunction; Loop *TheLoop; ScalarEvolution *SE; const DataLayout *DL; const TargetLibraryInfo *TLI; AliasAnalysis *AA; DominatorTree *DT; unsigned NumLoads; unsigned NumStores; unsigned MaxSafeDepDistBytes; }; Value *stripIntegerCast(Value *V); ///\brief Return the SCEV corresponding to a pointer with the symbolic stride ///replaced with constant one. /// /// 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 /// stride as collected by LoopVectorizationLegality::collectStridedAccess. const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE, ValueToValueMap &PtrToStride, Value *Ptr, Value *OrigPtr = nullptr); } // End llvm namespace #endif