AliasSetTracker.h revision 235fc57ef2ed0a3c43a6e2d77b7c13f96a6f8036
1//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines two classes: AliasSetTracker and AliasSet.  These interface
11// are used to classify a collection of pointer references into a maximal number
12// of disjoint sets.  Each AliasSet object constructed by the AliasSetTracker
13// object refers to memory disjoint from the other sets.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
18#define LLVM_ANALYSIS_ALIASSETTRACKER_H
19
20#include "llvm/Support/CallSite.h"
21#include "llvm/Support/Streams.h"
22#include "llvm/ADT/iterator"
23#include "llvm/ADT/hash_map"
24#include "llvm/ADT/ilist"
25
26namespace llvm {
27
28class AliasAnalysis;
29class LoadInst;
30class StoreInst;
31class FreeInst;
32class VAArgInst;
33class AliasSetTracker;
34class AliasSet;
35
36class AliasSet {
37  friend class AliasSetTracker;
38
39  class PointerRec;
40  typedef std::pair<Value* const, PointerRec> HashNodePair;
41
42  class PointerRec {
43    HashNodePair **PrevInList, *NextInList;
44    AliasSet *AS;
45    unsigned Size;
46  public:
47    PointerRec() : PrevInList(0), NextInList(0), AS(0), Size(0) {}
48
49    HashNodePair *getNext() const { return NextInList; }
50    bool hasAliasSet() const { return AS != 0; }
51
52    HashNodePair** setPrevInList(HashNodePair **PIL) {
53      PrevInList = PIL;
54      return &NextInList;
55    }
56
57    void updateSize(unsigned NewSize) {
58      if (NewSize > Size) Size = NewSize;
59    }
60
61    unsigned getSize() const { return Size; }
62
63    AliasSet *getAliasSet(AliasSetTracker &AST) {
64      assert(AS && "No AliasSet yet!");
65      if (AS->Forward) {
66        AliasSet *OldAS = AS;
67        AS = OldAS->getForwardedTarget(AST);
68        AS->addRef();
69        OldAS->dropRef(AST);
70      }
71      return AS;
72    }
73
74    void setAliasSet(AliasSet *as) {
75      assert(AS == 0 && "Already have an alias set!");
76      AS = as;
77    }
78
79    void removeFromList() {
80      if (NextInList) NextInList->second.PrevInList = PrevInList;
81      *PrevInList = NextInList;
82      if (AS->PtrListEnd == &NextInList) {
83        AS->PtrListEnd = PrevInList;
84        assert(*AS->PtrListEnd == 0 && "List not terminated right!");
85      }
86    }
87  };
88
89  HashNodePair *PtrList, **PtrListEnd;  // Doubly linked list of nodes
90  AliasSet *Forward;             // Forwarding pointer
91  AliasSet *Next, *Prev;         // Doubly linked list of AliasSets
92
93  std::vector<CallSite> CallSites; // All calls & invokes in this node
94
95  // RefCount - Number of nodes pointing to this AliasSet plus the number of
96  // AliasSets forwarding to it.
97  unsigned RefCount : 28;
98
99  /// AccessType - Keep track of whether this alias set merely refers to the
100  /// locations of memory, whether it modifies the memory, or whether it does
101  /// both.  The lattice goes from "NoModRef" to either Refs or Mods, then to
102  /// ModRef as necessary.
103  ///
104  enum AccessType {
105    NoModRef = 0, Refs = 1,         // Ref = bit 1
106    Mods     = 2, ModRef = 3        // Mod = bit 2
107  };
108  unsigned AccessTy : 2;
109
110  /// AliasType - Keep track the relationships between the pointers in the set.
111  /// Lattice goes from MustAlias to MayAlias.
112  ///
113  enum AliasType {
114    MustAlias = 0, MayAlias = 1
115  };
116  unsigned AliasTy : 1;
117
118  // Volatile - True if this alias set contains volatile loads or stores.
119  bool Volatile : 1;
120
121  friend struct ilist_traits<AliasSet>;
122  AliasSet *getPrev() const { return Prev; }
123  AliasSet *getNext() const { return Next; }
124  void setPrev(AliasSet *P) { Prev = P; }
125  void setNext(AliasSet *N) { Next = N; }
126
127  void addRef() { ++RefCount; }
128  void dropRef(AliasSetTracker &AST) {
129    assert(RefCount >= 1 && "Invalid reference count detected!");
130    if (--RefCount == 0)
131      removeFromTracker(AST);
132  }
133
134public:
135  /// Accessors...
136  bool isRef() const { return AccessTy & Refs; }
137  bool isMod() const { return AccessTy & Mods; }
138  bool isMustAlias() const { return AliasTy == MustAlias; }
139  bool isMayAlias()  const { return AliasTy == MayAlias; }
140
141  // isVolatile - Return true if this alias set contains volatile loads or
142  // stores.
143  bool isVolatile() const { return Volatile; }
144
145  /// isForwardingAliasSet - Return true if this alias set should be ignored as
146  /// part of the AliasSetTracker object.
147  bool isForwardingAliasSet() const { return Forward; }
148
149  /// mergeSetIn - Merge the specified alias set into this alias set...
150  ///
151  void mergeSetIn(AliasSet &AS, AliasSetTracker &AST);
152
153  // Alias Set iteration - Allow access to all of the pointer which are part of
154  // this alias set...
155  class iterator;
156  iterator begin() const { return iterator(PtrList); }
157  iterator end()   const { return iterator(); }
158  bool empty() const { return PtrList == 0; }
159
160  void print(std::ostream &OS) const;
161  void print(std::ostream *OS) const { if (OS) print(*OS); }
162  void dump() const;
163
164  /// Define an iterator for alias sets... this is just a forward iterator.
165  class iterator : public forward_iterator<HashNodePair, ptrdiff_t> {
166    HashNodePair *CurNode;
167  public:
168    explicit iterator(HashNodePair *CN = 0) : CurNode(CN) {}
169
170    bool operator==(const iterator& x) const {
171      return CurNode == x.CurNode;
172    }
173    bool operator!=(const iterator& x) const { return !operator==(x); }
174
175    const iterator &operator=(const iterator &I) {
176      CurNode = I.CurNode;
177      return *this;
178    }
179
180    value_type &operator*() const {
181      assert(CurNode && "Dereferencing AliasSet.end()!");
182      return *CurNode;
183    }
184    value_type *operator->() const { return &operator*(); }
185
186    Value *getPointer() const { return CurNode->first; }
187    unsigned getSize() const { return CurNode->second.getSize(); }
188
189    iterator& operator++() {                // Preincrement
190      assert(CurNode && "Advancing past AliasSet.end()!");
191      CurNode = CurNode->second.getNext();
192      return *this;
193    }
194    iterator operator++(int) { // Postincrement
195      iterator tmp = *this; ++*this; return tmp;
196    }
197  };
198
199private:
200  // Can only be created by AliasSetTracker
201  AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0),
202               AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
203  }
204
205  AliasSet(const AliasSet &AS) {
206    assert(0 && "Copy ctor called!?!?!");
207    abort();
208  }
209
210  HashNodePair *getSomePointer() const {
211    return PtrList;
212  }
213
214  /// getForwardedTarget - Return the real alias set this represents.  If this
215  /// has been merged with another set and is forwarding, return the ultimate
216  /// destination set.  This also implements the union-find collapsing as well.
217  AliasSet *getForwardedTarget(AliasSetTracker &AST) {
218    if (!Forward) return this;
219
220    AliasSet *Dest = Forward->getForwardedTarget(AST);
221    if (Dest != Forward) {
222      Dest->addRef();
223      Forward->dropRef(AST);
224      Forward = Dest;
225    }
226    return Dest;
227  }
228
229  void removeFromTracker(AliasSetTracker &AST);
230
231  void addPointer(AliasSetTracker &AST, HashNodePair &Entry, unsigned Size,
232                  bool KnownMustAlias = false);
233  void addCallSite(CallSite CS, AliasAnalysis &AA);
234  void removeCallSite(CallSite CS) {
235    for (unsigned i = 0, e = CallSites.size(); i != e; ++i)
236      if (CallSites[i].getInstruction() == CS.getInstruction()) {
237        CallSites[i] = CallSites.back();
238        CallSites.pop_back();
239      }
240  }
241  void setVolatile() { Volatile = true; }
242
243  /// aliasesPointer - Return true if the specified pointer "may" (or must)
244  /// alias one of the members in the set.
245  ///
246  bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const;
247  bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const;
248};
249
250inline std::ostream& operator<<(std::ostream &OS, const AliasSet &AS) {
251  AS.print(OS);
252  return OS;
253}
254
255
256class AliasSetTracker {
257  AliasAnalysis &AA;
258  ilist<AliasSet> AliasSets;
259
260  // Map from pointers to their node
261  hash_map<Value*, AliasSet::PointerRec> PointerMap;
262public:
263  /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
264  /// the specified alias analysis object to disambiguate load and store
265  /// addresses.
266  explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {}
267  ~AliasSetTracker() { clear(); }
268
269  /// add methods - These methods are used to add different types of
270  /// instructions to the alias sets.  Adding a new instruction can result in
271  /// one of three actions happening:
272  ///
273  ///   1. If the instruction doesn't alias any other sets, create a new set.
274  ///   2. If the instruction aliases exactly one set, add it to the set
275  ///   3. If the instruction aliases multiple sets, merge the sets, and add
276  ///      the instruction to the result.
277  ///
278  /// These methods return true if inserting the instruction resulted in the
279  /// addition of a new alias set (i.e., the pointer did not alias anything).
280  ///
281  bool add(Value *Ptr, unsigned Size);  // Add a location
282  bool add(LoadInst *LI);
283  bool add(StoreInst *SI);
284  bool add(FreeInst *FI);
285  bool add(VAArgInst *VAAI);
286  bool add(CallSite CS);          // Call/Invoke instructions
287  bool add(CallInst *CI)   { return add(CallSite(CI)); }
288  bool add(InvokeInst *II) { return add(CallSite(II)); }
289  bool add(Instruction *I);       // Dispatch to one of the other add methods...
290  void add(BasicBlock &BB);       // Add all instructions in basic block
291  void add(const AliasSetTracker &AST); // Add alias relations from another AST
292
293  /// remove methods - These methods are used to remove all entries that might
294  /// be aliased by the specified instruction.  These methods return true if any
295  /// alias sets were eliminated.
296  bool remove(Value *Ptr, unsigned Size);  // Remove a location
297  bool remove(LoadInst *LI);
298  bool remove(StoreInst *SI);
299  bool remove(FreeInst *FI);
300  bool remove(VAArgInst *VAAI);
301  bool remove(CallSite CS);
302  bool remove(CallInst *CI)   { return remove(CallSite(CI)); }
303  bool remove(InvokeInst *II) { return remove(CallSite(II)); }
304  bool remove(Instruction *I);
305  void remove(AliasSet &AS);
306
307  void clear() {
308    PointerMap.clear();
309    AliasSets.clear();
310  }
311
312  /// getAliasSets - Return the alias sets that are active.
313  ///
314  const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
315
316  /// getAliasSetForPointer - Return the alias set that the specified pointer
317  /// lives in.  If the New argument is non-null, this method sets the value to
318  /// true if a new alias set is created to contain the pointer (because the
319  /// pointer didn't alias anything).
320  AliasSet &getAliasSetForPointer(Value *P, unsigned Size, bool *New = 0);
321
322  /// getAliasSetForPointerIfExists - Return the alias set containing the
323  /// location specified if one exists, otherwise return null.
324  AliasSet *getAliasSetForPointerIfExists(Value *P, unsigned Size) {
325    return findAliasSetForPointer(P, Size);
326  }
327
328  /// containsPointer - Return true if the specified location is represented by
329  /// this alias set, false otherwise.  This does not modify the AST object or
330  /// alias sets.
331  bool containsPointer(Value *P, unsigned Size) const;
332
333  /// getAliasAnalysis - Return the underlying alias analysis object used by
334  /// this tracker.
335  AliasAnalysis &getAliasAnalysis() const { return AA; }
336
337  /// deleteValue method - This method is used to remove a pointer value from
338  /// the AliasSetTracker entirely.  It should be used when an instruction is
339  /// deleted from the program to update the AST.  If you don't use this, you
340  /// would have dangling pointers to deleted instructions.
341  ///
342  void deleteValue(Value *PtrVal);
343
344  /// copyValue - This method should be used whenever a preexisting value in the
345  /// program is copied or cloned, introducing a new value.  Note that it is ok
346  /// for clients that use this method to introduce the same value multiple
347  /// times: if the tracker already knows about a value, it will ignore the
348  /// request.
349  ///
350  void copyValue(Value *From, Value *To);
351
352
353  typedef ilist<AliasSet>::iterator iterator;
354  typedef ilist<AliasSet>::const_iterator const_iterator;
355
356  const_iterator begin() const { return AliasSets.begin(); }
357  const_iterator end()   const { return AliasSets.end(); }
358
359  iterator begin() { return AliasSets.begin(); }
360  iterator end()   { return AliasSets.end(); }
361
362  void print(std::ostream &OS) const;
363  void print(std::ostream *OS) const { if (OS) print(*OS); }
364  void dump() const;
365
366private:
367  friend class AliasSet;
368  void removeAliasSet(AliasSet *AS);
369
370  AliasSet::HashNodePair &getEntryFor(Value *V) {
371    // Standard operator[], except that it returns the whole pair, not just
372    // ->second.
373    return *PointerMap.insert(AliasSet::HashNodePair(V,
374                                            AliasSet::PointerRec())).first;
375  }
376
377  AliasSet &addPointer(Value *P, unsigned Size, AliasSet::AccessType E,
378                       bool &NewSet) {
379    NewSet = false;
380    AliasSet &AS = getAliasSetForPointer(P, Size, &NewSet);
381    AS.AccessTy |= E;
382    return AS;
383  }
384  AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size);
385
386  AliasSet *findAliasSetForCallSite(CallSite CS);
387};
388
389inline std::ostream& operator<<(std::ostream &OS, const AliasSetTracker &AST) {
390  AST.print(OS);
391  return OS;
392}
393
394} // End llvm namespace
395
396#endif
397