AliasSetTracker.h revision 3889a2cb05c36f30050941679d5fd55d45e6a3ed
1//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===//
2//
3// This file defines two classes: AliasSetTracker and AliasSet.  These interface
4// are used to classify a collection of pointer references into a maximal number
5// of disjoint sets.  Each AliasSet object constructed by the AliasSetTracker
6// object refers to memory disjoint from the other sets.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
11#define LLVM_ANALYSIS_ALIASSETTRACKER_H
12
13#include "llvm/Support/CallSite.h"
14#include "Support/iterator"
15#include "Support/hash_map"
16#include "Support/ilist"
17class AliasAnalysis;
18class LoadInst;
19class StoreInst;
20class AliasSetTracker;
21class AliasSet;
22
23class AliasSet {
24  friend class AliasSetTracker;
25
26  struct PointerRec;
27  typedef std::pair<Value* const, PointerRec> HashNodePair;
28
29  class PointerRec {
30    HashNodePair *NextInList;
31    AliasSet *AS;
32    unsigned Size;
33  public:
34    PointerRec() : NextInList(0), AS(0), Size(0) {}
35
36    HashNodePair *getNext() const { return NextInList; }
37    bool hasAliasSet() const { return AS != 0; }
38
39    void updateSize(unsigned NewSize) {
40      if (NewSize > Size) Size = NewSize;
41    }
42
43    unsigned getSize() const { return Size; }
44
45    AliasSet *getAliasSet(AliasSetTracker &AST) {
46      assert(AS && "No AliasSet yet!");
47      if (AS->Forward) {
48        AliasSet *OldAS = AS;
49        AS = OldAS->getForwardedTarget(AST);
50        if (--OldAS->RefCount == 0)
51          OldAS->removeFromTracker(AST);
52        AS->RefCount++;
53      }
54      return AS;
55    }
56
57    void setAliasSet(AliasSet *as) {
58      assert(AS == 0 && "Already have an alias set!");
59      AS = as;
60    }
61    void setTail(HashNodePair *T) {
62      assert(NextInList == 0 && "Already have tail!");
63      NextInList = T;
64    }
65  };
66
67  HashNodePair *PtrListHead, *PtrListTail; // Singly linked list of nodes
68  AliasSet *Forward;             // Forwarding pointer
69  AliasSet *Next, *Prev;         // Doubly linked list of AliasSets
70
71  std::vector<CallSite> CallSites; // All calls & invokes in this node
72
73  // RefCount - Number of nodes pointing to this AliasSet plus the number of
74  // AliasSets forwarding to it.
75  unsigned RefCount : 29;
76
77  /// AccessType - Keep track of whether this alias set merely refers to the
78  /// locations of memory, whether it modifies the memory, or whether it does
79  /// both.  The lattice goes from "NoModRef" to either Refs or Mods, then to
80  /// ModRef as neccesary.
81  ///
82  enum AccessType {
83    NoModRef = 0, Refs = 1,         // Ref = bit 1
84    Mods     = 2, ModRef = 3        // Mod = bit 2
85  };
86  unsigned AccessTy : 2;
87
88  /// AliasType - Keep track the relationships between the pointers in the set.
89  /// Lattice goes from MustAlias to MayAlias.
90  ///
91  enum AliasType {
92    MustAlias = 0, MayAlias = 1
93  };
94  unsigned AliasTy : 1;
95
96  friend class ilist_traits<AliasSet>;
97  AliasSet *getPrev() const { return Prev; }
98  AliasSet *getNext() const { return Next; }
99  void setPrev(AliasSet *P) { Prev = P; }
100  void setNext(AliasSet *N) { Next = N; }
101
102public:
103  /// Accessors...
104  bool isRef() const { return AccessTy & Refs; }
105  bool isMod() const { return AccessTy & Mods; }
106  bool isMustAlias() const { return AliasTy == MustAlias; }
107  bool isMayAlias()  const { return AliasTy == MayAlias; }
108
109  /// isForwardingAliasSet - Return true if this alias set should be ignored as
110  /// part of the AliasSetTracker object.
111  bool isForwardingAliasSet() const { return Forward; }
112
113  /// mergeSetIn - Merge the specified alias set into this alias set...
114  ///
115  void mergeSetIn(AliasSet &AS);
116
117  // Alias Set iteration - Allow access to all of the pointer which are part of
118  // this alias set...
119  class iterator;
120  iterator begin() const { return iterator(PtrListHead); }
121  iterator end()   const { return iterator(); }
122
123  void print(std::ostream &OS) const;
124  void dump() const;
125
126  /// Define an iterator for alias sets... this is just a forward iterator.
127  class iterator : public forward_iterator<HashNodePair, ptrdiff_t> {
128    HashNodePair *CurNode;
129  public:
130    iterator(HashNodePair *CN = 0) : CurNode(CN) {}
131
132    bool operator==(const iterator& x) const {
133      return CurNode == x.CurNode;
134    }
135    bool operator!=(const iterator& x) const { return !operator==(x); }
136
137    const iterator &operator=(const iterator &I) {
138      CurNode = I.CurNode;
139      return *this;
140    }
141
142    value_type &operator*() const {
143      assert(CurNode && "Dereferencing AliasSet.end()!");
144      return *CurNode;
145    }
146    value_type *operator->() const { return &operator*(); }
147
148    iterator& operator++() {                // Preincrement
149      assert(CurNode && "Advancing past AliasSet.end()!");
150      CurNode = CurNode->second.getNext();
151      return *this;
152    }
153    iterator operator++(int) { // Postincrement
154      iterator tmp = *this; ++*this; return tmp;
155    }
156  };
157
158private:
159  // Can only be created by AliasSetTracker
160  AliasSet() : PtrListHead(0), PtrListTail(0), Forward(0), RefCount(0),
161               AccessTy(NoModRef), AliasTy(MustAlias) {
162  }
163  HashNodePair *getSomePointer() const {
164    return PtrListHead ? PtrListHead : 0;
165  }
166
167  /// getForwardedTarget - Return the real alias set this represents.  If this
168  /// has been merged with another set and is forwarding, return the ultimate
169  /// destination set.  This also implements the union-find collapsing as well.
170  AliasSet *getForwardedTarget(AliasSetTracker &AST) {
171    if (!Forward) return this;
172
173    AliasSet *Dest = Forward->getForwardedTarget(AST);
174    if (Dest != Forward) {
175      Dest->RefCount++;
176      if (--Forward->RefCount == 0)
177        Forward->removeFromTracker(AST);
178      Forward = Dest;
179    }
180    return Dest;
181  }
182
183  void removeFromTracker(AliasSetTracker &AST);
184
185  void addPointer(AliasSetTracker &AST, HashNodePair &Entry, unsigned Size);
186  void addCallSite(CallSite CS);
187
188  /// aliasesPointer - Return true if the specified pointer "may" (or must)
189  /// alias one of the members in the set.
190  ///
191  bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const;
192  bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const;
193};
194
195inline std::ostream& operator<<(std::ostream &OS, const AliasSet &AS) {
196  AS.print(OS);
197  return OS;
198}
199
200
201class AliasSetTracker {
202  AliasAnalysis &AA;
203  ilist<AliasSet> AliasSets;
204
205  // Map from pointers to their node
206  hash_map<Value*, AliasSet::PointerRec> PointerMap;
207public:
208  /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
209  /// the specified alias analysis object to disambiguate load and store
210  /// addresses.
211  AliasSetTracker(AliasAnalysis &aa) : AA(aa) {}
212
213  /// add methods - These methods are used to add different types of
214  /// instructions to the alias sets.  Adding a new instruction can result in
215  /// one of three actions happening:
216  ///
217  ///   1. If the instruction doesn't alias any other sets, create a new set.
218  ///   2. If the instruction aliases exactly one set, add it to the set
219  ///   3. If the instruction aliases multiple sets, merge the sets, and add
220  ///      the instruction to the result.
221  ///
222  void add(LoadInst *LI);
223  void add(StoreInst *SI);
224  void add(CallSite CS);          // Call/Invoke instructions
225  void add(CallInst *CI)   { add(CallSite(CI)); }
226  void add(InvokeInst *II) { add(CallSite(II)); }
227  void add(Instruction *I);       // Dispatch to one of the other add methods...
228  void add(BasicBlock &BB);       // Add all instructions in basic block
229  void add(const AliasSetTracker &AST); // Add alias relations from another AST
230
231  /// getAliasSets - Return the alias sets that are active.
232  const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
233
234  /// getAliasSetForPointer - Return the alias set that the specified pointer
235  /// lives in...
236  AliasSet &getAliasSetForPointer(Value *P, unsigned Size);
237
238  /// getAliasAnalysis - Return the underlying alias analysis object used by
239  /// this tracker.
240  AliasAnalysis &getAliasAnalysis() const { return AA; }
241
242  typedef ilist<AliasSet>::iterator iterator;
243  typedef ilist<AliasSet>::const_iterator const_iterator;
244
245  const_iterator begin() const { return AliasSets.begin(); }
246  const_iterator end()   const { return AliasSets.end(); }
247
248  iterator begin() { return AliasSets.begin(); }
249  iterator end()   { return AliasSets.end(); }
250
251  void print(std::ostream &OS) const;
252  void dump() const;
253
254private:
255  friend class AliasSet;
256  void removeAliasSet(AliasSet *AS);
257
258  AliasSet::HashNodePair &getEntryFor(Value *V) {
259    // Standard operator[], except that it returns the whole pair, not just
260    // ->second.
261    return *PointerMap.insert(AliasSet::HashNodePair(V,
262                                            AliasSet::PointerRec())).first;
263  }
264
265  void addPointer(Value *P, unsigned Size, AliasSet::AccessType E) {
266    AliasSet &AS = getAliasSetForPointer(P, Size);
267    AS.AccessTy |= E;
268  }
269  AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size);
270
271  AliasSet *findAliasSetForCallSite(CallSite CS);
272};
273
274inline std::ostream& operator<<(std::ostream &OS, const AliasSetTracker &AST) {
275  AST.print(OS);
276  return OS;
277}
278
279#endif
280