Skip to content

Commit 656bf13

Browse files
authored
[AST] Don't merge memory locations in AliasSetTracker (#65731)
This changes the AliasSetTracker to track memory locations instead of pointers in its alias sets. The motivation for this is outlined in an RFC posted on LLVM discourse: https://discourse.llvm.org/t/rfc-dont-merge-memory-locations-in-aliassettracker/73336 In the data structures of the AST implementation, I made the choice to replace the linked list of `PointerRec` entries (that had to go anyway) with a simple flat vector of `MemoryLocation` objects, but for the `AliasSet` objects referenced from a lookup table, I retained the mechanism of a linked list, reference counting, forwarding, etc. The data structures could be revised in a follow-up change.
1 parent 8fb685f commit 656bf13

16 files changed

+488
-688
lines changed

llvm/include/llvm/Analysis/AliasSetTracker.h

Lines changed: 52 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
//
99
// This file defines two classes: AliasSetTracker and AliasSet. These interfaces
10-
// are used to classify a collection of pointer references into a maximal number
10+
// are used to classify a collection of memory locations into a maximal number
1111
// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
1212
// object refers to memory disjoint from the other sets.
1313
//
@@ -19,16 +19,14 @@
1919
#define LLVM_ANALYSIS_ALIASSETTRACKER_H
2020

2121
#include "llvm/ADT/DenseMap.h"
22-
#include "llvm/ADT/DenseMapInfo.h"
22+
#include "llvm/ADT/SmallVector.h"
2323
#include "llvm/ADT/ilist.h"
2424
#include "llvm/ADT/ilist_node.h"
2525
#include "llvm/Analysis/MemoryLocation.h"
2626
#include "llvm/IR/Instruction.h"
2727
#include "llvm/IR/PassManager.h"
2828
#include "llvm/IR/ValueHandle.h"
2929
#include <cassert>
30-
#include <cstddef>
31-
#include <iterator>
3230
#include <vector>
3331

3432
namespace llvm {
@@ -49,99 +47,12 @@ class Value;
4947
class AliasSet : public ilist_node<AliasSet> {
5048
friend class AliasSetTracker;
5149

52-
class PointerRec {
53-
Value *Val; // The pointer this record corresponds to.
54-
PointerRec **PrevInList = nullptr;
55-
PointerRec *NextInList = nullptr;
56-
AliasSet *AS = nullptr;
57-
LocationSize Size = LocationSize::mapEmpty();
58-
AAMDNodes AAInfo;
59-
60-
// Whether the size for this record has been set at all. This makes no
61-
// guarantees about the size being known.
62-
bool isSizeSet() const { return Size != LocationSize::mapEmpty(); }
63-
64-
public:
65-
PointerRec(Value *V)
66-
: Val(V), AAInfo(DenseMapInfo<AAMDNodes>::getEmptyKey()) {}
67-
68-
Value *getValue() const { return Val; }
69-
70-
PointerRec *getNext() const { return NextInList; }
71-
bool hasAliasSet() const { return AS != nullptr; }
72-
73-
PointerRec** setPrevInList(PointerRec **PIL) {
74-
PrevInList = PIL;
75-
return &NextInList;
76-
}
77-
78-
bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) {
79-
bool SizeChanged = false;
80-
if (NewSize != Size) {
81-
LocationSize OldSize = Size;
82-
Size = isSizeSet() ? Size.unionWith(NewSize) : NewSize;
83-
SizeChanged = OldSize != Size;
84-
}
85-
86-
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
87-
// We don't have a AAInfo yet. Set it to NewAAInfo.
88-
AAInfo = NewAAInfo;
89-
else {
90-
AAMDNodes Intersection(AAInfo.intersect(NewAAInfo));
91-
SizeChanged |= Intersection != AAInfo;
92-
AAInfo = Intersection;
93-
}
94-
return SizeChanged;
95-
}
96-
97-
LocationSize getSize() const {
98-
assert(isSizeSet() && "Getting an unset size!");
99-
return Size;
100-
}
101-
102-
/// Return the AAInfo, or null if there is no information or conflicting
103-
/// information.
104-
AAMDNodes getAAInfo() const {
105-
// If we have missing or conflicting AAInfo, return null.
106-
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey() ||
107-
AAInfo == DenseMapInfo<AAMDNodes>::getTombstoneKey())
108-
return AAMDNodes();
109-
return AAInfo;
110-
}
111-
112-
AliasSet *getAliasSet(AliasSetTracker &AST) {
113-
assert(AS && "No AliasSet yet!");
114-
if (AS->Forward) {
115-
AliasSet *OldAS = AS;
116-
AS = OldAS->getForwardedTarget(AST);
117-
AS->addRef();
118-
OldAS->dropRef(AST);
119-
}
120-
return AS;
121-
}
122-
123-
void setAliasSet(AliasSet *as) {
124-
assert(!AS && "Already have an alias set!");
125-
AS = as;
126-
}
127-
128-
void eraseFromList() {
129-
if (NextInList) NextInList->PrevInList = PrevInList;
130-
*PrevInList = NextInList;
131-
if (AS->PtrListEnd == &NextInList) {
132-
AS->PtrListEnd = PrevInList;
133-
assert(*AS->PtrListEnd == nullptr && "List not terminated right!");
134-
}
135-
delete this;
136-
}
137-
};
138-
139-
// Doubly linked list of nodes.
140-
PointerRec *PtrList = nullptr;
141-
PointerRec **PtrListEnd;
14250
// Forwarding pointer.
14351
AliasSet *Forward = nullptr;
14452

