blob: 0ef63dc68e1ca9a923f21989283c1795fd3ce445 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
27namespace llvm {
28
29class CallInst;
30class Function;
31class raw_ostream;
32class Value;
33
Andrew Scullcdfcccc2018-10-05 20:58:37 +010034/// A cache of \@llvm.assume calls within a function.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035///
36/// This cache provides fast lookup of assumptions within a function by caching
37/// them and amortizing the cost of scanning for them across all queries. Passes
38/// that create new assumptions are required to call registerAssumption() to
Andrew Scullcdfcccc2018-10-05 20:58:37 +010039/// register any new \@llvm.assume calls that they create. Deletions of
40/// \@llvm.assume calls do not require special handling.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010041class AssumptionCache {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020042public:
43 /// Value of ResultElem::Index indicating that the argument to the call of the
44 /// llvm.assume.
45 enum : unsigned { ExprResultIdx = std::numeric_limits<unsigned>::max() };
46
47 struct ResultElem {
48 WeakTrackingVH Assume;
49
50 /// contains either ExprResultIdx or the index of the operand bundle
51 /// containing the knowledge.
52 unsigned Index;
53 operator Value *() const { return Assume; }
54 };
55
56private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010057 /// The function for which this cache is handling assumptions.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010058 ///
59 /// We track this to lazily populate our assumptions.
60 Function &F;
61
Andrew Scullcdfcccc2018-10-05 20:58:37 +010062 /// Vector of weak value handles to calls of the \@llvm.assume
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010063 /// intrinsic.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020064 SmallVector<ResultElem, 4> AssumeHandles;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010065
66 class AffectedValueCallbackVH final : public CallbackVH {
67 AssumptionCache *AC;
68
69 void deleted() override;
70 void allUsesReplacedWith(Value *) override;
71
72 public:
73 using DMI = DenseMapInfo<Value *>;
74
75 AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr)
76 : CallbackVH(V), AC(AC) {}
77 };
78
79 friend AffectedValueCallbackVH;
80
Andrew Scullcdfcccc2018-10-05 20:58:37 +010081 /// A map of values about which an assumption might be providing
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010082 /// information to the relevant set of assumptions.
83 using AffectedValuesMap =
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020084 DenseMap<AffectedValueCallbackVH, SmallVector<ResultElem, 1>,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010085 AffectedValueCallbackVH::DMI>;
86 AffectedValuesMap AffectedValues;
87
88 /// Get the vector of assumptions which affect a value from the cache.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020089 SmallVector<ResultElem, 1> &getOrInsertAffectedValues(Value *V);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010090
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020091 /// Move affected values in the cache for OV to be affected values for NV.
92 void transferAffectedValuesInCache(Value *OV, Value *NV);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093
Andrew Scullcdfcccc2018-10-05 20:58:37 +010094 /// Flag tracking whether we have scanned the function yet.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010095 ///
96 /// We want to be as lazy about this as possible, and so we scan the function
97 /// at the last moment.
98 bool Scanned = false;
99
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100100 /// Scan the function for assumptions and add them to the cache.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101 void scanFunction();
102
103public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100104 /// Construct an AssumptionCache from a function by scanning all of
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100105 /// its instructions.
106 AssumptionCache(Function &F) : F(F) {}
107
108 /// This cache is designed to be self-updating and so it should never be
109 /// invalidated.
110 bool invalidate(Function &, const PreservedAnalyses &,
111 FunctionAnalysisManager::Invalidator &) {
112 return false;
113 }
114
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100115 /// Add an \@llvm.assume intrinsic to this function's cache.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116 ///
117 /// The call passed in must be an instruction within this function and must
118 /// not already be in the cache.
119 void registerAssumption(CallInst *CI);
120
Andrew Walbran16937d02019-10-22 13:54:20 +0100121 /// Remove an \@llvm.assume intrinsic from this function's cache if it has
122 /// been added to the cache earlier.
123 void unregisterAssumption(CallInst *CI);
124
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100125 /// Update the cache of values being affected by this assumption (i.e.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100126 /// the values about which this assumption provides information).
127 void updateAffectedValues(CallInst *CI);
128
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100129 /// Clear the cache of \@llvm.assume intrinsics for a function.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100130 ///
131 /// It will be re-scanned the next time it is requested.
132 void clear() {
133 AssumeHandles.clear();
134 AffectedValues.clear();
135 Scanned = false;
136 }
137
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100138 /// Access the list of assumption handles currently tracked for this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100139 /// function.
140 ///
141 /// Note that these produce weak handles that may be null. The caller must
142 /// handle that case.
143 /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>>
144 /// when we can write that to filter out the null values. Then caller code
145 /// will become simpler.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200146 MutableArrayRef<ResultElem> assumptions() {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100147 if (!Scanned)
148 scanFunction();
149 return AssumeHandles;
150 }
151
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100152 /// Access the list of assumptions which affect this value.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200153 MutableArrayRef<ResultElem> assumptionsFor(const Value *V) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 if (!Scanned)
155 scanFunction();
156
157 auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
158 if (AVI == AffectedValues.end())
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200159 return MutableArrayRef<ResultElem>();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100160
161 return AVI->second;
162 }
163};
164
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100165/// A function analysis which provides an \c AssumptionCache.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100166///
167/// This analysis is intended for use with the new pass manager and will vend
168/// assumption caches for a given function.
169class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
170 friend AnalysisInfoMixin<AssumptionAnalysis>;
171
172 static AnalysisKey Key;
173
174public:
175 using Result = AssumptionCache;
176
177 AssumptionCache run(Function &F, FunctionAnalysisManager &) {
178 return AssumptionCache(F);
179 }
180};
181
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100182/// Printer pass for the \c AssumptionAnalysis results.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100183class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
184 raw_ostream &OS;
185
186public:
187 explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
188
189 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
190};
191
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100192/// An immutable pass that tracks lazily created \c AssumptionCache
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100193/// objects.
194///
195/// This is essentially a workaround for the legacy pass manager's weaknesses
196/// which associates each assumption cache with Function and clears it if the
197/// function is deleted. The nature of the AssumptionCache is that it is not
198/// invalidated by any changes to the function body and so this is sufficient
199/// to be conservatively correct.
200class AssumptionCacheTracker : public ImmutablePass {
201 /// A callback value handle applied to function objects, which we use to
202 /// delete our cache of intrinsics for a function when it is deleted.
203 class FunctionCallbackVH final : public CallbackVH {
204 AssumptionCacheTracker *ACT;
205
206 void deleted() override;
207
208 public:
209 using DMI = DenseMapInfo<Value *>;
210
211 FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
212 : CallbackVH(V), ACT(ACT) {}
213 };
214
215 friend FunctionCallbackVH;
216
217 using FunctionCallsMap =
218 DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
219 FunctionCallbackVH::DMI>;
220
221 FunctionCallsMap AssumptionCaches;
222
223public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100224 /// Get the cached assumptions for a function.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100225 ///
226 /// If no assumptions are cached, this will scan the function. Otherwise, the
227 /// existing cache will be returned.
228 AssumptionCache &getAssumptionCache(Function &F);
229
Andrew Walbran16937d02019-10-22 13:54:20 +0100230 /// Return the cached assumptions for a function if it has already been
231 /// scanned. Otherwise return nullptr.
232 AssumptionCache *lookupAssumptionCache(Function &F);
233
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100234 AssumptionCacheTracker();
235 ~AssumptionCacheTracker() override;
236
237 void releaseMemory() override {
238 verifyAnalysis();
239 AssumptionCaches.shrink_and_clear();
240 }
241
242 void verifyAnalysis() const override;
243
244 bool doFinalization(Module &) override {
245 verifyAnalysis();
246 return false;
247 }
248
249 static char ID; // Pass identification, replacement for typeid
250};
251
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200252template<> struct simplify_type<AssumptionCache::ResultElem> {
253 using SimpleType = Value *;
254
255 static SimpleType getSimplifiedValue(AssumptionCache::ResultElem &Val) {
256 return Val;
257 }
258};
259template<> struct simplify_type<const AssumptionCache::ResultElem> {
260 using SimpleType = /*const*/ Value *;
261
262 static SimpleType getSimplifiedValue(const AssumptionCache::ResultElem &Val) {
263 return Val;
264 }
265};
266
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100267} // end namespace llvm
268
269#endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H