1 //===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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).
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H
16 #define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
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"
32 class TargetTransformInfo
;
35 /// A cache of \@llvm.assume calls within a function.
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
{
44 /// Value of ResultElem::Index indicating that the argument to the call of the
46 enum : unsigned { ExprResultIdx
= std::numeric_limits
<unsigned>::max() };
51 /// contains either ExprResultIdx or the index of the operand bundle
52 /// containing the knowledge.
54 operator Value
*() const { return Assume
; }
58 /// The function for which this cache is handling assumptions.
60 /// We track this to lazily populate our assumptions.
63 TargetTransformInfo
*TTI
;
65 /// Vector of weak value handles to calls of the \@llvm.assume
67 SmallVector
<ResultElem
, 4> AssumeHandles
;
69 class AffectedValueCallbackVH final
: public CallbackVH
{
72 void deleted() override
;
73 void allUsesReplacedWith(Value
*) override
;
76 using DMI
= DenseMapInfo
<Value
*>;
78 AffectedValueCallbackVH(Value
*V
, AssumptionCache
*AC
= nullptr)
79 : CallbackVH(V
), AC(AC
) {}
82 friend AffectedValueCallbackVH
;
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
;
91 /// Get the vector of assumptions which affect a value from the cache.
92 SmallVector
<ResultElem
, 1> &getOrInsertAffectedValues(Value
*V
);
94 /// Move affected values in the cache for OV to be affected values for NV.
95 void transferAffectedValuesInCache(Value
*OV
, Value
*NV
);
97 /// Flag tracking whether we have scanned the function yet.
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;
103 /// Scan the function for assumptions and add them to the cache.
107 /// Construct an AssumptionCache from a function by scanning all of
108 /// its instructions.
109 AssumptionCache(Function
&F
, TargetTransformInfo
*TTI
= nullptr)
112 /// This cache is designed to be self-updating and so it should never be
114 bool invalidate(Function
&, const PreservedAnalyses
&,
115 FunctionAnalysisManager::Invalidator
&) {
119 /// Add an \@llvm.assume intrinsic to this function's cache.
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
);
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
);
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
);
133 /// Clear the cache of \@llvm.assume intrinsics for a function.
135 /// It will be re-scanned the next time it is requested.
137 AssumeHandles
.clear();
138 AffectedValues
.clear();
142 /// Access the list of assumption handles currently tracked for this
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() {
153 return AssumeHandles
;
156 /// Access the list of assumptions which affect this value.
157 MutableArrayRef
<ResultElem
> assumptionsFor(const Value
*V
) {
161 auto AVI
= AffectedValues
.find_as(const_cast<Value
*>(V
));
162 if (AVI
== AffectedValues
.end())
163 return MutableArrayRef
<ResultElem
>();
169 /// A function analysis which provides an \c AssumptionCache.
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
>;
176 static AnalysisKey Key
;
179 using Result
= AssumptionCache
;
181 AssumptionCache
run(Function
&F
, FunctionAnalysisManager
&);
184 /// Printer pass for the \c AssumptionAnalysis results.
185 class AssumptionPrinterPass
: public PassInfoMixin
<AssumptionPrinterPass
> {
189 explicit AssumptionPrinterPass(raw_ostream
&OS
) : OS(OS
) {}
191 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
);
193 static bool isRequired() { return true; }
196 /// An immutable pass that tracks lazily created \c AssumptionCache
199 /// This is essentially a workaround for the legacy pass manager's weaknesses
200 /// which associates each assumption cache with Function and clears it if the
201 /// function is deleted. The nature of the AssumptionCache is that it is not
202 /// invalidated by any changes to the function body and so this is sufficient
203 /// to be conservatively correct.
204 class AssumptionCacheTracker
: public ImmutablePass
{
205 /// A callback value handle applied to function objects, which we use to
206 /// delete our cache of intrinsics for a function when it is deleted.
207 class FunctionCallbackVH final
: public CallbackVH
{
208 AssumptionCacheTracker
*ACT
;
210 void deleted() override
;
213 using DMI
= DenseMapInfo
<Value
*>;
215 FunctionCallbackVH(Value
*V
, AssumptionCacheTracker
*ACT
= nullptr)
216 : CallbackVH(V
), ACT(ACT
) {}
219 friend FunctionCallbackVH
;
221 using FunctionCallsMap
=
222 DenseMap
<FunctionCallbackVH
, std::unique_ptr
<AssumptionCache
>,
223 FunctionCallbackVH::DMI
>;
225 FunctionCallsMap AssumptionCaches
;
228 /// Get the cached assumptions for a function.
230 /// If no assumptions are cached, this will scan the function. Otherwise, the
231 /// existing cache will be returned.
232 AssumptionCache
&getAssumptionCache(Function
&F
);
234 /// Return the cached assumptions for a function if it has already been
235 /// scanned. Otherwise return nullptr.
236 AssumptionCache
*lookupAssumptionCache(Function
&F
);
238 AssumptionCacheTracker();
239 ~AssumptionCacheTracker() override
;
241 void releaseMemory() override
{
243 AssumptionCaches
.shrink_and_clear();
246 void verifyAnalysis() const override
;
248 bool doFinalization(Module
&) override
{
253 static char ID
; // Pass identification, replacement for typeid
256 template<> struct simplify_type
<AssumptionCache::ResultElem
> {
257 using SimpleType
= Value
*;
259 static SimpleType
getSimplifiedValue(AssumptionCache::ResultElem
&Val
) {
263 template<> struct simplify_type
<const AssumptionCache::ResultElem
> {
264 using SimpleType
= /*const*/ Value
*;
266 static SimpleType
getSimplifiedValue(const AssumptionCache::ResultElem
&Val
) {
271 } // end namespace llvm
273 #endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H