53+
/// Memory locations in this alias set.
54+
SmallVector<MemoryLocation, 0> MemoryLocs;
55+
14556
/// All instructions without a specific address in this alias set.
14657
std::vector<AssertingVH<Instruction>> UnknownInsts;
14758

@@ -178,8 +89,6 @@ class AliasSet : public ilist_node<AliasSet> {
17889
};
17990
unsigned Alias : 1;
18091

181-
unsigned SetSize = 0;
182-
18392
void addRef() { ++RefCount; }
18493

18594
void dropRef(AliasSetTracker &AST) {
@@ -205,95 +114,40 @@ class AliasSet : public ilist_node<AliasSet> {
205114
/// Merge the specified alias set into this alias set.
206115
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST, BatchAAResults &BatchAA);
207116

208-
// Alias Set iteration - Allow access to all of the pointers which are part of
209-
// this alias set.
210-
class iterator;
211-
iterator begin() const { return iterator(PtrList); }
212-
iterator end() const { return iterator(); }
213-
bool empty() const { return PtrList == nullptr; }
117+
// Alias Set iteration - Allow access to all of the memory locations which are
118+
// part of this alias set.
119+
using iterator = SmallVectorImpl<MemoryLocation>::const_iterator;
120+
iterator begin() const { return MemoryLocs.begin(); }
121+
iterator end() const { return MemoryLocs.end(); }
214122

215-
// Unfortunately, ilist::size() is linear, so we have to add code to keep
216-
// track of the list's exact size.
217-
unsigned size() { return SetSize; }
123+
unsigned size() { return MemoryLocs.size(); }
124+
125+
/// Retrieve the pointer values for the memory locations in this alias set.
126+
/// The order matches that of the memory locations, but duplicate pointer
127+
/// values are omitted.
128+
using PointerVector = SmallVector<const Value *, 8>;
129+
PointerVector getPointers() const;
218130

219131
void print(raw_ostream &OS) const;
220132
void dump() const;
221133

222-
/// Define an iterator for alias sets... this is just a forward iterator.
223-
class iterator {
224-
PointerRec *CurNode;
225-
226-
public:
227-
using iterator_category = std::forward_iterator_tag;
228-
using value_type = PointerRec;
229-
using difference_type = std::ptrdiff_t;
230-
using pointer = value_type *;
231-
using reference = value_type &;
232-
233-
explicit iterator(PointerRec *CN = nullptr) : CurNode(CN) {}
234-
235-
bool operator==(const iterator& x) const {
236-
return CurNode == x.CurNode;
237-
}
238-
bool operator!=(const iterator& x) const { return !operator==(x); }
239-
240-
value_type &operator*() const {
241-
assert(CurNode && "Dereferencing AliasSet.end()!");
242-
return *CurNode;
243-
}
244-
value_type *operator->() const { return &operator*(); }
245-
246-
Value *getPointer() const { return CurNode->getValue(); }
247-
LocationSize getSize() const { return CurNode->getSize(); }
248-
AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); }
249-
250-
iterator& operator++() { // Preincrement
251-
assert(CurNode && "Advancing past AliasSet.end()!");
252-
CurNode = CurNode->getNext();
253-
return *this;
254-
}
255-
iterator operator++(int) { // Postincrement
256-
iterator tmp = *this; ++*this; return tmp;
257-
}
258-
};
259-
260134
private:
261135
// Can only be created by AliasSetTracker.
262136
AliasSet()
263-
: PtrListEnd(&PtrList), RefCount(0), AliasAny(false), Access(NoAccess),
264-
Alias(SetMustAlias) {}
265-
266-
PointerRec *getSomePointer() const {
267-
return PtrList;
268-
}
269-
270-
/// Return the real alias set this represents. If this has been merged with
271-
/// another set and is forwarding, return the ultimate destination set. This
272-
/// also implements the union-find collapsing as well.
273-
AliasSet *getForwardedTarget(AliasSetTracker &AST) {
274-
if (!Forward) return this;
275-
276-
AliasSet *Dest = Forward->getForwardedTarget(AST);
277-
if (Dest != Forward) {
278-
Dest->addRef();
279-
Forward->dropRef(AST);
280-
Forward = Dest;
281-
}
282-
return Dest;
283-
}
137+
: RefCount(0), AliasAny(false), Access(NoAccess), Alias(SetMustAlias) {}
284138

