Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===// |
2 | // |
||
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 |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file defines the MemoryDependenceAnalysis analysis pass. |
||
10 | // |
||
11 | //===----------------------------------------------------------------------===// |
||
12 | |||
13 | #ifndef LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H |
||
14 | #define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H |
||
15 | |||
16 | #include "llvm/ADT/DenseMap.h" |
||
17 | #include "llvm/ADT/PointerEmbeddedInt.h" |
||
18 | #include "llvm/ADT/PointerIntPair.h" |
||
19 | #include "llvm/ADT/PointerSumType.h" |
||
20 | #include "llvm/ADT/SmallPtrSet.h" |
||
21 | #include "llvm/Analysis/MemoryLocation.h" |
||
22 | #include "llvm/IR/PassManager.h" |
||
23 | #include "llvm/IR/PredIteratorCache.h" |
||
24 | #include "llvm/IR/ValueHandle.h" |
||
25 | #include "llvm/Pass.h" |
||
26 | #include <optional> |
||
27 | |||
28 | namespace llvm { |
||
29 | |||
30 | class AAResults; |
||
31 | class AssumptionCache; |
||
32 | class BatchAAResults; |
||
33 | class DominatorTree; |
||
34 | class PHITransAddr; |
||
35 | |||
36 | /// A memory dependence query can return one of three different answers. |
||
37 | class MemDepResult { |
||
38 | enum DepType { |
||
39 | /// Clients of MemDep never see this. |
||
40 | /// |
||
41 | /// Entries with this marker occur in a LocalDeps map or NonLocalDeps map |
||
42 | /// when the instruction they previously referenced was removed from |
||
43 | /// MemDep. In either case, the entry may include an instruction pointer. |
||
44 | /// If so, the pointer is an instruction in the block where scanning can |
||
45 | /// start from, saving some work. |
||
46 | /// |
||
47 | /// In a default-constructed MemDepResult object, the type will be Invalid |
||
48 | /// and the instruction pointer will be null. |
||
49 | Invalid = 0, |
||
50 | |||
51 | /// This is a dependence on the specified instruction which clobbers the |
||
52 | /// desired value. The pointer member of the MemDepResult pair holds the |
||
53 | /// instruction that clobbers the memory. For example, this occurs when we |
||
54 | /// see a may-aliased store to the memory location we care about. |
||
55 | /// |
||
56 | /// There are several cases that may be interesting here: |
||
57 | /// 1. Loads are clobbered by may-alias stores. |
||
58 | /// 2. Loads are considered clobbered by partially-aliased loads. The |
||
59 | /// client may choose to analyze deeper into these cases. |
||
60 | Clobber, |
||
61 | |||
62 | /// This is a dependence on the specified instruction which defines or |
||
63 | /// produces the desired memory location. The pointer member of the |
||
64 | /// MemDepResult pair holds the instruction that defines the memory. |
||
65 | /// |
||
66 | /// Cases of interest: |
||
67 | /// 1. This could be a load or store for dependence queries on |
||
68 | /// load/store. The value loaded or stored is the produced value. |
||
69 | /// Note that the pointer operand may be different than that of the |
||
70 | /// queried pointer due to must aliases and phi translation. Note |
||
71 | /// that the def may not be the same type as the query, the pointers |
||
72 | /// may just be must aliases. |
||
73 | /// 2. For loads and stores, this could be an allocation instruction. In |
||
74 | /// this case, the load is loading an undef value or a store is the |
||
75 | /// first store to (that part of) the allocation. |
||
76 | /// 3. Dependence queries on calls return Def only when they are readonly |
||
77 | /// calls or memory use intrinsics with identical callees and no |
||
78 | /// intervening clobbers. No validation is done that the operands to |
||
79 | /// the calls are the same. |
||
80 | /// 4. For loads and stores, this could be a select instruction that |
||
81 | /// defines pointer to this memory location. In this case, users can |
||
82 | /// find non-clobbered Defs for both select values that are reaching |
||
83 | // the desired memory location (there is still a guarantee that there |
||
84 | // are no clobbers between analyzed memory location and select). |
||
85 | Def, |
||
86 | |||
87 | /// This marker indicates that the query has no known dependency in the |
||
88 | /// specified block. |
||
89 | /// |
||
90 | /// More detailed state info is encoded in the upper part of the pair (i.e. |
||
91 | /// the Instruction*) |
||
92 | Other |
||
93 | }; |
||
94 | |||
95 | /// If DepType is "Other", the upper part of the sum type is an encoding of |
||
96 | /// the following more detailed type information. |
||
97 | enum OtherType { |
||
98 | /// This marker indicates that the query has no dependency in the specified |
||
99 | /// block. |
||
100 | /// |
||
101 | /// To find out more, the client should query other predecessor blocks. |
||
102 | NonLocal = 1, |
||
103 | /// This marker indicates that the query has no dependency in the specified |
||
104 | /// function. |
||
105 | NonFuncLocal, |
||
106 | /// This marker indicates that the query dependency is unknown. |
||
107 | Unknown |
||
108 | }; |
||
109 | |||
110 | using ValueTy = PointerSumType< |
||
111 | DepType, PointerSumTypeMember<Invalid, Instruction *>, |
||
112 | PointerSumTypeMember<Clobber, Instruction *>, |
||
113 | PointerSumTypeMember<Def, Instruction *>, |
||
114 | PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>; |
||
115 | ValueTy Value; |
||
116 | |||
117 | explicit MemDepResult(ValueTy V) : Value(V) {} |
||
118 | |||
119 | public: |
||
120 | MemDepResult() = default; |
||
121 | |||
122 | /// get methods: These are static ctor methods for creating various |
||
123 | /// MemDepResult kinds. |
||
124 | static MemDepResult getDef(Instruction *Inst) { |
||
125 | assert(Inst && "Def requires inst"); |
||
126 | return MemDepResult(ValueTy::create<Def>(Inst)); |
||
127 | } |
||
128 | static MemDepResult getClobber(Instruction *Inst) { |
||
129 | assert(Inst && "Clobber requires inst"); |
||
130 | return MemDepResult(ValueTy::create<Clobber>(Inst)); |
||
131 | } |
||
132 | static MemDepResult getNonLocal() { |
||
133 | return MemDepResult(ValueTy::create<Other>(NonLocal)); |
||
134 | } |
||
135 | static MemDepResult getNonFuncLocal() { |
||
136 | return MemDepResult(ValueTy::create<Other>(NonFuncLocal)); |
||
137 | } |
||
138 | static MemDepResult getUnknown() { |
||
139 | return MemDepResult(ValueTy::create<Other>(Unknown)); |
||
140 | } |
||
141 | |||
142 | /// Tests if this MemDepResult represents a query that is an instruction |
||
143 | /// clobber dependency. |
||
144 | bool isClobber() const { return Value.is<Clobber>(); } |
||
145 | |||
146 | /// Tests if this MemDepResult represents a query that is an instruction |
||
147 | /// definition dependency. |
||
148 | bool isDef() const { return Value.is<Def>(); } |
||
149 | |||
150 | /// Tests if this MemDepResult represents a valid local query (Clobber/Def). |
||
151 | bool isLocal() const { return isClobber() || isDef(); } |
||
152 | |||
153 | /// Tests if this MemDepResult represents a query that is transparent to the |
||
154 | /// start of the block, but where a non-local hasn't been done. |
||
155 | bool isNonLocal() const { |
||
156 | return Value.is<Other>() && Value.cast<Other>() == NonLocal; |
||
157 | } |
||
158 | |||
159 | /// Tests if this MemDepResult represents a query that is transparent to the |
||
160 | /// start of the function. |
||
161 | bool isNonFuncLocal() const { |
||
162 | return Value.is<Other>() && Value.cast<Other>() == NonFuncLocal; |
||
163 | } |
||
164 | |||
165 | /// Tests if this MemDepResult represents a query which cannot and/or will |
||
166 | /// not be computed. |
||
167 | bool isUnknown() const { |
||
168 | return Value.is<Other>() && Value.cast<Other>() == Unknown; |
||
169 | } |
||
170 | |||
171 | /// If this is a normal dependency, returns the instruction that is depended |
||
172 | /// on. Otherwise, returns null. |
||
173 | Instruction *getInst() const { |
||
174 | switch (Value.getTag()) { |
||
175 | case Invalid: |
||
176 | return Value.cast<Invalid>(); |
||
177 | case Clobber: |
||
178 | return Value.cast<Clobber>(); |
||
179 | case Def: |
||
180 | return Value.cast<Def>(); |
||
181 | case Other: |
||
182 | return nullptr; |
||
183 | } |
||
184 | llvm_unreachable("Unknown discriminant!"); |
||
185 | } |
||
186 | |||
187 | bool operator==(const MemDepResult &M) const { return Value == M.Value; } |
||
188 | bool operator!=(const MemDepResult &M) const { return Value != M.Value; } |
||
189 | bool operator<(const MemDepResult &M) const { return Value < M.Value; } |
||
190 | bool operator>(const MemDepResult &M) const { return Value > M.Value; } |
||
191 | |||
192 | private: |
||
193 | friend class MemoryDependenceResults; |
||
194 | |||
195 | /// Tests if this is a MemDepResult in its dirty/invalid. state. |
||
196 | bool isDirty() const { return Value.is<Invalid>(); } |
||
197 | |||
198 | static MemDepResult getDirty(Instruction *Inst) { |
||
199 | return MemDepResult(ValueTy::create<Invalid>(Inst)); |
||
200 | } |
||
201 | }; |
||
202 | |||
203 | /// This is an entry in the NonLocalDepInfo cache. |
||
204 | /// |
||
205 | /// For each BasicBlock (the BB entry) it keeps a MemDepResult. |
||
206 | class NonLocalDepEntry { |
||
207 | BasicBlock *BB; |
||
208 | MemDepResult Result; |
||
209 | |||
210 | public: |
||
211 | NonLocalDepEntry(BasicBlock *bb, MemDepResult result) |
||
212 | : BB(bb), Result(result) {} |
||
213 | |||
214 | // This is used for searches. |
||
215 | NonLocalDepEntry(BasicBlock *bb) : BB(bb) {} |
||
216 | |||
217 | // BB is the sort key, it can't be changed. |
||
218 | BasicBlock *getBB() const { return BB; } |
||
219 | |||
220 | void setResult(const MemDepResult &R) { Result = R; } |
||
221 | |||
222 | const MemDepResult &getResult() const { return Result; } |
||
223 | |||
224 | bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; } |
||
225 | }; |
||
226 | |||
227 | /// This is a result from a NonLocal dependence query. |
||
228 | /// |
||
229 | /// For each BasicBlock (the BB entry) it keeps a MemDepResult and the |
||
230 | /// (potentially phi translated) address that was live in the block. |
||
231 | class NonLocalDepResult { |
||
232 | NonLocalDepEntry Entry; |
||
233 | Value *Address; |
||
234 | |||
235 | public: |
||
236 | NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address) |
||
237 | : Entry(bb, result), Address(address) {} |
||
238 | |||
239 | // BB is the sort key, it can't be changed. |
||
240 | BasicBlock *getBB() const { return Entry.getBB(); } |
||
241 | |||
242 | void setResult(const MemDepResult &R, Value *Addr) { |
||
243 | Entry.setResult(R); |
||
244 | Address = Addr; |
||
245 | } |
||
246 | |||
247 | const MemDepResult &getResult() const { return Entry.getResult(); } |
||
248 | |||
249 | /// Returns the address of this pointer in this block. |
||
250 | /// |
||
251 | /// This can be different than the address queried for the non-local result |
||
252 | /// because of phi translation. This returns null if the address was not |
||
253 | /// available in a block (i.e. because phi translation failed) or if this is |
||
254 | /// a cached result and that address was deleted. |
||
255 | /// |
||
256 | /// The address is always null for a non-local 'call' dependence. |
||
257 | Value *getAddress() const { return Address; } |
||
258 | }; |
||
259 | |||
260 | /// Provides a lazy, caching interface for making common memory aliasing |
||
261 | /// information queries, backed by LLVM's alias analysis passes. |
||
262 | /// |
||
263 | /// The dependency information returned is somewhat unusual, but is pragmatic. |
||
264 | /// If queried about a store or call that might modify memory, the analysis |
||
265 | /// will return the instruction[s] that may either load from that memory or |
||
266 | /// store to it. If queried with a load or call that can never modify memory, |
||
267 | /// the analysis will return calls and stores that might modify the pointer, |
||
268 | /// but generally does not return loads unless a) they are volatile, or |
||
269 | /// b) they load from *must-aliased* pointers. Returning a dependence on |
||
270 | /// must-alias'd pointers instead of all pointers interacts well with the |
||
271 | /// internal caching mechanism. |
||
272 | class MemoryDependenceResults { |
||
273 | // A map from instructions to their dependency. |
||
274 | using LocalDepMapType = DenseMap<Instruction *, MemDepResult>; |
||
275 | LocalDepMapType LocalDeps; |
||
276 | |||
277 | public: |
||
278 | using NonLocalDepInfo = std::vector<NonLocalDepEntry>; |
||
279 | |||
280 | private: |
||
281 | /// A pair<Value*, bool> where the bool is true if the dependence is a read |
||
282 | /// only dependence, false if read/write. |
||
283 | using ValueIsLoadPair = PointerIntPair<const Value *, 1, bool>; |
||
284 | |||
285 | /// This pair is used when caching information for a block. |
||
286 | /// |
||
287 | /// If the pointer is null, the cache value is not a full query that starts |
||
288 | /// at the specified block. If non-null, the bool indicates whether or not |
||
289 | /// the contents of the block was skipped. |
||
290 | using BBSkipFirstBlockPair = PointerIntPair<BasicBlock *, 1, bool>; |
||
291 | |||
292 | /// This record is the information kept for each (value, is load) pair. |
||
293 | struct NonLocalPointerInfo { |
||
294 | /// The pair of the block and the skip-first-block flag. |
||
295 | BBSkipFirstBlockPair Pair; |
||
296 | /// The results of the query for each relevant block. |
||
297 | NonLocalDepInfo NonLocalDeps; |
||
298 | /// The maximum size of the dereferences of the pointer. |
||
299 | /// |
||
300 | /// May be UnknownSize if the sizes are unknown. |
||
301 | LocationSize Size = LocationSize::afterPointer(); |
||
302 | /// The AA tags associated with dereferences of the pointer. |
||
303 | /// |
||
304 | /// The members may be null if there are no tags or conflicting tags. |
||
305 | AAMDNodes AATags; |
||
306 | |||
307 | NonLocalPointerInfo() = default; |
||
308 | }; |
||
309 | |||
310 | /// Cache storing single nonlocal def for the instruction. |
||
311 | /// It is set when nonlocal def would be found in function returning only |
||
312 | /// local dependencies. |
||
313 | DenseMap<AssertingVH<const Value>, NonLocalDepResult> NonLocalDefsCache; |
||
314 | using ReverseNonLocalDefsCacheTy = |
||
315 | DenseMap<Instruction *, SmallPtrSet<const Value*, 4>>; |
||
316 | ReverseNonLocalDefsCacheTy ReverseNonLocalDefsCache; |
||
317 | |||
318 | /// This map stores the cached results of doing a pointer lookup at the |
||
319 | /// bottom of a block. |
||
320 | /// |
||
321 | /// The key of this map is the pointer+isload bit, the value is a list of |
||
322 | /// <bb->result> mappings. |
||
323 | using CachedNonLocalPointerInfo = |
||
324 | DenseMap<ValueIsLoadPair, NonLocalPointerInfo>; |
||
325 | CachedNonLocalPointerInfo NonLocalPointerDeps; |
||
326 | |||
327 | // A map from instructions to their non-local pointer dependencies. |
||
328 | using ReverseNonLocalPtrDepTy = |
||
329 | DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>; |
||
330 | ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps; |
||
331 | |||
332 | /// This is the instruction we keep for each cached access that we have for |
||
333 | /// an instruction. |
||
334 | /// |
||
335 | /// The pointer is an owning pointer and the bool indicates whether we have |
||
336 | /// any dirty bits in the set. |
||
337 | using PerInstNLInfo = std::pair<NonLocalDepInfo, bool>; |
||
338 | |||
339 | // A map from instructions to their non-local dependencies. |
||
340 | using NonLocalDepMapType = DenseMap<Instruction *, PerInstNLInfo>; |
||
341 | |||
342 | NonLocalDepMapType NonLocalDepsMap; |
||
343 | |||
344 | // A reverse mapping from dependencies to the dependees. This is |
||
345 | // used when removing instructions to keep the cache coherent. |
||
346 | using ReverseDepMapType = |
||
347 | DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>; |
||
348 | ReverseDepMapType ReverseLocalDeps; |
||
349 | |||
350 | // A reverse mapping from dependencies to the non-local dependees. |
||
351 | ReverseDepMapType ReverseNonLocalDeps; |
||
352 | |||
353 | /// Current AA implementation, just a cache. |
||
354 | AAResults &AA; |
||
355 | AssumptionCache &AC; |
||
356 | const TargetLibraryInfo &TLI; |
||
357 | DominatorTree &DT; |
||
358 | PredIteratorCache PredCache; |
||
359 | |||
360 | unsigned DefaultBlockScanLimit; |
||
361 | |||
362 | /// Offsets to dependant clobber loads. |
||
363 | using ClobberOffsetsMapType = DenseMap<LoadInst *, int32_t>; |
||
364 | ClobberOffsetsMapType ClobberOffsets; |
||
365 | |||
366 | public: |
||
367 | MemoryDependenceResults(AAResults &AA, AssumptionCache &AC, |
||
368 | const TargetLibraryInfo &TLI, DominatorTree &DT, |
||
369 | unsigned DefaultBlockScanLimit) |
||
370 | : AA(AA), AC(AC), TLI(TLI), DT(DT), |
||
371 | DefaultBlockScanLimit(DefaultBlockScanLimit) {} |
||
372 | |||
373 | /// Handle invalidation in the new PM. |
||
374 | bool invalidate(Function &F, const PreservedAnalyses &PA, |
||
375 | FunctionAnalysisManager::Invalidator &Inv); |
||
376 | |||
377 | /// Some methods limit the number of instructions they will examine. |
||
378 | /// The return value of this method is the default limit that will be |
||
379 | /// used if no limit is explicitly passed in. |
||
380 | unsigned getDefaultBlockScanLimit() const; |
||
381 | |||
382 | /// Returns the instruction on which a memory operation depends. |
||
383 | /// |
||
384 | /// See the class comment for more details. It is illegal to call this on |
||
385 | /// non-memory instructions. |
||
386 | MemDepResult getDependency(Instruction *QueryInst); |
||
387 | |||
388 | /// Perform a full dependency query for the specified call, returning the set |
||
389 | /// of blocks that the value is potentially live across. |
||
390 | /// |
||
391 | /// The returned set of results will include a "NonLocal" result for all |
||
392 | /// blocks where the value is live across. |
||
393 | /// |
||
394 | /// This method assumes the instruction returns a "NonLocal" dependency |
||
395 | /// within its own block. |
||
396 | /// |
||
397 | /// This returns a reference to an internal data structure that may be |
||
398 | /// invalidated on the next non-local query or when an instruction is |
||
399 | /// removed. Clients must copy this data if they want it around longer than |
||
400 | /// that. |
||
401 | const NonLocalDepInfo &getNonLocalCallDependency(CallBase *QueryCall); |
||
402 | |||
403 | /// Perform a full dependency query for an access to the QueryInst's |
||
404 | /// specified memory location, returning the set of instructions that either |
||
405 | /// define or clobber the value. |
||
406 | /// |
||
407 | /// Warning: For a volatile query instruction, the dependencies will be |
||
408 | /// accurate, and thus usable for reordering, but it is never legal to |
||
409 | /// remove the query instruction. |
||
410 | /// |
||
411 | /// This method assumes the pointer has a "NonLocal" dependency within |
||
412 | /// QueryInst's parent basic block. |
||
413 | void getNonLocalPointerDependency(Instruction *QueryInst, |
||
414 | SmallVectorImpl<NonLocalDepResult> &Result); |
||
415 | |||
416 | /// Removes an instruction from the dependence analysis, updating the |
||
417 | /// dependence of instructions that previously depended on it. |
||
418 | void removeInstruction(Instruction *InstToRemove); |
||
419 | |||
420 | /// Invalidates cached information about the specified pointer, because it |
||
421 | /// may be too conservative in memdep. |
||
422 | /// |
||
423 | /// This is an optional call that can be used when the client detects an |
||
424 | /// equivalence between the pointer and some other value and replaces the |
||
425 | /// other value with ptr. This can make Ptr available in more places that |
||
426 | /// cached info does not necessarily keep. |
||
427 | void invalidateCachedPointerInfo(Value *Ptr); |
||
428 | |||
429 | /// Clears the PredIteratorCache info. |
||
430 | /// |
||
431 | /// This needs to be done when the CFG changes, e.g., due to splitting |
||
432 | /// critical edges. |
||
433 | void invalidateCachedPredecessors(); |
||
434 | |||
435 | /// Returns the instruction on which a memory location depends. |
||
436 | /// |
||
437 | /// If isLoad is true, this routine ignores may-aliases with read-only |
||
438 | /// operations. If isLoad is false, this routine ignores may-aliases |
||
439 | /// with reads from read-only locations. If possible, pass the query |
||
440 | /// instruction as well; this function may take advantage of the metadata |
||
441 | /// annotated to the query instruction to refine the result. \p Limit |
||
442 | /// can be used to set the maximum number of instructions that will be |
||
443 | /// examined to find the pointer dependency. On return, it will be set to |
||
444 | /// the number of instructions left to examine. If a null pointer is passed |
||
445 | /// in, the limit will default to the value of -memdep-block-scan-limit. |
||
446 | /// |
||
447 | /// Note that this is an uncached query, and thus may be inefficient. |
||
448 | MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad, |
||
449 | BasicBlock::iterator ScanIt, |
||
450 | BasicBlock *BB, |
||
451 | Instruction *QueryInst = nullptr, |
||
452 | unsigned *Limit = nullptr); |
||
453 | |||
454 | MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad, |
||
455 | BasicBlock::iterator ScanIt, |
||
456 | BasicBlock *BB, |
||
457 | Instruction *QueryInst, |
||
458 | unsigned *Limit, |
||
459 | BatchAAResults &BatchAA); |
||
460 | |||
461 | MemDepResult |
||
462 | getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad, |
||
463 | BasicBlock::iterator ScanIt, BasicBlock *BB, |
||
464 | Instruction *QueryInst, unsigned *Limit, |
||
465 | BatchAAResults &BatchAA); |
||
466 | |||
467 | /// This analysis looks for other loads and stores with invariant.group |
||
468 | /// metadata and the same pointer operand. Returns Unknown if it does not |
||
469 | /// find anything, and Def if it can be assumed that 2 instructions load or |
||
470 | /// store the same value and NonLocal which indicate that non-local Def was |
||
471 | /// found, which can be retrieved by calling getNonLocalPointerDependency |
||
472 | /// with the same queried instruction. |
||
473 | MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB); |
||
474 | |||
475 | /// Release memory in caches. |
||
476 | void releaseMemory(); |
||
477 | |||
478 | /// Return the clobber offset to dependent instruction. |
||
479 | std::optional<int32_t> getClobberOffset(LoadInst *DepInst) const { |
||
480 | const auto Off = ClobberOffsets.find(DepInst); |
||
481 | if (Off != ClobberOffsets.end()) |
||
482 | return Off->getSecond(); |
||
483 | return std::nullopt; |
||
484 | } |
||
485 | |||
486 | private: |
||
487 | MemDepResult getCallDependencyFrom(CallBase *Call, bool isReadOnlyCall, |
||
488 | BasicBlock::iterator ScanIt, |
||
489 | BasicBlock *BB); |
||
490 | bool getNonLocalPointerDepFromBB(Instruction *QueryInst, |
||
491 | const PHITransAddr &Pointer, |
||
492 | const MemoryLocation &Loc, bool isLoad, |
||
493 | BasicBlock *BB, |
||
494 | SmallVectorImpl<NonLocalDepResult> &Result, |
||
495 | DenseMap<BasicBlock *, Value *> &Visited, |
||
496 | bool SkipFirstBlock = false, |
||
497 | bool IsIncomplete = false); |
||
498 | MemDepResult getNonLocalInfoForBlock(Instruction *QueryInst, |
||
499 | const MemoryLocation &Loc, bool isLoad, |
||
500 | BasicBlock *BB, NonLocalDepInfo *Cache, |
||
501 | unsigned NumSortedEntries, |
||
502 | BatchAAResults &BatchAA); |
||
503 | |||
504 | void removeCachedNonLocalPointerDependencies(ValueIsLoadPair P); |
||
505 | |||
506 | void verifyRemoved(Instruction *Inst) const; |
||
507 | }; |
||
508 | |||
509 | /// An analysis that produces \c MemoryDependenceResults for a function. |
||
510 | /// |
||
511 | /// This is essentially a no-op because the results are computed entirely |
||
512 | /// lazily. |
||
513 | class MemoryDependenceAnalysis |
||
514 | : public AnalysisInfoMixin<MemoryDependenceAnalysis> { |
||
515 | friend AnalysisInfoMixin<MemoryDependenceAnalysis>; |
||
516 | |||
517 | static AnalysisKey Key; |
||
518 | |||
519 | unsigned DefaultBlockScanLimit; |
||
520 | |||
521 | public: |
||
522 | using Result = MemoryDependenceResults; |
||
523 | |||
524 | MemoryDependenceAnalysis(); |
||
525 | MemoryDependenceAnalysis(unsigned DefaultBlockScanLimit) : DefaultBlockScanLimit(DefaultBlockScanLimit) { } |
||
526 | |||
527 | MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM); |
||
528 | }; |
||
529 | |||
530 | /// A wrapper analysis pass for the legacy pass manager that exposes a \c |
||
531 | /// MemoryDepnedenceResults instance. |
||
532 | class MemoryDependenceWrapperPass : public FunctionPass { |
||
533 | std::optional<MemoryDependenceResults> MemDep; |
||
534 | |||
535 | public: |
||
536 | static char ID; |
||
537 | |||
538 | MemoryDependenceWrapperPass(); |
||
539 | ~MemoryDependenceWrapperPass() override; |
||
540 | |||
541 | /// Pass Implementation stuff. This doesn't do any analysis eagerly. |
||
542 | bool runOnFunction(Function &) override; |
||
543 | |||
544 | /// Clean up memory in between runs |
||
545 | void releaseMemory() override; |
||
546 | |||
547 | /// Does not modify anything. It uses Value Numbering and Alias Analysis. |
||
548 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
||
549 | |||
550 | MemoryDependenceResults &getMemDep() { return *MemDep; } |
||
551 | }; |
||
552 | |||
553 | } // end namespace llvm |
||
554 | |||
555 | #endif // LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H |