175075efeSEugene Zelenko //===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===//
2f5123fecSDaniel Jasper //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f5123fecSDaniel Jasper //
7f5123fecSDaniel Jasper //===----------------------------------------------------------------------===//
8f5123fecSDaniel Jasper //
9f5123fecSDaniel Jasper // This file contains a pass that keeps track of @llvm.assume intrinsics in
10f5123fecSDaniel Jasper // the functions of a module (allowing assumptions within any function to be
11f5123fecSDaniel Jasper // found cheaply by other parts of the optimizer).
12f5123fecSDaniel Jasper //
13f5123fecSDaniel Jasper //===----------------------------------------------------------------------===//
14f5123fecSDaniel Jasper 
15f5123fecSDaniel Jasper #ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H
16f5123fecSDaniel Jasper #define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
17f5123fecSDaniel Jasper 
18f5123fecSDaniel Jasper #include "llvm/ADT/ArrayRef.h"
19f5123fecSDaniel Jasper #include "llvm/ADT/DenseMap.h"
2075075efeSEugene Zelenko #include "llvm/ADT/DenseMapInfo.h"
2175075efeSEugene Zelenko #include "llvm/ADT/SmallVector.h"
22f5123fecSDaniel Jasper #include "llvm/IR/PassManager.h"
236bda14b3SChandler Carruth #include "llvm/IR/ValueHandle.h"
24f5123fecSDaniel Jasper #include "llvm/Pass.h"
25f5123fecSDaniel Jasper #include <memory>
26f5123fecSDaniel Jasper 
27f5123fecSDaniel Jasper namespace llvm {
28f5123fecSDaniel Jasper 
29a6d2a8d6SPhilip Reames class AssumeInst;
3075075efeSEugene Zelenko class Function;
3175075efeSEugene Zelenko class raw_ostream;
32*bf225939SMichael Liao class TargetTransformInfo;
3375075efeSEugene Zelenko class Value;
3475075efeSEugene Zelenko 
355f8f34e4SAdrian Prantl /// A cache of \@llvm.assume calls within a function.
36f5123fecSDaniel Jasper ///
37f5123fecSDaniel Jasper /// This cache provides fast lookup of assumptions within a function by caching
3896e36a67SPeter Collingbourne /// them and amortizing the cost of scanning for them across all queries. Passes
3996e36a67SPeter Collingbourne /// that create new assumptions are required to call registerAssumption() to
403e790840SMatt Davis /// register any new \@llvm.assume calls that they create. Deletions of
413e790840SMatt Davis /// \@llvm.assume calls do not require special handling.
42f5123fecSDaniel Jasper class AssumptionCache {
43813f438bSTyker public:
44813f438bSTyker   /// Value of ResultElem::Index indicating that the argument to the call of the
45813f438bSTyker   /// llvm.assume.
46813f438bSTyker   enum : unsigned { ExprResultIdx = std::numeric_limits<unsigned>::max() };
47813f438bSTyker 
48813f438bSTyker   struct ResultElem {
49378f4e5eSJohannes Doerfert     WeakVH Assume;
50813f438bSTyker 
51813f438bSTyker     /// contains either ExprResultIdx or the index of the operand bundle
52813f438bSTyker     /// containing the knowledge.
53813f438bSTyker     unsigned Index;
54813f438bSTyker     operator Value *() const { return Assume; }
55813f438bSTyker   };
56813f438bSTyker 
57813f438bSTyker private:
585f8f34e4SAdrian Prantl   /// The function for which this cache is handling assumptions.
59f5123fecSDaniel Jasper   ///
60f5123fecSDaniel Jasper   /// We track this to lazily populate our assumptions.
61f5123fecSDaniel Jasper   Function &F;
62f5123fecSDaniel Jasper 
63*bf225939SMichael Liao   TargetTransformInfo *TTI;
64*bf225939SMichael Liao 
65606aa622SMichael Kruse   /// Vector of weak value handles to calls of the \@llvm.assume
66606aa622SMichael Kruse   /// intrinsic.
67606aa622SMichael Kruse   SmallVector<ResultElem, 4> AssumeHandles;
68f5123fecSDaniel Jasper 
698a9a783fSHal Finkel   class AffectedValueCallbackVH final : public CallbackVH {
708a9a783fSHal Finkel     AssumptionCache *AC;
7175075efeSEugene Zelenko 
728a9a783fSHal Finkel     void deleted() override;
738a9a783fSHal Finkel     void allUsesReplacedWith(Value *) override;
748a9a783fSHal Finkel 
758a9a783fSHal Finkel   public:
768a9a783fSHal Finkel     using DMI = DenseMapInfo<Value *>;
778a9a783fSHal Finkel 
788a9a783fSHal Finkel     AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr)
CallbackVH(V)798a9a783fSHal Finkel         : CallbackVH(V), AC(AC) {}
808a9a783fSHal Finkel   };
818a9a783fSHal Finkel 
828a9a783fSHal Finkel   friend AffectedValueCallbackVH;
838a9a783fSHal Finkel 
845f8f34e4SAdrian Prantl   /// A map of values about which an assumption might be providing
858a9a783fSHal Finkel   /// information to the relevant set of assumptions.
868a9a783fSHal Finkel   using AffectedValuesMap =
87813f438bSTyker       DenseMap<AffectedValueCallbackVH, SmallVector<ResultElem, 1>,
888a9a783fSHal Finkel                AffectedValueCallbackVH::DMI>;
898a9a783fSHal Finkel   AffectedValuesMap AffectedValues;
908a9a783fSHal Finkel 
918a9a783fSHal Finkel   /// Get the vector of assumptions which affect a value from the cache.
92813f438bSTyker   SmallVector<ResultElem, 1> &getOrInsertAffectedValues(Value *V);
93c29d5f16SHal Finkel 
9422970d66STim Northover   /// Move affected values in the cache for OV to be affected values for NV.
9522970d66STim Northover   void transferAffectedValuesInCache(Value *OV, Value *NV);
968a9a783fSHal Finkel 
975f8f34e4SAdrian Prantl   /// Flag tracking whether we have scanned the function yet.
98f5123fecSDaniel Jasper   ///
99f5123fecSDaniel Jasper   /// We want to be as lazy about this as possible, and so we scan the function
100f5123fecSDaniel Jasper   /// at the last moment.
10175075efeSEugene Zelenko   bool Scanned = false;
102f5123fecSDaniel Jasper 
1035f8f34e4SAdrian Prantl   /// Scan the function for assumptions and add them to the cache.
104f5123fecSDaniel Jasper   void scanFunction();
105f5123fecSDaniel Jasper 
106f5123fecSDaniel Jasper public:
1075f8f34e4SAdrian Prantl   /// Construct an AssumptionCache from a function by scanning all of
108f5123fecSDaniel Jasper   /// its instructions.
109*bf225939SMichael Liao   AssumptionCache(Function &F, TargetTransformInfo *TTI = nullptr)
F(F)110*bf225939SMichael Liao       : F(F), TTI(TTI) {}
111f5123fecSDaniel Jasper 
1122f19a324SChandler Carruth   /// This cache is designed to be self-updating and so it should never be
1132f19a324SChandler Carruth   /// invalidated.
invalidate(Function &,const PreservedAnalyses &,FunctionAnalysisManager::Invalidator &)1142f19a324SChandler Carruth   bool invalidate(Function &, const PreservedAnalyses &,
1152f19a324SChandler Carruth                   FunctionAnalysisManager::Invalidator &) {
1162f19a324SChandler Carruth     return false;
1172f19a324SChandler Carruth   }
1182f19a324SChandler Carruth 
1195f8f34e4SAdrian Prantl   /// Add an \@llvm.assume intrinsic to this function's cache.
120f5123fecSDaniel Jasper   ///
121f5123fecSDaniel Jasper   /// The call passed in must be an instruction within this function and must
122f5123fecSDaniel Jasper   /// not already be in the cache.
123a6d2a8d6SPhilip Reames   void registerAssumption(AssumeInst *CI);
124f5123fecSDaniel Jasper 
125807960e6SSergey Dmitriev   /// Remove an \@llvm.assume intrinsic from this function's cache if it has
126807960e6SSergey Dmitriev   /// been added to the cache earlier.
127a6d2a8d6SPhilip Reames   void unregisterAssumption(AssumeInst *CI);
128807960e6SSergey Dmitriev 
1295f8f34e4SAdrian Prantl   /// Update the cache of values being affected by this assumption (i.e.
1308a9a783fSHal Finkel   /// the values about which this assumption provides information).
131a6d2a8d6SPhilip Reames   void updateAffectedValues(AssumeInst *CI);
1328a9a783fSHal Finkel 
1335f8f34e4SAdrian Prantl   /// Clear the cache of \@llvm.assume intrinsics for a function.
134f5123fecSDaniel Jasper   ///
135f5123fecSDaniel Jasper   /// It will be re-scanned the next time it is requested.
clear()136f5123fecSDaniel Jasper   void clear() {
137f5123fecSDaniel Jasper     AssumeHandles.clear();
1388a9a783fSHal Finkel     AffectedValues.clear();
139f5123fecSDaniel Jasper     Scanned = false;
140f5123fecSDaniel Jasper   }
141f5123fecSDaniel Jasper 
1425f8f34e4SAdrian Prantl   /// Access the list of assumption handles currently tracked for this
143f5123fecSDaniel Jasper   /// function.
144606aa622SMichael Kruse   ///
145606aa622SMichael Kruse   /// Note that these produce weak handles that may be null. The caller must
146606aa622SMichael Kruse   /// handle that case.
147606aa622SMichael Kruse   /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>>
148606aa622SMichael Kruse   /// when we can write that to filter out the null values. Then caller code
149606aa622SMichael Kruse   /// will become simpler.
assumptions()150606aa622SMichael Kruse   MutableArrayRef<ResultElem> assumptions() {
151f5123fecSDaniel Jasper     if (!Scanned)
152f5123fecSDaniel Jasper       scanFunction();
153f5123fecSDaniel Jasper     return AssumeHandles;
154f5123fecSDaniel Jasper   }
1558a9a783fSHal Finkel 
1565f8f34e4SAdrian Prantl   /// Access the list of assumptions which affect this value.
assumptionsFor(const Value * V)157813f438bSTyker   MutableArrayRef<ResultElem> assumptionsFor(const Value *V) {
1588a9a783fSHal Finkel     if (!Scanned)
1598a9a783fSHal Finkel       scanFunction();
1608a9a783fSHal Finkel 
1618a9a783fSHal Finkel     auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
1628a9a783fSHal Finkel     if (AVI == AffectedValues.end())
163813f438bSTyker       return MutableArrayRef<ResultElem>();
1648a9a783fSHal Finkel 
1658a9a783fSHal Finkel     return AVI->second;
1668a9a783fSHal Finkel   }
167f5123fecSDaniel Jasper };
168f5123fecSDaniel Jasper 
1695f8f34e4SAdrian Prantl /// A function analysis which provides an \c AssumptionCache.
170f5123fecSDaniel Jasper ///
171f5123fecSDaniel Jasper /// This analysis is intended for use with the new pass manager and will vend
172f5123fecSDaniel Jasper /// assumption caches for a given function.
173f5123fecSDaniel Jasper class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
174f5123fecSDaniel Jasper   friend AnalysisInfoMixin<AssumptionAnalysis>;
17575075efeSEugene Zelenko 
176f5123fecSDaniel Jasper   static AnalysisKey Key;
177f5123fecSDaniel Jasper 
178f5123fecSDaniel Jasper public:
17975075efeSEugene Zelenko   using Result = AssumptionCache;
180f5123fecSDaniel Jasper 
181*bf225939SMichael Liao   AssumptionCache run(Function &F, FunctionAnalysisManager &);
182f5123fecSDaniel Jasper };
183f5123fecSDaniel Jasper 
1845f8f34e4SAdrian Prantl /// Printer pass for the \c AssumptionAnalysis results.
185f5123fecSDaniel Jasper class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
186f5123fecSDaniel Jasper   raw_ostream &OS;
187f5123fecSDaniel Jasper 
188f5123fecSDaniel Jasper public:
AssumptionPrinterPass(raw_ostream & OS)189f5123fecSDaniel Jasper   explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
19075075efeSEugene Zelenko 
191f5123fecSDaniel Jasper   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
192f5123fecSDaniel Jasper };
193f5123fecSDaniel Jasper 
1945f8f34e4SAdrian Prantl /// An immutable pass that tracks lazily created \c AssumptionCache
195f5123fecSDaniel Jasper /// objects.
196f5123fecSDaniel Jasper ///
197f5123fecSDaniel Jasper /// This is essentially a workaround for the legacy pass manager's weaknesses
198f5123fecSDaniel Jasper /// which associates each assumption cache with Function and clears it if the
199f5123fecSDaniel Jasper /// function is deleted. The nature of the AssumptionCache is that it is not
200f5123fecSDaniel Jasper /// invalidated by any changes to the function body and so this is sufficient
201f5123fecSDaniel Jasper /// to be conservatively correct.
202f5123fecSDaniel Jasper class AssumptionCacheTracker : public ImmutablePass {
203f5123fecSDaniel Jasper   /// A callback value handle applied to function objects, which we use to
204f5123fecSDaniel Jasper   /// delete our cache of intrinsics for a function when it is deleted.
205f5123fecSDaniel Jasper   class FunctionCallbackVH final : public CallbackVH {
206f5123fecSDaniel Jasper     AssumptionCacheTracker *ACT;
20775075efeSEugene Zelenko 
208f5123fecSDaniel Jasper     void deleted() override;
209f5123fecSDaniel Jasper 
210f5123fecSDaniel Jasper   public:
21175075efeSEugene Zelenko     using DMI = DenseMapInfo<Value *>;
212f5123fecSDaniel Jasper 
213f5123fecSDaniel Jasper     FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
CallbackVH(V)214f5123fecSDaniel Jasper         : CallbackVH(V), ACT(ACT) {}
215f5123fecSDaniel Jasper   };
216f5123fecSDaniel Jasper 
217f5123fecSDaniel Jasper   friend FunctionCallbackVH;
218f5123fecSDaniel Jasper 
21975075efeSEugene Zelenko   using FunctionCallsMap =
22075075efeSEugene Zelenko       DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
22175075efeSEugene Zelenko                FunctionCallbackVH::DMI>;
22275075efeSEugene Zelenko 
223f5123fecSDaniel Jasper   FunctionCallsMap AssumptionCaches;
224f5123fecSDaniel Jasper 
225f5123fecSDaniel Jasper public:
2265f8f34e4SAdrian Prantl   /// Get the cached assumptions for a function.
227f5123fecSDaniel Jasper   ///
228f5123fecSDaniel Jasper   /// If no assumptions are cached, this will scan the function. Otherwise, the
229f5123fecSDaniel Jasper   /// existing cache will be returned.
230f5123fecSDaniel Jasper   AssumptionCache &getAssumptionCache(Function &F);
231f5123fecSDaniel Jasper 
232807960e6SSergey Dmitriev   /// Return the cached assumptions for a function if it has already been
233807960e6SSergey Dmitriev   /// scanned. Otherwise return nullptr.
234807960e6SSergey Dmitriev   AssumptionCache *lookupAssumptionCache(Function &F);
235807960e6SSergey Dmitriev 
236f5123fecSDaniel Jasper   AssumptionCacheTracker();
237f5123fecSDaniel Jasper   ~AssumptionCacheTracker() override;
238f5123fecSDaniel Jasper 
releaseMemory()2399421c2dcSPeter Collingbourne   void releaseMemory() override {
2409421c2dcSPeter Collingbourne     verifyAnalysis();
2419421c2dcSPeter Collingbourne     AssumptionCaches.shrink_and_clear();
2429421c2dcSPeter Collingbourne   }
243f5123fecSDaniel Jasper 
244f5123fecSDaniel Jasper   void verifyAnalysis() const override;
24575075efeSEugene Zelenko 
doFinalization(Module &)246f5123fecSDaniel Jasper   bool doFinalization(Module &) override {
247f5123fecSDaniel Jasper     verifyAnalysis();
248f5123fecSDaniel Jasper     return false;
249f5123fecSDaniel Jasper   }
250f5123fecSDaniel Jasper 
251f5123fecSDaniel Jasper   static char ID; // Pass identification, replacement for typeid
252f5123fecSDaniel Jasper };
253f5123fecSDaniel Jasper 
254813f438bSTyker template<> struct simplify_type<AssumptionCache::ResultElem> {
255813f438bSTyker   using SimpleType = Value *;
256813f438bSTyker 
257813f438bSTyker   static SimpleType getSimplifiedValue(AssumptionCache::ResultElem &Val) {
258813f438bSTyker     return Val;
259813f438bSTyker   }
260813f438bSTyker };
261813f438bSTyker template<> struct simplify_type<const AssumptionCache::ResultElem> {
262813f438bSTyker   using SimpleType = /*const*/ Value *;
263813f438bSTyker 
264813f438bSTyker   static SimpleType getSimplifiedValue(const AssumptionCache::ResultElem &Val) {
265813f438bSTyker     return Val;
266813f438bSTyker   }
267813f438bSTyker };
268813f438bSTyker 
269f5123fecSDaniel Jasper } // end namespace llvm
270f5123fecSDaniel Jasper 
27175075efeSEugene Zelenko #endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H
272