ZoneAlgo.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. //===------ ZoneAlgo.h ------------------------------------------*- 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. // Derive information about array elements between statements ("Zones").
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef POLLY_ZONEALGO_H
  13. #define POLLY_ZONEALGO_H
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/DenseSet.h"
  16. #include "llvm/ADT/SmallPtrSet.h"
  17. #include "isl/isl-noexceptions.h"
  18. #include <memory>
  19. namespace llvm {
  20. class Value;
  21. class LoopInfo;
  22. class Loop;
  23. class PHINode;
  24. class raw_ostream;
  25. } // namespace llvm
  26. namespace polly {
  27. class Scop;
  28. class ScopStmt;
  29. class MemoryAccess;
  30. class ScopArrayInfo;
  31. /// Return only the mappings that map to known values.
  32. ///
  33. /// @param UMap { [] -> ValInst[] }
  34. ///
  35. /// @return { [] -> ValInst[] }
  36. isl::union_map filterKnownValInst(const isl::union_map &UMap);
  37. /// Base class for algorithms based on zones, like DeLICM.
  38. class ZoneAlgorithm {
  39. protected:
  40. /// The name of the pass this is used from. Used for optimization remarks.
  41. const char *PassName;
  42. /// Hold a reference to the isl_ctx to avoid it being freed before we released
  43. /// all of the isl objects.
  44. ///
  45. /// This must be declared before any other member that holds an isl object.
  46. /// This guarantees that the shared_ptr and its isl_ctx is destructed last,
  47. /// after all other members free'd the isl objects they were holding.
  48. std::shared_ptr<isl_ctx> IslCtx;
  49. /// Cached reaching definitions for each ScopStmt.
  50. ///
  51. /// Use getScalarReachingDefinition() to get its contents.
  52. llvm::DenseMap<ScopStmt *, isl::map> ScalarReachDefZone;
  53. /// The analyzed Scop.
  54. Scop *S;
  55. /// LoopInfo analysis used to determine whether values are synthesizable.
  56. llvm::LoopInfo *LI;
  57. /// Parameter space that does not need realignment.
  58. isl::space ParamSpace;
  59. /// Space the schedule maps to.
  60. isl::space ScatterSpace;
  61. /// Cached version of the schedule and domains.
  62. isl::union_map Schedule;
  63. /// Combined access relations of all MemoryKind::Array READ accesses.
  64. /// { DomainRead[] -> Element[] }
  65. isl::union_map AllReads;
  66. /// The loaded values (llvm::LoadInst) of all reads.
  67. /// { [Element[] -> DomainRead[]] -> ValInst[] }
  68. isl::union_map AllReadValInst;
  69. /// Combined access relations of all MemoryKind::Array, MAY_WRITE accesses.
  70. /// { DomainMayWrite[] -> Element[] }
  71. isl::union_map AllMayWrites;
  72. /// Combined access relations of all MemoryKind::Array, MUST_WRITE accesses.
  73. /// { DomainMustWrite[] -> Element[] }
  74. isl::union_map AllMustWrites;
  75. /// Combined access relations of all MK_Array write accesses (union of
  76. /// AllMayWrites and AllMustWrites).
  77. /// { DomainWrite[] -> Element[] }
  78. isl::union_map AllWrites;
  79. /// The value instances written to array elements of all write accesses.
  80. /// { [Element[] -> DomainWrite[]] -> ValInst[] }
  81. isl::union_map AllWriteValInst;
  82. /// All reaching definitions for MemoryKind::Array writes.
  83. /// { [Element[] -> Zone[]] -> DomainWrite[] }
  84. isl::union_map WriteReachDefZone;
  85. /// Map llvm::Values to an isl identifier.
  86. /// Used with -polly-use-llvm-names=false as an alternative method to get
  87. /// unique ids that do not depend on pointer values.
  88. llvm::DenseMap<llvm::Value *, isl::id> ValueIds;
  89. /// Set of array elements that can be reliably used for zone analysis.
  90. /// { Element[] }
  91. isl::union_set CompatibleElts;
  92. /// List of PHIs that may transitively refer to themselves.
  93. ///
  94. /// Computing them would require a polyhedral transitive closure operation,
  95. /// for which isl may only return an approximation. For correctness, we always
  96. /// require an exact result. Hence, we exclude such PHIs.
  97. llvm::SmallPtrSet<llvm::PHINode *, 4> RecursivePHIs;
  98. /// PHIs that have been computed.
  99. ///
  100. /// Computed PHIs are replaced by their incoming values using #NormalizeMap.
  101. llvm::DenseSet<llvm::PHINode *> ComputedPHIs;
  102. /// For computed PHIs, contains the ValInst they stand for.
  103. ///
  104. /// To show an example, assume the following PHINode:
  105. ///
  106. /// Stmt:
  107. /// %phi = phi double [%val1, %bb1], [%val2, %bb2]
  108. ///
  109. /// It's ValInst is:
  110. ///
  111. /// { [Stmt[i] -> phi[]] }
  112. ///
  113. /// The value %phi will be either %val1 or %val2, depending on whether in
  114. /// iteration i %bb1 or %bb2 has been executed before. In SCoPs, this can be
  115. /// determined at compile-time, and the result stored in #NormalizeMap. For
  116. /// the previous example, it could be:
  117. ///
  118. /// { [Stmt[i] -> phi[]] -> [Stmt[0] -> val1[]];
  119. /// [Stmt[i] -> phi[]] -> [Stmt[i] -> val2[]] : i > 0 }
  120. ///
  121. /// Only ValInsts in #ComputedPHIs are present in this map. Other values are
  122. /// assumed to represent themselves. This is to avoid adding lots of identity
  123. /// entries to this map.
  124. ///
  125. /// { PHIValInst[] -> IncomingValInst[] }
  126. isl::union_map NormalizeMap;
  127. /// Cache for computePerPHI(const ScopArrayInfo *)
  128. llvm::SmallDenseMap<llvm::PHINode *, isl::union_map> PerPHIMaps;
  129. /// A cache for getDefToTarget().
  130. llvm::DenseMap<std::pair<ScopStmt *, ScopStmt *>, isl::map> DefToTargetCache;
  131. /// Prepare the object before computing the zones of @p S.
  132. ///
  133. /// @param PassName Name of the pass using this analysis.
  134. /// @param S The SCoP to process.
  135. /// @param LI LoopInfo analysis used to determine synthesizable values.
  136. ZoneAlgorithm(const char *PassName, Scop *S, llvm::LoopInfo *LI);
  137. private:
  138. /// Find the array elements that violate the zone analysis assumptions.
  139. ///
  140. /// What violates our assumptions:
  141. /// - A load after a write of the same location; we assume that all reads
  142. /// occur before the writes.
  143. /// - Two writes to the same location; we cannot model the order in which
  144. /// these occur.
  145. ///
  146. /// Scalar reads implicitly always occur before other accesses therefore never
  147. /// violate the first condition. There is also at most one write to a scalar,
  148. /// satisfying the second condition.
  149. ///
  150. /// @param Stmt The statement to be analyzed.
  151. /// @param[out] IncompatibleElts Receives the elements that are not
  152. /// zone-analysis compatible.
  153. /// @param[out] AllElts receives all encountered elements.
  154. void collectIncompatibleElts(ScopStmt *Stmt, isl::union_set &IncompatibleElts,
  155. isl::union_set &AllElts);
  156. void addArrayReadAccess(MemoryAccess *MA);
  157. /// Return the ValInst write by a (must-)write access. Returns the 'unknown'
  158. /// ValInst if there is no single ValInst[] the array element written to will
  159. /// have.
  160. ///
  161. /// @return { ValInst[] }
  162. isl::union_map getWrittenValue(MemoryAccess *MA, isl::map AccRel);
  163. void addArrayWriteAccess(MemoryAccess *MA);
  164. /// For an llvm::Value defined in @p DefStmt, compute the RAW dependency for a
  165. /// use in every instance of @p UseStmt.
  166. ///
  167. /// @param UseStmt Statement a scalar is used in.
  168. /// @param DefStmt Statement a scalar is defined in.
  169. ///
  170. /// @return { DomainUse[] -> DomainDef[] }
  171. isl::map computeUseToDefFlowDependency(ScopStmt *UseStmt, ScopStmt *DefStmt);
  172. protected:
  173. isl::union_set makeEmptyUnionSet() const;
  174. isl::union_map makeEmptyUnionMap() const;
  175. /// For each 'execution' of a PHINode, get the incoming block that was
  176. /// executed before.
  177. ///
  178. /// For each PHI instance we can directly determine which was the incoming
  179. /// block, and hence derive which value the PHI has.
  180. ///
  181. /// @param SAI The ScopArrayInfo representing the PHI's storage.
  182. ///
  183. /// @return { DomainPHIRead[] -> DomainPHIWrite[] }
  184. isl::union_map computePerPHI(const polly::ScopArrayInfo *SAI);
  185. /// Find the array elements that can be used for zone analysis.
  186. void collectCompatibleElts();
  187. /// Get the schedule for @p Stmt.
  188. ///
  189. /// The domain of the result is as narrow as possible.
  190. isl::map getScatterFor(ScopStmt *Stmt) const;
  191. /// Get the schedule of @p MA's parent statement.
  192. isl::map getScatterFor(MemoryAccess *MA) const;
  193. /// Get the schedule for the statement instances of @p Domain.
  194. isl::union_map getScatterFor(isl::union_set Domain) const;
  195. /// Get the schedule for the statement instances of @p Domain.
  196. isl::map getScatterFor(isl::set Domain) const;
  197. /// Get the domain of @p Stmt.
  198. isl::set getDomainFor(ScopStmt *Stmt) const;
  199. /// Get the domain @p MA's parent statement.
  200. isl::set getDomainFor(MemoryAccess *MA) const;
  201. /// Get the access relation of @p MA.
  202. ///
  203. /// The domain of the result is as narrow as possible.
  204. isl::map getAccessRelationFor(MemoryAccess *MA) const;
  205. /// Get a domain translation map from a (scalar) definition to the statement
  206. /// where the definition is being moved to.
  207. ///
  208. /// @p TargetStmt can also be seen at an llvm::Use of an llvm::Value in
  209. /// @p DefStmt. In addition, we allow transitive uses:
  210. ///
  211. /// DefStmt -> MiddleStmt -> TargetStmt
  212. ///
  213. /// where an operand tree of instructions in DefStmt and MiddleStmt are to be
  214. /// moved to TargetStmt. To be generally correct, we also need to know all the
  215. /// intermediate statements. However, we make use of the fact that
  216. /// ForwardOpTree currently does not support a move from a loop body across
  217. /// its header such that only the first definition and the target statement
  218. /// are relevant.
  219. ///
  220. /// @param DefStmt Statement from where a definition might be moved from.
  221. /// @param TargetStmt Statement where the definition is potentially being
  222. /// moved to (should contain a use of that definition).
  223. ///
  224. /// @return { DomainDef[] -> DomainTarget[] }
  225. isl::map getDefToTarget(ScopStmt *DefStmt, ScopStmt *TargetStmt);
  226. /// Get the reaching definition of a scalar defined in @p Stmt.
  227. ///
  228. /// Note that this does not depend on the llvm::Instruction, only on the
  229. /// statement it is defined in. Therefore the same computation can be reused.
  230. ///
  231. /// @param Stmt The statement in which a scalar is defined.
  232. ///
  233. /// @return { Scatter[] -> DomainDef[] }
  234. isl::map getScalarReachingDefinition(ScopStmt *Stmt);
  235. /// Get the reaching definition of a scalar defined in @p DefDomain.
  236. ///
  237. /// @param DomainDef { DomainDef[] }
  238. /// The write statements to get the reaching definition for.
  239. ///
  240. /// @return { Scatter[] -> DomainDef[] }
  241. isl::map getScalarReachingDefinition(isl::set DomainDef);
  242. /// Create a statement-to-unknown value mapping.
  243. ///
  244. /// @param Stmt The statement whose instances are mapped to unknown.
  245. ///
  246. /// @return { Domain[] -> ValInst[] }
  247. isl::map makeUnknownForDomain(ScopStmt *Stmt) const;
  248. /// Create an isl_id that represents @p V.
  249. isl::id makeValueId(llvm::Value *V);
  250. /// Create the space for an llvm::Value that is available everywhere.
  251. isl::space makeValueSpace(llvm::Value *V);
  252. /// Create a set with the llvm::Value @p V which is available everywhere.
  253. isl::set makeValueSet(llvm::Value *V);
  254. /// Create a mapping from a statement instance to the instance of an
  255. /// llvm::Value that can be used in there.
  256. ///
  257. /// Although LLVM IR uses single static assignment, llvm::Values can have
  258. /// different contents in loops, when they get redefined in the last
  259. /// iteration. This function tries to get the statement instance of the
  260. /// previous definition, relative to a user.
  261. ///
  262. /// Example:
  263. /// for (int i = 0; i < N; i += 1) {
  264. /// DEF:
  265. /// int v = A[i];
  266. /// USE:
  267. /// use(v);
  268. /// }
  269. ///
  270. /// The value instance used by statement instance USE[i] is DEF[i]. Hence,
  271. /// makeValInst returns:
  272. ///
  273. /// { USE[i] -> [DEF[i] -> v[]] : 0 <= i < N }
  274. ///
  275. /// @param Val The value to get the instance of.
  276. /// @param UserStmt The statement that uses @p Val. Can be nullptr.
  277. /// @param Scope Loop the using instruction resides in.
  278. /// @param IsCertain Pass true if the definition of @p Val is a
  279. /// MUST_WRITE or false if the write is conditional.
  280. ///
  281. /// @return { DomainUse[] -> ValInst[] }
  282. isl::map makeValInst(llvm::Value *Val, ScopStmt *UserStmt, llvm::Loop *Scope,
  283. bool IsCertain = true);
  284. /// Create and normalize a ValInst.
  285. ///
  286. /// @see makeValInst
  287. /// @see normalizeValInst
  288. /// @see #NormalizedPHI
  289. isl::union_map makeNormalizedValInst(llvm::Value *Val, ScopStmt *UserStmt,
  290. llvm::Loop *Scope,
  291. bool IsCertain = true);
  292. /// Return whether @p MA can be used for transformations (e.g. OpTree load
  293. /// forwarding, DeLICM mapping).
  294. bool isCompatibleAccess(MemoryAccess *MA);
  295. /// Compute the different zones.
  296. void computeCommon();
  297. /// Compute the normalization map that replaces PHIs by their incoming
  298. /// values.
  299. ///
  300. /// @see #NormalizeMap
  301. void computeNormalizedPHIs();
  302. /// Print the current state of all MemoryAccesses to @p.
  303. void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const;
  304. /// Is @p MA a PHI READ access that can be normalized?
  305. ///
  306. /// @see #NormalizeMap
  307. bool isNormalizable(MemoryAccess *MA);
  308. /// @{
  309. /// Determine whether the argument does not map to any computed PHI. Those
  310. /// should have been replaced by their incoming values.
  311. ///
  312. /// @see #NormalizedPHI
  313. isl::boolean isNormalized(isl::map Map);
  314. isl::boolean isNormalized(isl::union_map Map);
  315. /// @}
  316. public:
  317. /// Return the SCoP this object is analyzing.
  318. Scop *getScop() const { return S; }
  319. /// A reaching definition zone is known to have the definition's written value
  320. /// if the definition is a MUST_WRITE.
  321. ///
  322. /// @return { [Element[] -> Zone[]] -> ValInst[] }
  323. isl::union_map computeKnownFromMustWrites() const;
  324. /// A reaching definition zone is known to be the same value as any load that
  325. /// reads from that array element in that period.
  326. ///
  327. /// @return { [Element[] -> Zone[]] -> ValInst[] }
  328. isl::union_map computeKnownFromLoad() const;
  329. /// Compute which value an array element stores at every instant.
  330. ///
  331. /// @param FromWrite Use stores as source of information.
  332. /// @param FromRead Use loads as source of information.
  333. ///
  334. /// @return { [Element[] -> Zone[]] -> ValInst[] }
  335. isl::union_map computeKnown(bool FromWrite, bool FromRead) const;
  336. };
  337. /// Create a domain-to-unknown value mapping.
  338. ///
  339. /// Value instances that do not represent a specific value are represented by an
  340. /// unnamed tuple of 0 dimensions. Its meaning depends on the context. It can
  341. /// either mean a specific but unknown value which cannot be represented by
  342. /// other means. It conflicts with itself because those two unknown ValInsts may
  343. /// have different concrete values at runtime.
  344. ///
  345. /// The other meaning is an arbitrary or wildcard value that can be chosen
  346. /// freely, like LLVM's undef. If matched with an unknown ValInst, there is no
  347. /// conflict.
  348. ///
  349. /// @param Domain { Domain[] }
  350. ///
  351. /// @return { Domain[] -> ValInst[] }
  352. isl::union_map makeUnknownForDomain(isl::union_set Domain);
  353. } // namespace polly
  354. #endif /* POLLY_ZONEALGO_H */