1 //===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- 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 defines two classes: AliasSetTracker and AliasSet. These interfaces
10 // are used to classify a collection of pointer references into a maximal number
11 // of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
12 // object refers to memory disjoint from the other sets.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
17 #define LLVM_ANALYSIS_ALIASSETTRACKER_H
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/DenseMapInfo.h"
21 #include "llvm/ADT/ilist.h"
22 #include "llvm/ADT/ilist_node.h"
23 #include "llvm/Analysis/AliasAnalysis.h"
24 #include "llvm/IR/Instruction.h"
25 #include "llvm/IR/Metadata.h"
26 #include "llvm/IR/ValueHandle.h"
27 #include "llvm/Support/Casting.h"
36 class AliasSetTracker
;
42 class AnyMemTransferInst
;
48 class AliasSet
: public ilist_node
<AliasSet
> {
49 friend class AliasSetTracker
;
52 Value
*Val
; // The pointer this record corresponds to.
53 PointerRec
**PrevInList
= nullptr;
54 PointerRec
*NextInList
= nullptr;
55 AliasSet
*AS
= nullptr;
56 LocationSize Size
= LocationSize::mapEmpty();
59 // Whether the size for this record has been set at all. This makes no
60 // guarantees about the size being known.
61 bool isSizeSet() const { return Size
!= LocationSize::mapEmpty(); }
65 : Val(V
), AAInfo(DenseMapInfo
<AAMDNodes
>::getEmptyKey()) {}
67 Value
*getValue() const { return Val
; }
69 PointerRec
*getNext() const { return NextInList
; }
70 bool hasAliasSet() const { return AS
!= nullptr; }
72 PointerRec
** setPrevInList(PointerRec
**PIL
) {
77 bool updateSizeAndAAInfo(LocationSize NewSize
, const AAMDNodes
&NewAAInfo
) {
78 bool SizeChanged
= false;
79 if (NewSize
!= Size
) {
80 LocationSize OldSize
= Size
;
81 Size
= isSizeSet() ? Size
.unionWith(NewSize
) : NewSize
;
82 SizeChanged
= OldSize
!= Size
;
85 if (AAInfo
== DenseMapInfo
<AAMDNodes
>::getEmptyKey())
86 // We don't have a AAInfo yet. Set it to NewAAInfo.
89 AAMDNodes
Intersection(AAInfo
.intersect(NewAAInfo
));
90 if (!Intersection
.TBAA
|| !Intersection
.Scope
||
91 !Intersection
.NoAlias
) {
92 // NewAAInfo conflicts with AAInfo.
93 AAInfo
= DenseMapInfo
<AAMDNodes
>::getTombstoneKey();
96 AAInfo
= Intersection
;
101 LocationSize
getSize() const {
102 assert(isSizeSet() && "Getting an unset size!");
106 /// Return the AAInfo, or null if there is no information or conflicting
108 AAMDNodes
getAAInfo() const {
109 // If we have missing or conflicting AAInfo, return null.
110 if (AAInfo
== DenseMapInfo
<AAMDNodes
>::getEmptyKey() ||
111 AAInfo
== DenseMapInfo
<AAMDNodes
>::getTombstoneKey())
116 AliasSet
*getAliasSet(AliasSetTracker
&AST
) {
117 assert(AS
&& "No AliasSet yet!");
119 AliasSet
*OldAS
= AS
;
120 AS
= OldAS
->getForwardedTarget(AST
);
127 void setAliasSet(AliasSet
*as
) {
128 assert(!AS
&& "Already have an alias set!");
132 void eraseFromList() {
133 if (NextInList
) NextInList
->PrevInList
= PrevInList
;
134 *PrevInList
= NextInList
;
135 if (AS
->PtrListEnd
== &NextInList
) {
136 AS
->PtrListEnd
= PrevInList
;
137 assert(*AS
->PtrListEnd
== nullptr && "List not terminated right!");
143 // Doubly linked list of nodes.
144 PointerRec
*PtrList
= nullptr;
145 PointerRec
**PtrListEnd
;
146 // Forwarding pointer.
147 AliasSet
*Forward
= nullptr;
149 /// All instructions without a specific address in this alias set.
150 /// In rare cases this vector can have a null'ed out WeakVH
151 /// instances (can happen if some other loop pass deletes an
152 /// instruction in this list).
153 std::vector
<WeakVH
> UnknownInsts
;
155 /// Number of nodes pointing to this AliasSet plus the number of AliasSets
156 /// forwarding to it.
157 unsigned RefCount
: 27;
159 // Signifies that this set should be considered to alias any pointer.
160 // Use when the tracker holding this set is saturated.
161 unsigned AliasAny
: 1;
163 /// The kinds of access this alias set models.
165 /// We keep track of whether this alias set merely refers to the locations of
166 /// memory (and not any particular access), whether it modifies or references
167 /// the memory, or whether it does both. The lattice goes from "NoAccess" to
168 /// either RefAccess or ModAccess, then to ModRefAccess as necessary.
173 ModRefAccess
= RefAccess
| ModAccess
177 /// The kind of alias relationship between pointers of the set.
179 /// These represent conservatively correct alias results between any members
180 /// of the set. We represent these independently of the values of alias
181 /// results in order to pack it into a single bit. Lattice goes from
182 /// MustAlias to MayAlias.
184 SetMustAlias
= 0, SetMayAlias
= 1
188 unsigned SetSize
= 0;
190 void addRef() { ++RefCount
; }
192 void dropRef(AliasSetTracker
&AST
) {
193 assert(RefCount
>= 1 && "Invalid reference count detected!");
195 removeFromTracker(AST
);
198 Instruction
*getUnknownInst(unsigned i
) const {
199 assert(i
< UnknownInsts
.size());
200 return cast_or_null
<Instruction
>(UnknownInsts
[i
]);
204 AliasSet(const AliasSet
&) = delete;
205 AliasSet
&operator=(const AliasSet
&) = delete;
208 bool isRef() const { return Access
& RefAccess
; }
209 bool isMod() const { return Access
& ModAccess
; }
210 bool isMustAlias() const { return Alias
== SetMustAlias
; }
211 bool isMayAlias() const { return Alias
== SetMayAlias
; }
213 /// Return true if this alias set should be ignored as part of the
214 /// AliasSetTracker object.
215 bool isForwardingAliasSet() const { return Forward
; }
217 /// Merge the specified alias set into this alias set.
218 void mergeSetIn(AliasSet
&AS
, AliasSetTracker
&AST
);
220 // Alias Set iteration - Allow access to all of the pointers which are part of
223 iterator
begin() const { return iterator(PtrList
); }
224 iterator
end() const { return iterator(); }
225 bool empty() const { return PtrList
== nullptr; }
227 // Unfortunately, ilist::size() is linear, so we have to add code to keep
228 // track of the list's exact size.
229 unsigned size() { return SetSize
; }
231 /// If this alias set is known to contain a single instruction and *only* a
232 /// single unique instruction, return it. Otherwise, return nullptr.
233 Instruction
* getUniqueInstruction();
235 void print(raw_ostream
&OS
) const;
238 /// Define an iterator for alias sets... this is just a forward iterator.
239 class iterator
: public std::iterator
<std::forward_iterator_tag
,
240 PointerRec
, ptrdiff_t> {
244 explicit iterator(PointerRec
*CN
= nullptr) : CurNode(CN
) {}
246 bool operator==(const iterator
& x
) const {
247 return CurNode
== x
.CurNode
;
249 bool operator!=(const iterator
& x
) const { return !operator==(x
); }
251 value_type
&operator*() const {
252 assert(CurNode
&& "Dereferencing AliasSet.end()!");
255 value_type
*operator->() const { return &operator*(); }
257 Value
*getPointer() const { return CurNode
->getValue(); }
258 LocationSize
getSize() const { return CurNode
->getSize(); }
259 AAMDNodes
getAAInfo() const { return CurNode
->getAAInfo(); }
261 iterator
& operator++() { // Preincrement
262 assert(CurNode
&& "Advancing past AliasSet.end()!");
263 CurNode
= CurNode
->getNext();
266 iterator
operator++(int) { // Postincrement
267 iterator tmp
= *this; ++*this; return tmp
;
272 // Can only be created by AliasSetTracker.
274 : PtrListEnd(&PtrList
), RefCount(0), AliasAny(false), Access(NoAccess
),
275 Alias(SetMustAlias
) {}
277 PointerRec
*getSomePointer() const {
281 /// Return the real alias set this represents. If this has been merged with
282 /// another set and is forwarding, return the ultimate destination set. This
283 /// also implements the union-find collapsing as well.
284 AliasSet
*getForwardedTarget(AliasSetTracker
&AST
) {
285 if (!Forward
) return this;
287 AliasSet
*Dest
= Forward
->getForwardedTarget(AST
);
288 if (Dest
!= Forward
) {
290 Forward
->dropRef(AST
);
296 void removeFromTracker(AliasSetTracker
&AST
);
298 void addPointer(AliasSetTracker
&AST
, PointerRec
&Entry
, LocationSize Size
,
299 const AAMDNodes
&AAInfo
, bool KnownMustAlias
= false,
300 bool SkipSizeUpdate
= false);
301 void addUnknownInst(Instruction
*I
, AliasAnalysis
&AA
);
303 void removeUnknownInst(AliasSetTracker
&AST
, Instruction
*I
) {
304 bool WasEmpty
= UnknownInsts
.empty();
305 for (size_t i
= 0, e
= UnknownInsts
.size(); i
!= e
; ++i
)
306 if (UnknownInsts
[i
] == I
) {
307 UnknownInsts
[i
] = UnknownInsts
.back();
308 UnknownInsts
.pop_back();
309 --i
; --e
; // Revisit the moved entry.
311 if (!WasEmpty
&& UnknownInsts
.empty())
316 /// If the specified pointer "may" (or must) alias one of the members in the
317 /// set return the appropriate AliasResult. Otherwise return NoAlias.
318 AliasResult
aliasesPointer(const Value
*Ptr
, LocationSize Size
,
319 const AAMDNodes
&AAInfo
, AliasAnalysis
&AA
) const;
320 bool aliasesUnknownInst(const Instruction
*Inst
, AliasAnalysis
&AA
) const;
323 inline raw_ostream
& operator<<(raw_ostream
&OS
, const AliasSet
&AS
) {
328 class AliasSetTracker
{
329 /// A CallbackVH to arrange for AliasSetTracker to be notified whenever a
330 /// Value is deleted.
331 class ASTCallbackVH final
: public CallbackVH
{
332 AliasSetTracker
*AST
;
334 void deleted() override
;
335 void allUsesReplacedWith(Value
*) override
;
338 ASTCallbackVH(Value
*V
, AliasSetTracker
*AST
= nullptr);
340 ASTCallbackVH
&operator=(Value
*V
);
342 /// Traits to tell DenseMap that tell us how to compare and hash the value
344 struct ASTCallbackVHDenseMapInfo
: public DenseMapInfo
<Value
*> {};
349 ilist
<AliasSet
> AliasSets
;
351 using PointerMapType
= DenseMap
<ASTCallbackVH
, AliasSet::PointerRec
*,
352 ASTCallbackVHDenseMapInfo
>;
354 // Map from pointers to their node
355 PointerMapType PointerMap
;
358 /// Create an empty collection of AliasSets, and use the specified alias
359 /// analysis object to disambiguate load and store addresses.
360 explicit AliasSetTracker(AliasAnalysis
&aa
) : AA(aa
) {}
361 explicit AliasSetTracker(AliasAnalysis
&aa
, MemorySSA
*mssa
, Loop
*l
)
362 : AA(aa
), MSSA(mssa
), L(l
) {}
363 ~AliasSetTracker() { clear(); }
365 /// These methods are used to add different types of instructions to the alias
366 /// sets. Adding a new instruction can result in one of three actions
369 /// 1. If the instruction doesn't alias any other sets, create a new set.
370 /// 2. If the instruction aliases exactly one set, add it to the set
371 /// 3. If the instruction aliases multiple sets, merge the sets, and add
372 /// the instruction to the result.
374 /// These methods return true if inserting the instruction resulted in the
375 /// addition of a new alias set (i.e., the pointer did not alias anything).
377 void add(Value
*Ptr
, LocationSize Size
, const AAMDNodes
&AAInfo
); // Add a loc
378 void add(LoadInst
*LI
);
379 void add(StoreInst
*SI
);
380 void add(VAArgInst
*VAAI
);
381 void add(AnyMemSetInst
*MSI
);
382 void add(AnyMemTransferInst
*MTI
);
383 void add(Instruction
*I
); // Dispatch to one of the other add methods...
384 void add(BasicBlock
&BB
); // Add all instructions in basic block
385 void add(const AliasSetTracker
&AST
); // Add alias relations from another AST
386 void addUnknown(Instruction
*I
);
387 void addAllInstructionsInLoopUsingMSSA();
391 /// Return the alias sets that are active.
392 const ilist
<AliasSet
> &getAliasSets() const { return AliasSets
; }
394 /// Return the alias set which contains the specified memory location. If
395 /// the memory location aliases two or more existing alias sets, will have
396 /// the effect of merging those alias sets before the single resulting alias
398 AliasSet
&getAliasSetFor(const MemoryLocation
&MemLoc
);
400 /// Return the underlying alias analysis object used by this tracker.
401 AliasAnalysis
&getAliasAnalysis() const { return AA
; }
403 /// This method is used to remove a pointer value from the AliasSetTracker
404 /// entirely. It should be used when an instruction is deleted from the
405 /// program to update the AST. If you don't use this, you would have dangling
406 /// pointers to deleted instructions.
407 void deleteValue(Value
*PtrVal
);
409 /// This method should be used whenever a preexisting value in the program is
410 /// copied or cloned, introducing a new value. Note that it is ok for clients
411 /// that use this method to introduce the same value multiple times: if the
412 /// tracker already knows about a value, it will ignore the request.
413 void copyValue(Value
*From
, Value
*To
);
415 using iterator
= ilist
<AliasSet
>::iterator
;
416 using const_iterator
= ilist
<AliasSet
>::const_iterator
;
418 const_iterator
begin() const { return AliasSets
.begin(); }
419 const_iterator
end() const { return AliasSets
.end(); }
421 iterator
begin() { return AliasSets
.begin(); }
422 iterator
end() { return AliasSets
.end(); }
424 void print(raw_ostream
&OS
) const;
428 friend class AliasSet
;
430 // The total number of pointers contained in all "may" alias sets.
431 unsigned TotalMayAliasSetSize
= 0;
433 // A non-null value signifies this AST is saturated. A saturated AST lumps
434 // all pointers into a single "May" set.
435 AliasSet
*AliasAnyAS
= nullptr;
437 void removeAliasSet(AliasSet
*AS
);
439 /// Just like operator[] on the map, except that it creates an entry for the
440 /// pointer if it doesn't already exist.
441 AliasSet::PointerRec
&getEntryFor(Value
*V
) {
442 AliasSet::PointerRec
*&Entry
= PointerMap
[ASTCallbackVH(V
, this)];
444 Entry
= new AliasSet::PointerRec(V
);
448 AliasSet
&addPointer(MemoryLocation Loc
, AliasSet::AccessLattice E
);
449 AliasSet
*mergeAliasSetsForPointer(const Value
*Ptr
, LocationSize Size
,
450 const AAMDNodes
&AAInfo
,
453 /// Merge all alias sets into a single set that is considered to alias any
455 AliasSet
&mergeAllAliasSets();
457 AliasSet
*findAliasSetForUnknownInst(Instruction
*Inst
);
460 inline raw_ostream
& operator<<(raw_ostream
&OS
, const AliasSetTracker
&AST
) {
465 } // end namespace llvm
467 #endif // LLVM_ANALYSIS_ALIASSETTRACKER_H