AssumptionCache.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file contains a pass that keeps track of @llvm.assume intrinsics in
  15. // the functions of a module (allowing assumptions within any function to be
  16. // found cheaply by other parts of the optimizer).
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H
  20. #define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
  21. #include "llvm/ADT/ArrayRef.h"
  22. #include "llvm/ADT/DenseMap.h"
  23. #include "llvm/ADT/DenseMapInfo.h"
  24. #include "llvm/ADT/SmallVector.h"
  25. #include "llvm/IR/PassManager.h"
  26. #include "llvm/IR/ValueHandle.h"
  27. #include "llvm/Pass.h"
  28. #include <memory>
  29. namespace llvm {
  30. class CondGuardInst;
  31. class Function;
  32. class raw_ostream;
  33. class TargetTransformInfo;
  34. class Value;
  35. /// A cache of \@llvm.assume calls within a function.
  36. ///
  37. /// This cache provides fast lookup of assumptions within a function by caching
  38. /// them and amortizing the cost of scanning for them across all queries. Passes
  39. /// that create new assumptions are required to call registerAssumption() to
  40. /// register any new \@llvm.assume calls that they create. Deletions of
  41. /// \@llvm.assume calls do not require special handling.
  42. class AssumptionCache {
  43. public:
  44. /// Value of ResultElem::Index indicating that the argument to the call of the
  45. /// llvm.assume.
  46. enum : unsigned { ExprResultIdx = std::numeric_limits<unsigned>::max() };
  47. struct ResultElem {
  48. WeakVH Assume;
  49. /// contains either ExprResultIdx or the index of the operand bundle
  50. /// containing the knowledge.
  51. unsigned Index;
  52. operator Value *() const { return Assume; }
  53. };
  54. private:
  55. /// The function for which this cache is handling assumptions.
  56. ///
  57. /// We track this to lazily populate our assumptions.
  58. Function &F;
  59. TargetTransformInfo *TTI;
  60. /// Vector of weak value handles to calls of the \@llvm.assume
  61. /// intrinsic.
  62. SmallVector<ResultElem, 4> AssumeHandles;
  63. class AffectedValueCallbackVH final : public CallbackVH {
  64. AssumptionCache *AC;
  65. void deleted() override;
  66. void allUsesReplacedWith(Value *) override;
  67. public:
  68. using DMI = DenseMapInfo<Value *>;
  69. AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr)
  70. : CallbackVH(V), AC(AC) {}
  71. };
  72. friend AffectedValueCallbackVH;
  73. /// A map of values about which an assumption might be providing
  74. /// information to the relevant set of assumptions.
  75. using AffectedValuesMap =
  76. DenseMap<AffectedValueCallbackVH, SmallVector<ResultElem, 1>,
  77. AffectedValueCallbackVH::DMI>;
  78. AffectedValuesMap AffectedValues;
  79. /// Get the vector of assumptions which affect a value from the cache.
  80. SmallVector<ResultElem, 1> &getOrInsertAffectedValues(Value *V);
  81. /// Move affected values in the cache for OV to be affected values for NV.
  82. void transferAffectedValuesInCache(Value *OV, Value *NV);
  83. /// Flag tracking whether we have scanned the function yet.
  84. ///
  85. /// We want to be as lazy about this as possible, and so we scan the function
  86. /// at the last moment.
  87. bool Scanned = false;
  88. /// Scan the function for assumptions and add them to the cache.
  89. void scanFunction();
  90. public:
  91. /// Construct an AssumptionCache from a function by scanning all of
  92. /// its instructions.
  93. AssumptionCache(Function &F, TargetTransformInfo *TTI = nullptr)
  94. : F(F), TTI(TTI) {}
  95. /// This cache is designed to be self-updating and so it should never be
  96. /// invalidated.
  97. bool invalidate(Function &, const PreservedAnalyses &,
  98. FunctionAnalysisManager::Invalidator &) {
  99. return false;
  100. }
  101. /// Add an \@llvm.assume intrinsic to this function's cache.
  102. ///
  103. /// The call passed in must be an instruction within this function and must
  104. /// not already be in the cache.
  105. void registerAssumption(CondGuardInst *CI);
  106. /// Remove an \@llvm.assume intrinsic from this function's cache if it has
  107. /// been added to the cache earlier.
  108. void unregisterAssumption(CondGuardInst *CI);
  109. /// Update the cache of values being affected by this assumption (i.e.
  110. /// the values about which this assumption provides information).
  111. void updateAffectedValues(CondGuardInst *CI);
  112. /// Clear the cache of \@llvm.assume intrinsics for a function.
  113. ///
  114. /// It will be re-scanned the next time it is requested.
  115. void clear() {
  116. AssumeHandles.clear();
  117. AffectedValues.clear();
  118. Scanned = false;
  119. }
  120. /// Access the list of assumption handles currently tracked for this
  121. /// function.
  122. ///
  123. /// Note that these produce weak handles that may be null. The caller must
  124. /// handle that case.
  125. /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>>
  126. /// when we can write that to filter out the null values. Then caller code
  127. /// will become simpler.
  128. MutableArrayRef<ResultElem> assumptions() {
  129. if (!Scanned)
  130. scanFunction();
  131. return AssumeHandles;
  132. }
  133. /// Access the list of assumptions which affect this value.
  134. MutableArrayRef<ResultElem> assumptionsFor(const Value *V) {
  135. if (!Scanned)
  136. scanFunction();
  137. auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
  138. if (AVI == AffectedValues.end())
  139. return MutableArrayRef<ResultElem>();
  140. return AVI->second;
  141. }
  142. };
  143. /// A function analysis which provides an \c AssumptionCache.
  144. ///
  145. /// This analysis is intended for use with the new pass manager and will vend
  146. /// assumption caches for a given function.
  147. class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
  148. friend AnalysisInfoMixin<AssumptionAnalysis>;
  149. static AnalysisKey Key;
  150. public:
  151. using Result = AssumptionCache;
  152. AssumptionCache run(Function &F, FunctionAnalysisManager &);
  153. };
  154. /// Printer pass for the \c AssumptionAnalysis results.
  155. class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
  156. raw_ostream &OS;
  157. public:
  158. explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
  159. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  160. };
  161. /// An immutable pass that tracks lazily created \c AssumptionCache
  162. /// objects.
  163. ///
  164. /// This is essentially a workaround for the legacy pass manager's weaknesses
  165. /// which associates each assumption cache with Function and clears it if the
  166. /// function is deleted. The nature of the AssumptionCache is that it is not
  167. /// invalidated by any changes to the function body and so this is sufficient
  168. /// to be conservatively correct.
  169. class AssumptionCacheTracker : public ImmutablePass {
  170. /// A callback value handle applied to function objects, which we use to
  171. /// delete our cache of intrinsics for a function when it is deleted.
  172. class FunctionCallbackVH final : public CallbackVH {
  173. AssumptionCacheTracker *ACT;
  174. void deleted() override;
  175. public:
  176. using DMI = DenseMapInfo<Value *>;
  177. FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
  178. : CallbackVH(V), ACT(ACT) {}
  179. };
  180. friend FunctionCallbackVH;
  181. using FunctionCallsMap =
  182. DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
  183. FunctionCallbackVH::DMI>;
  184. FunctionCallsMap AssumptionCaches;
  185. public:
  186. /// Get the cached assumptions for a function.
  187. ///
  188. /// If no assumptions are cached, this will scan the function. Otherwise, the
  189. /// existing cache will be returned.
  190. AssumptionCache &getAssumptionCache(Function &F);
  191. /// Return the cached assumptions for a function if it has already been
  192. /// scanned. Otherwise return nullptr.
  193. AssumptionCache *lookupAssumptionCache(Function &F);
  194. AssumptionCacheTracker();
  195. ~AssumptionCacheTracker() override;
  196. void releaseMemory() override {
  197. verifyAnalysis();
  198. AssumptionCaches.shrink_and_clear();
  199. }
  200. void verifyAnalysis() const override;
  201. bool doFinalization(Module &) override {
  202. verifyAnalysis();
  203. return false;
  204. }
  205. static char ID; // Pass identification, replacement for typeid
  206. };
  207. template<> struct simplify_type<AssumptionCache::ResultElem> {
  208. using SimpleType = Value *;
  209. static SimpleType getSimplifiedValue(AssumptionCache::ResultElem &Val) {
  210. return Val;
  211. }
  212. };
  213. template<> struct simplify_type<const AssumptionCache::ResultElem> {
  214. using SimpleType = /*const*/ Value *;
  215. static SimpleType getSimplifiedValue(const AssumptionCache::ResultElem &Val) {
  216. return Val;
  217. }
  218. };
  219. } // end namespace llvm
  220. #endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H
  221. #ifdef __GNUC__
  222. #pragma GCC diagnostic pop
  223. #endif