DependenceInfo.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. //===--- polly/DependenceInfo.h - Polyhedral dependency analysis *- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Calculate the data dependency relations for a Scop using ISL.
  10. //
  11. // The integer set library (ISL) from Sven has an integrated dependency analysis
  12. // to calculate data dependences. This pass takes advantage of this and
  13. // calculates those dependences of a Scop.
  14. //
  15. // The dependences in this pass are exact in terms that for a specific read
  16. // statement instance only the last write statement instance is returned. In
  17. // case of may-writes, a set of possible write instances is returned. This
  18. // analysis will never produce redundant dependences.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef POLLY_DEPENDENCE_INFO_H
  22. #define POLLY_DEPENDENCE_INFO_H
  23. #include "polly/ScopPass.h"
  24. #include "isl/ctx.h"
  25. #include "isl/isl-noexceptions.h"
  26. namespace polly {
  27. /// The accumulated dependence information for a SCoP.
  28. ///
  29. /// The Dependences struct holds all dependence information we collect and
  30. /// compute for one SCoP. It also offers an interface that allows users to
  31. /// query only specific parts.
  32. struct Dependences {
  33. // Granularities of the current dependence analysis
  34. enum AnalysisLevel {
  35. AL_Statement = 0,
  36. // Distinguish accessed memory references in the same statement
  37. AL_Reference,
  38. // Distinguish memory access instances in the same statement
  39. AL_Access,
  40. NumAnalysisLevels
  41. };
  42. /// Map type for reduction dependences.
  43. using ReductionDependencesMapTy = DenseMap<MemoryAccess *, isl_map *>;
  44. /// Map type to associate statements with schedules.
  45. using StatementToIslMapTy = DenseMap<ScopStmt *, isl::map>;
  46. /// The type of the dependences.
  47. ///
  48. /// Reduction dependences are separated from RAW/WAW/WAR dependences because
  49. /// we can ignore them during the scheduling. That's because the order
  50. /// in which the reduction statements are executed does not matter. However,
  51. /// if they are executed in parallel we need to take additional measures
  52. /// (e.g, privatization) to ensure a correct result. The (reverse) transitive
  53. /// closure of the reduction dependences are used to check for parallel
  54. /// executed reduction statements during code generation. These dependences
  55. /// connect all instances of a reduction with each other, they are therefore
  56. /// cyclic and possibly "reversed".
  57. enum Type {
  58. // Write after read
  59. TYPE_WAR = 1 << 0,
  60. // Read after write
  61. TYPE_RAW = 1 << 1,
  62. // Write after write
  63. TYPE_WAW = 1 << 2,
  64. // Reduction dependences
  65. TYPE_RED = 1 << 3,
  66. // Transitive closure of the reduction dependences (& the reverse)
  67. TYPE_TC_RED = 1 << 4,
  68. };
  69. const std::shared_ptr<isl_ctx> &getSharedIslCtx() const { return IslCtx; }
  70. /// Get the dependences of type @p Kinds.
  71. ///
  72. /// @param Kinds This integer defines the different kinds of dependences
  73. /// that will be returned. To return more than one kind, the
  74. /// different kinds are 'ored' together.
  75. isl::union_map getDependences(int Kinds) const;
  76. /// Report if valid dependences are available.
  77. bool hasValidDependences() const;
  78. /// Return the reduction dependences caused by @p MA.
  79. ///
  80. /// @return The reduction dependences caused by @p MA or nullptr if none.
  81. __isl_give isl_map *getReductionDependences(MemoryAccess *MA) const;
  82. /// Return all reduction dependences.
  83. const ReductionDependencesMapTy &getReductionDependences() const {
  84. return ReductionDependences;
  85. }
  86. /// Check if a partial schedule is parallel wrt to @p Deps.
  87. ///
  88. /// @param Schedule The subset of the schedule space that we want to
  89. /// check.
  90. /// @param Deps The dependences @p Schedule needs to respect.
  91. /// @param MinDistancePtr If not nullptr, the minimal dependence distance will
  92. /// be returned at the address of that pointer
  93. ///
  94. /// @return Returns true, if executing parallel the outermost dimension of
  95. /// @p Schedule is valid according to the dependences @p Deps.
  96. bool isParallel(__isl_keep isl_union_map *Schedule,
  97. __isl_take isl_union_map *Deps,
  98. __isl_give isl_pw_aff **MinDistancePtr = nullptr) const;
  99. /// Check if a new schedule is valid.
  100. ///
  101. /// @param S The current SCoP.
  102. /// @param NewSchedules The new schedules
  103. ///
  104. /// @return True if the new schedule is valid, false if it reverses
  105. /// dependences.
  106. bool isValidSchedule(Scop &S, const StatementToIslMapTy &NewSchedules) const;
  107. /// Print the stored dependence information.
  108. void print(llvm::raw_ostream &OS) const;
  109. /// Dump the dependence information stored to the dbgs stream.
  110. void dump() const;
  111. /// Return the granularity of this dependence analysis.
  112. AnalysisLevel getDependenceLevel() { return Level; }
  113. /// Allow the DependenceInfo access to private members and methods.
  114. ///
  115. /// To restrict access to the internal state, only the DependenceInfo class
  116. /// is able to call or modify a Dependences struct.
  117. friend struct DependenceAnalysis;
  118. friend struct DependenceInfoPrinterPass;
  119. friend class DependenceInfo;
  120. friend class DependenceInfoWrapperPass;
  121. /// Destructor that will free internal objects.
  122. ~Dependences() { releaseMemory(); }
  123. private:
  124. /// Create an empty dependences struct.
  125. explicit Dependences(const std::shared_ptr<isl_ctx> &IslCtx,
  126. AnalysisLevel Level)
  127. : RAW(nullptr), WAR(nullptr), WAW(nullptr), RED(nullptr), TC_RED(nullptr),
  128. IslCtx(IslCtx), Level(Level) {}
  129. /// Calculate and add at the privatization dependences.
  130. void addPrivatizationDependences();
  131. /// Calculate the dependences for a certain SCoP @p S.
  132. void calculateDependences(Scop &S);
  133. /// Set the reduction dependences for @p MA to @p Deps.
  134. void setReductionDependences(MemoryAccess *MA, __isl_take isl_map *Deps);
  135. /// Free the objects associated with this Dependences struct.
  136. ///
  137. /// The Dependences struct will again be "empty" afterwards.
  138. void releaseMemory();
  139. /// The different basic kinds of dependences we calculate.
  140. isl_union_map *RAW;
  141. isl_union_map *WAR;
  142. isl_union_map *WAW;
  143. /// The special reduction dependences.
  144. isl_union_map *RED;
  145. /// The (reverse) transitive closure of reduction dependences.
  146. isl_union_map *TC_RED;
  147. /// Mapping from memory accesses to their reduction dependences.
  148. ReductionDependencesMapTy ReductionDependences;
  149. /// Isl context from the SCoP.
  150. std::shared_ptr<isl_ctx> IslCtx;
  151. /// Granularity of this dependence analysis.
  152. const AnalysisLevel Level;
  153. };
  154. struct DependenceAnalysis : public AnalysisInfoMixin<DependenceAnalysis> {
  155. static AnalysisKey Key;
  156. struct Result {
  157. Scop &S;
  158. std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels];
  159. /// Return the dependence information for the current SCoP.
  160. ///
  161. /// @param Level The granularity of dependence analysis result.
  162. ///
  163. /// @return The dependence analysis result
  164. ///
  165. const Dependences &getDependences(Dependences::AnalysisLevel Level);
  166. /// Recompute dependences from schedule and memory accesses.
  167. const Dependences &recomputeDependences(Dependences::AnalysisLevel Level);
  168. };
  169. Result run(Scop &S, ScopAnalysisManager &SAM,
  170. ScopStandardAnalysisResults &SAR);
  171. };
  172. struct DependenceInfoPrinterPass
  173. : public PassInfoMixin<DependenceInfoPrinterPass> {
  174. DependenceInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
  175. PreservedAnalyses run(Scop &S, ScopAnalysisManager &,
  176. ScopStandardAnalysisResults &, SPMUpdater &);
  177. raw_ostream &OS;
  178. };
  179. class DependenceInfo : public ScopPass {
  180. public:
  181. static char ID;
  182. /// Construct a new DependenceInfo pass.
  183. DependenceInfo() : ScopPass(ID) {}
  184. /// Return the dependence information for the current SCoP.
  185. ///
  186. /// @param Level The granularity of dependence analysis result.
  187. ///
  188. /// @return The dependence analysis result
  189. ///
  190. const Dependences &getDependences(Dependences::AnalysisLevel Level);
  191. /// Recompute dependences from schedule and memory accesses.
  192. const Dependences &recomputeDependences(Dependences::AnalysisLevel Level);
  193. /// Compute the dependence information for the SCoP @p S.
  194. bool runOnScop(Scop &S) override;
  195. /// Print the dependences for the given SCoP to @p OS.
  196. void printScop(raw_ostream &OS, Scop &) const override;
  197. /// Release the internal memory.
  198. void releaseMemory() override {
  199. for (auto &d : D)
  200. d.reset();
  201. }
  202. /// Register all analyses and transformation required.
  203. void getAnalysisUsage(AnalysisUsage &AU) const override;
  204. private:
  205. Scop *S;
  206. /// Dependences struct for the current SCoP.
  207. std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels];
  208. };
  209. /// Construct a new DependenceInfoWrapper pass.
  210. class DependenceInfoWrapperPass : public FunctionPass {
  211. public:
  212. static char ID;
  213. /// Construct a new DependenceInfoWrapper pass.
  214. DependenceInfoWrapperPass() : FunctionPass(ID) {}
  215. /// Return the dependence information for the given SCoP.
  216. ///
  217. /// @param S SCoP object.
  218. /// @param Level The granularity of dependence analysis result.
  219. ///
  220. /// @return The dependence analysis result
  221. ///
  222. const Dependences &getDependences(Scop *S, Dependences::AnalysisLevel Level);
  223. /// Recompute dependences from schedule and memory accesses.
  224. const Dependences &recomputeDependences(Scop *S,
  225. Dependences::AnalysisLevel Level);
  226. /// Compute the dependence information on-the-fly for the function.
  227. bool runOnFunction(Function &F) override;
  228. /// Print the dependences for the current function to @p OS.
  229. void print(raw_ostream &OS, const Module *M = nullptr) const override;
  230. /// Release the internal memory.
  231. void releaseMemory() override { ScopToDepsMap.clear(); }
  232. /// Register all analyses and transformation required.
  233. void getAnalysisUsage(AnalysisUsage &AU) const override;
  234. private:
  235. using ScopToDepsMapTy = DenseMap<Scop *, std::unique_ptr<Dependences>>;
  236. /// Scop to Dependence map for the current function.
  237. ScopToDepsMapTy ScopToDepsMap;
  238. };
  239. } // namespace polly
  240. namespace llvm {
  241. void initializeDependenceInfoPass(llvm::PassRegistry &);
  242. void initializeDependenceInfoWrapperPassPass(llvm::PassRegistry &);
  243. } // namespace llvm
  244. #endif