- //===--- polly/DependenceInfo.h - Polyhedral dependency analysis *- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Calculate the data dependency relations for a Scop using ISL. 
- // 
- // The integer set library (ISL) from Sven has an integrated dependency analysis 
- // to calculate data dependences. This pass takes advantage of this and 
- // calculates those dependences of a Scop. 
- // 
- // The dependences in this pass are exact in terms that for a specific read 
- // statement instance only the last write statement instance is returned. In 
- // case of may-writes, a set of possible write instances is returned. This 
- // analysis will never produce redundant dependences. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef POLLY_DEPENDENCE_INFO_H 
- #define POLLY_DEPENDENCE_INFO_H 
-   
- #include "polly/ScopPass.h" 
- #include "isl/ctx.h" 
- #include "isl/isl-noexceptions.h" 
-   
- namespace polly { 
-   
- /// The accumulated dependence information for a SCoP. 
- /// 
- /// The Dependences struct holds all dependence information we collect and 
- /// compute for one SCoP. It also offers an interface that allows users to 
- /// query only specific parts. 
- class Dependences final { 
- public: 
-   // Granularities of the current dependence analysis 
-   enum AnalysisLevel { 
-     AL_Statement = 0, 
-     // Distinguish accessed memory references in the same statement 
-     AL_Reference, 
-     // Distinguish memory access instances in the same statement 
-     AL_Access, 
-   
-     NumAnalysisLevels 
-   }; 
-   
-   /// Map type for reduction dependences. 
-   using ReductionDependencesMapTy = DenseMap<MemoryAccess *, isl_map *>; 
-   
-   /// Map type to associate statements with schedules. 
-   using StatementToIslMapTy = DenseMap<ScopStmt *, isl::map>; 
-   
-   /// The type of the dependences. 
-   /// 
-   /// Reduction dependences are separated from RAW/WAW/WAR dependences because 
-   /// we can ignore them during the scheduling. That's because the order 
-   /// in which the reduction statements are executed does not matter. However, 
-   /// if they are executed in parallel we need to take additional measures 
-   /// (e.g, privatization) to ensure a correct result. The (reverse) transitive 
-   /// closure of the reduction dependences are used to check for parallel 
-   /// executed reduction statements during code generation. These dependences 
-   /// connect all instances of a reduction with each other, they are therefore 
-   /// cyclic and possibly "reversed". 
-   enum Type { 
-     // Write after read 
-     TYPE_WAR = 1 << 0, 
-   
-     // Read after write 
-     TYPE_RAW = 1 << 1, 
-   
-     // Write after write 
-     TYPE_WAW = 1 << 2, 
-   
-     // Reduction dependences 
-     TYPE_RED = 1 << 3, 
-   
-     // Transitive closure of the reduction dependences (& the reverse) 
-     TYPE_TC_RED = 1 << 4, 
-   }; 
-   
-   const std::shared_ptr<isl_ctx> &getSharedIslCtx() const { return IslCtx; } 
-   
-   /// Get the dependences of type @p Kinds. 
-   /// 
-   /// @param Kinds This integer defines the different kinds of dependences 
-   ///              that will be returned. To return more than one kind, the 
-   ///              different kinds are 'ored' together. 
-   isl::union_map getDependences(int Kinds) const; 
-   
-   /// Report if valid dependences are available. 
-   bool hasValidDependences() const; 
-   
-   /// Return the reduction dependences caused by @p MA. 
-   /// 
-   /// @return The reduction dependences caused by @p MA or nullptr if none. 
-   __isl_give isl_map *getReductionDependences(MemoryAccess *MA) const; 
-   
-   /// Return all reduction dependences. 
-   const ReductionDependencesMapTy &getReductionDependences() const { 
-     return ReductionDependences; 
-   } 
-   
-   /// Check if a partial schedule is parallel wrt to @p Deps. 
-   /// 
-   /// @param Schedule       The subset of the schedule space that we want to 
-   ///                       check. 
-   /// @param Deps           The dependences @p Schedule needs to respect. 
-   /// @param MinDistancePtr If not nullptr, the minimal dependence distance will 
-   ///                       be returned at the address of that pointer 
-   /// 
-   /// @return Returns true, if executing parallel the outermost dimension of 
-   ///         @p Schedule is valid according to the dependences @p Deps. 
-   bool isParallel(__isl_keep isl_union_map *Schedule, 
-                   __isl_take isl_union_map *Deps, 
-                   __isl_give isl_pw_aff **MinDistancePtr = nullptr) const; 
-   
-   /// Check if a new schedule is valid. 
-   /// 
-   /// @param S             The current SCoP. 
-   /// @param NewSchedules  The new schedules 
-   /// 
-   /// @return True if the new schedule is valid, false if it reverses 
-   ///         dependences. 
-   bool isValidSchedule(Scop &S, const StatementToIslMapTy &NewSchedules) const; 
-   
-   /// Return true of the schedule @p NewSched is a schedule for @S that does not 
-   /// violate any dependences. 
-   bool isValidSchedule(Scop &S, isl::schedule NewSched) const; 
-   
-   /// Print the stored dependence information. 
-   void print(llvm::raw_ostream &OS) const; 
-   
-   /// Dump the dependence information stored to the dbgs stream. 
-   void dump() const; 
-   
-   /// Return the granularity of this dependence analysis. 
-   AnalysisLevel getDependenceLevel() { return Level; } 
-   
-   /// Allow the DependenceInfo access to private members and methods. 
-   /// 
-   /// To restrict access to the internal state, only the DependenceInfo class 
-   /// is able to call or modify a Dependences struct. 
-   friend struct DependenceAnalysis; 
-   friend struct DependenceInfoPrinterPass; 
-   friend class DependenceInfo; 
-   friend class DependenceInfoWrapperPass; 
-   
-   /// Destructor that will free internal objects. 
-   ~Dependences() { releaseMemory(); } 
-   
- private: 
-   /// Create an empty dependences struct. 
-   explicit Dependences(const std::shared_ptr<isl_ctx> &IslCtx, 
-                        AnalysisLevel Level) 
-       : RAW(nullptr), WAR(nullptr), WAW(nullptr), RED(nullptr), TC_RED(nullptr), 
-         IslCtx(IslCtx), Level(Level) {} 
-   
-   /// Calculate and add at the privatization dependences. 
-   void addPrivatizationDependences(); 
-   
-   /// Calculate the dependences for a certain SCoP @p S. 
-   void calculateDependences(Scop &S); 
-   
-   /// Set the reduction dependences for @p MA to @p Deps. 
-   void setReductionDependences(MemoryAccess *MA, __isl_take isl_map *Deps); 
-   
-   /// Free the objects associated with this Dependences struct. 
-   /// 
-   /// The Dependences struct will again be "empty" afterwards. 
-   void releaseMemory(); 
-   
-   /// The different basic kinds of dependences we calculate. 
-   isl_union_map *RAW; 
-   isl_union_map *WAR; 
-   isl_union_map *WAW; 
-   
-   /// The special reduction dependences. 
-   isl_union_map *RED; 
-   
-   /// The (reverse) transitive closure of reduction dependences. 
-   isl_union_map *TC_RED; 
-   
-   /// Mapping from memory accesses to their reduction dependences. 
-   ReductionDependencesMapTy ReductionDependences; 
-   
-   /// Isl context from the SCoP. 
-   std::shared_ptr<isl_ctx> IslCtx; 
-   
-   /// Granularity of this dependence analysis. 
-   const AnalysisLevel Level; 
- }; 
-   
- struct DependenceAnalysis final : public AnalysisInfoMixin<DependenceAnalysis> { 
-   static AnalysisKey Key; 
-   struct Result { 
-     Scop &S; 
-     std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels]; 
-   
-     /// Return the dependence information for the current SCoP. 
-     /// 
-     /// @param Level The granularity of dependence analysis result. 
-     /// 
-     /// @return The dependence analysis result 
-     /// 
-     const Dependences &getDependences(Dependences::AnalysisLevel Level); 
-   
-     /// Recompute dependences from schedule and memory accesses. 
-     const Dependences &recomputeDependences(Dependences::AnalysisLevel Level); 
-   
-     /// Invalidate the dependence information and recompute it when needed 
-     /// again. 
-     /// May be required when the underlaying Scop was changed in a way that 
-     /// would add new dependencies (e.g. between new statement instances 
-     /// insierted into the SCoP) or intentionally breaks existing ones. It is 
-     /// not required when updating the schedule that conforms the existing 
-     /// dependencies. 
-     void abandonDependences(); 
-   }; 
-   Result run(Scop &S, ScopAnalysisManager &SAM, 
-              ScopStandardAnalysisResults &SAR); 
- }; 
-   
- struct DependenceInfoPrinterPass final 
-     : PassInfoMixin<DependenceInfoPrinterPass> { 
-   DependenceInfoPrinterPass(raw_ostream &OS) : OS(OS) {} 
-   
-   PreservedAnalyses run(Scop &S, ScopAnalysisManager &, 
-                         ScopStandardAnalysisResults &, SPMUpdater &); 
-   
-   raw_ostream &OS; 
- }; 
-   
- class DependenceInfo final : public ScopPass { 
- public: 
-   static char ID; 
-   
-   /// Construct a new DependenceInfo pass. 
-   DependenceInfo() : ScopPass(ID) {} 
-   
-   /// Return the dependence information for the current SCoP. 
-   /// 
-   /// @param Level The granularity of dependence analysis result. 
-   /// 
-   /// @return The dependence analysis result 
-   /// 
-   const Dependences &getDependences(Dependences::AnalysisLevel Level); 
-   
-   /// Recompute dependences from schedule and memory accesses. 
-   const Dependences &recomputeDependences(Dependences::AnalysisLevel Level); 
-   
-   /// Invalidate the dependence information and recompute it when needed again. 
-   /// May be required when the underlaying Scop was changed in a way that would 
-   /// add new dependencies (e.g. between new statement instances insierted into 
-   /// the SCoP) or intentionally breaks existing ones. It is not required when 
-   /// updating the schedule that conforms the existing dependencies. 
-   void abandonDependences(); 
-   
-   /// Compute the dependence information for the SCoP @p S. 
-   bool runOnScop(Scop &S) override; 
-   
-   /// Print the dependences for the given SCoP to @p OS. 
-   void printScop(raw_ostream &OS, Scop &) const override; 
-   
-   /// Release the internal memory. 
-   void releaseMemory() override { 
-     for (auto &d : D) 
-       d.reset(); 
-   } 
-   
-   /// Register all analyses and transformation required. 
-   void getAnalysisUsage(AnalysisUsage &AU) const override; 
-   
- private: 
-   Scop *S; 
-   
-   /// Dependences struct for the current SCoP. 
-   std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels]; 
- }; 
-   
- llvm::Pass *createDependenceInfoPass(); 
- llvm::Pass *createDependenceInfoPrinterLegacyPass(llvm::raw_ostream &OS); 
-   
- /// Construct a new DependenceInfoWrapper pass. 
- class DependenceInfoWrapperPass final : public FunctionPass { 
- public: 
-   static char ID; 
-   
-   /// Construct a new DependenceInfoWrapper pass. 
-   DependenceInfoWrapperPass() : FunctionPass(ID) {} 
-   
-   /// Return the dependence information for the given SCoP. 
-   /// 
-   /// @param S     SCoP object. 
-   /// @param Level The granularity of dependence analysis result. 
-   /// 
-   /// @return The dependence analysis result 
-   /// 
-   const Dependences &getDependences(Scop *S, Dependences::AnalysisLevel Level); 
-   
-   /// Recompute dependences from schedule and memory accesses. 
-   const Dependences &recomputeDependences(Scop *S, 
-                                           Dependences::AnalysisLevel Level); 
-   
-   /// Compute the dependence information on-the-fly for the function. 
-   bool runOnFunction(Function &F) override; 
-   
-   /// Print the dependences for the current function to @p OS. 
-   void print(raw_ostream &OS, const Module *M = nullptr) const override; 
-   
-   /// Release the internal memory. 
-   void releaseMemory() override { ScopToDepsMap.clear(); } 
-   
-   /// Register all analyses and transformation required. 
-   void getAnalysisUsage(AnalysisUsage &AU) const override; 
-   
- private: 
-   using ScopToDepsMapTy = DenseMap<Scop *, std::unique_ptr<Dependences>>; 
-   
-   /// Scop to Dependence map for the current function. 
-   ScopToDepsMapTy ScopToDepsMap; 
- }; 
-   
- llvm::Pass *createDependenceInfoWrapperPassPass(); 
- llvm::Pass * 
- createDependenceInfoPrinterLegacyFunctionPass(llvm::raw_ostream &OS); 
-   
- } // namespace polly 
-   
- namespace llvm { 
- void initializeDependenceInfoPass(llvm::PassRegistry &); 
- void initializeDependenceInfoPrinterLegacyPassPass(llvm::PassRegistry &); 
- void initializeDependenceInfoWrapperPassPass(llvm::PassRegistry &); 
- void initializeDependenceInfoPrinterLegacyFunctionPassPass( 
-     llvm::PassRegistry &); 
- } // namespace llvm 
-   
- #endif 
-