Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:11

0001 //===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains a pass that keeps track of @llvm.assume intrinsics in
0010 // the functions of a module (allowing assumptions within any function to be
0011 // found cheaply by other parts of the optimizer).
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H
0016 #define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
0017 
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/ADT/DenseMap.h"
0020 #include "llvm/ADT/DenseMapInfo.h"
0021 #include "llvm/ADT/SmallVector.h"
0022 #include "llvm/IR/PassManager.h"
0023 #include "llvm/IR/ValueHandle.h"
0024 #include "llvm/Pass.h"
0025 #include <memory>
0026 
0027 namespace llvm {
0028 
0029 class AssumeInst;
0030 class Function;
0031 class raw_ostream;
0032 class TargetTransformInfo;
0033 class Value;
0034 
0035 /// A cache of \@llvm.assume calls within a function.
0036 ///
0037 /// This cache provides fast lookup of assumptions within a function by caching
0038 /// them and amortizing the cost of scanning for them across all queries. Passes
0039 /// that create new assumptions are required to call registerAssumption() to
0040 /// register any new \@llvm.assume calls that they create. Deletions of
0041 /// \@llvm.assume calls do not require special handling.
0042 class AssumptionCache {
0043 public:
0044   /// Value of ResultElem::Index indicating that the argument to the call of the
0045   /// llvm.assume.
0046   enum : unsigned { ExprResultIdx = std::numeric_limits<unsigned>::max() };
0047 
0048   struct ResultElem {
0049     WeakVH Assume;
0050 
0051     /// contains either ExprResultIdx or the index of the operand bundle
0052     /// containing the knowledge.
0053     unsigned Index;
0054     operator Value *() const { return Assume; }
0055   };
0056 
0057 private:
0058   /// The function for which this cache is handling assumptions.
0059   ///
0060   /// We track this to lazily populate our assumptions.
0061   Function &F;
0062 
0063   TargetTransformInfo *TTI;
0064 
0065   /// Vector of weak value handles to calls of the \@llvm.assume
0066   /// intrinsic.
0067   SmallVector<ResultElem, 4> AssumeHandles;
0068 
0069   class AffectedValueCallbackVH final : public CallbackVH {
0070     AssumptionCache *AC;
0071 
0072     void deleted() override;
0073     void allUsesReplacedWith(Value *) override;
0074 
0075   public:
0076     using DMI = DenseMapInfo<Value *>;
0077 
0078     AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr)
0079         : CallbackVH(V), AC(AC) {}
0080   };
0081 
0082   friend AffectedValueCallbackVH;
0083 
0084   /// A map of values about which an assumption might be providing
0085   /// information to the relevant set of assumptions.
0086   using AffectedValuesMap =
0087       DenseMap<AffectedValueCallbackVH, SmallVector<ResultElem, 1>,
0088                AffectedValueCallbackVH::DMI>;
0089   AffectedValuesMap AffectedValues;
0090 
0091   /// Get the vector of assumptions which affect a value from the cache.
0092   SmallVector<ResultElem, 1> &getOrInsertAffectedValues(Value *V);
0093 
0094   /// Move affected values in the cache for OV to be affected values for NV.
0095   void transferAffectedValuesInCache(Value *OV, Value *NV);
0096 
0097   /// Flag tracking whether we have scanned the function yet.
0098   ///
0099   /// We want to be as lazy about this as possible, and so we scan the function
0100   /// at the last moment.
0101   bool Scanned = false;
0102 
0103   /// Scan the function for assumptions and add them to the cache.
0104   void scanFunction();
0105 
0106 public:
0107   /// Construct an AssumptionCache from a function by scanning all of
0108   /// its instructions.
0109   AssumptionCache(Function &F, TargetTransformInfo *TTI = nullptr)
0110       : F(F), TTI(TTI) {}
0111 
0112   /// This cache is designed to be self-updating and so it should never be
0113   /// invalidated.
0114   bool invalidate(Function &, const PreservedAnalyses &,
0115                   FunctionAnalysisManager::Invalidator &) {
0116     return false;
0117   }
0118 
0119   /// Add an \@llvm.assume intrinsic to this function's cache.
0120   ///
0121   /// The call passed in must be an instruction within this function and must
0122   /// not already be in the cache.
0123   void registerAssumption(AssumeInst *CI);
0124 
0125   /// Remove an \@llvm.assume intrinsic from this function's cache if it has
0126   /// been added to the cache earlier.
0127   void unregisterAssumption(AssumeInst *CI);
0128 
0129   /// Update the cache of values being affected by this assumption (i.e.
0130   /// the values about which this assumption provides information).
0131   void updateAffectedValues(AssumeInst *CI);
0132 
0133   /// Clear the cache of \@llvm.assume intrinsics for a function.
0134   ///
0135   /// It will be re-scanned the next time it is requested.
0136   void clear() {
0137     AssumeHandles.clear();
0138     AffectedValues.clear();
0139     Scanned = false;
0140   }
0141 
0142   /// Access the list of assumption handles currently tracked for this
0143   /// function.
0144   ///
0145   /// Note that these produce weak handles that may be null. The caller must
0146   /// handle that case.
0147   /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>>
0148   /// when we can write that to filter out the null values. Then caller code
0149   /// will become simpler.
0150   MutableArrayRef<ResultElem> assumptions() {
0151     if (!Scanned)
0152       scanFunction();
0153     return AssumeHandles;
0154   }
0155 
0156   /// Access the list of assumptions which affect this value.
0157   MutableArrayRef<ResultElem> assumptionsFor(const Value *V) {
0158     if (!Scanned)
0159       scanFunction();
0160 
0161     auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
0162     if (AVI == AffectedValues.end())
0163       return MutableArrayRef<ResultElem>();
0164 
0165     return AVI->second;
0166   }
0167 };
0168 
0169 /// A function analysis which provides an \c AssumptionCache.
0170 ///
0171 /// This analysis is intended for use with the new pass manager and will vend
0172 /// assumption caches for a given function.
0173 class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
0174   friend AnalysisInfoMixin<AssumptionAnalysis>;
0175 
0176   static AnalysisKey Key;
0177 
0178 public:
0179   using Result = AssumptionCache;
0180 
0181   AssumptionCache run(Function &F, FunctionAnalysisManager &);
0182 };
0183 
0184 /// Printer pass for the \c AssumptionAnalysis results.
0185 class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
0186   raw_ostream &OS;
0187 
0188 public:
0189   explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
0190 
0191   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0192 
0193   static bool isRequired() { return true; }
0194 };
0195 
0196 /// An immutable pass that tracks lazily created \c AssumptionCache
0197 /// objects.
0198 ///
0199 /// This is essentially a workaround for the legacy pass manager's weaknesses
0200 /// which associates each assumption cache with Function and clears it if the
0201 /// function is deleted. The nature of the AssumptionCache is that it is not
0202 /// invalidated by any changes to the function body and so this is sufficient
0203 /// to be conservatively correct.
0204 class AssumptionCacheTracker : public ImmutablePass {
0205   /// A callback value handle applied to function objects, which we use to
0206   /// delete our cache of intrinsics for a function when it is deleted.
0207   class FunctionCallbackVH final : public CallbackVH {
0208     AssumptionCacheTracker *ACT;
0209 
0210     void deleted() override;
0211 
0212   public:
0213     using DMI = DenseMapInfo<Value *>;
0214 
0215     FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
0216         : CallbackVH(V), ACT(ACT) {}
0217   };
0218 
0219   friend FunctionCallbackVH;
0220 
0221   using FunctionCallsMap =
0222       DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
0223                FunctionCallbackVH::DMI>;
0224 
0225   FunctionCallsMap AssumptionCaches;
0226 
0227 public:
0228   /// Get the cached assumptions for a function.
0229   ///
0230   /// If no assumptions are cached, this will scan the function. Otherwise, the
0231   /// existing cache will be returned.
0232   AssumptionCache &getAssumptionCache(Function &F);
0233 
0234   /// Return the cached assumptions for a function if it has already been
0235   /// scanned. Otherwise return nullptr.
0236   AssumptionCache *lookupAssumptionCache(Function &F);
0237 
0238   AssumptionCacheTracker();
0239   ~AssumptionCacheTracker() override;
0240 
0241   void releaseMemory() override {
0242     verifyAnalysis();
0243     AssumptionCaches.shrink_and_clear();
0244   }
0245 
0246   void verifyAnalysis() const override;
0247 
0248   bool doFinalization(Module &) override {
0249     verifyAnalysis();
0250     return false;
0251   }
0252 
0253   static char ID; // Pass identification, replacement for typeid
0254 };
0255 
0256 template<> struct simplify_type<AssumptionCache::ResultElem> {
0257   using SimpleType = Value *;
0258 
0259   static SimpleType getSimplifiedValue(AssumptionCache::ResultElem &Val) {
0260     return Val;
0261   }
0262 };
0263 template<> struct simplify_type<const AssumptionCache::ResultElem> {
0264   using SimpleType = /*const*/ Value *;
0265 
0266   static SimpleType getSimplifiedValue(const AssumptionCache::ResultElem &Val) {
0267     return Val;
0268   }
0269 };
0270 
0271 } // end namespace llvm
0272 
0273 #endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H