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