285139
void removeFromTracker(AliasSetTracker &AST);
286140

287-
void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size,
288-
const AAMDNodes &AAInfo, bool KnownMustAlias = false,
289-
bool SkipSizeUpdate = false);
141+
void addMemoryLocation(AliasSetTracker &AST, const MemoryLocation &MemLoc,
142+
bool KnownMustAlias = false);
290143
void addUnknownInst(Instruction *I, BatchAAResults &AA);
291144

292145
public:
293-
/// If the specified pointer "may" (or must) alias one of the members in the
294-
/// set return the appropriate AliasResult. Otherwise return NoAlias.
295-
AliasResult aliasesPointer(const Value *Ptr, LocationSize Size,
296-
const AAMDNodes &AAInfo, BatchAAResults &AA) const;
146+
/// If the specified memory location "may" (or must) alias one of the members
147+
/// in the set return the appropriate AliasResult. Otherwise return NoAlias.
148+
AliasResult aliasesMemoryLocation(const MemoryLocation &MemLoc,
149+
BatchAAResults &AA) const;
150+
297151
ModRefInfo aliasesUnknownInst(const Instruction *Inst,
298152
BatchAAResults &AA) const;
299153
};
@@ -307,9 +161,10 @@ class AliasSetTracker {
307161
BatchAAResults &AA;
308162
ilist<AliasSet> AliasSets;
309163

310-
using PointerMapType = DenseMap<AssertingVH<Value>, AliasSet::PointerRec *>;
164+
using PointerMapType = DenseMap<AssertingVH<const Value>, AliasSet *>;
311165

312-
// Map from pointers to their node
166+
// Map from pointer values to the alias set holding one or more memory
167+
// locations with that pointer value.
313168
PointerMapType PointerMap;
314169

315170
public:
@@ -327,9 +182,6 @@ class AliasSetTracker {
327182
/// 3. If the instruction aliases multiple sets, merge the sets, and add
328183
/// the instruction to the result.
329184
///
330-
/// These methods return true if inserting the instruction resulted in the
331-
/// addition of a new alias set (i.e., the pointer did not alias anything).
332-
///
333185
void add(const MemoryLocation &Loc);
334186
void add(LoadInst *LI);
335187
void add(StoreInst *SI);
@@ -370,31 +222,39 @@ class AliasSetTracker {
370222
private:
371223
friend class AliasSet;
372224

373-
// The total number of pointers contained in all "may" alias sets.
374-
unsigned TotalMayAliasSetSize = 0;
225+
// The total number of memory locations contained in all alias sets.
226+
unsigned TotalAliasSetSize = 0;
375227

376228
// A non-null value signifies this AST is saturated. A saturated AST lumps
377-
// all pointers into a single "May" set.
229+
// all elements into a single "May" set.
378230
AliasSet *AliasAnyAS = nullptr;
379231

380232
void removeAliasSet(AliasSet *AS);
381233

382-
/// Just like operator[] on the map, except that it creates an entry for the
383-
/// pointer if it doesn't already exist.
384-
AliasSet::PointerRec &getEntryFor(Value *V) {
385-
AliasSet::PointerRec *&Entry = PointerMap[V];
386-
if (!Entry)
387-
Entry = new AliasSet::PointerRec(V);
388-
return *Entry;
234+
// Update an alias set field to point to its real destination. If the field is
235+
// pointing to a set that has been merged with another set and is forwarding,
236+
// the field is updated to point to the set obtained by following the
237+
// forwarding links. The Forward fields of intermediate alias sets are
238+
// collapsed as well, and alias set reference counts are updated to reflect
239+
// the new situation.
240+
void collapseForwardingIn(AliasSet *&AS) {
241+
if (AS->Forward) {
242+
collapseForwardingIn(AS->Forward);
243+
// Swap out AS for AS->Forward, while updating reference counts.
244+
AliasSet *NewAS = AS->Forward;
245+
NewAS->addRef();
246+
AS->dropRef(*this);
247+
AS = NewAS;
248+
}
389249
}
390250

391-
AliasSet &addPointer(MemoryLocation Loc, AliasSet::AccessLattice E);
392-
AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size,
393-
const AAMDNodes &AAInfo,
394-
bool &MustAliasAll);
251+
AliasSet &addMemoryLocation(MemoryLocation Loc, AliasSet::AccessLattice E);
252+
AliasSet *mergeAliasSetsForMemoryLocation(const MemoryLocation &MemLoc,
253+
AliasSet *PtrAS,
254+
bool &MustAliasAll);
395255

396-
/// Merge all alias sets into a single set that is considered to alias any
397-
/// pointer.
256+
/// Merge all alias sets into a single set that is considered to alias
257+
/// any memory location or instruction.
398258
AliasSet &mergeAllAliasSets();
399259

400260
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);

0 commit comments

Comments
 (0)