AssumptionCache.h 8.6 KB

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