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