xref: /llvm-project/llvm/include/llvm/Analysis/AliasSetTracker.h (revision 0da2ba811ac8a01509bc533428941fb9519c0715)
1 //===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- 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 two classes: AliasSetTracker and AliasSet. These interfaces
10 // are used to classify a collection of memory locations 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.
13 //
14 // An AliasSetTracker can only be used on immutable IR.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
19 #define LLVM_ANALYSIS_ALIASSETTRACKER_H
20 
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/ilist.h"
24 #include "llvm/ADT/ilist_node.h"
25 #include "llvm/Analysis/MemoryLocation.h"
26 #include "llvm/IR/PassManager.h"
27 #include "llvm/IR/ValueHandle.h"
28 #include <cassert>
29 #include <vector>
30 
31 namespace llvm {
32 
33 class AliasResult;
34 class AliasSetTracker;
35 class AnyMemSetInst;
36 class AnyMemTransferInst;
37 class BasicBlock;
38 class BatchAAResults;
39 class Function;
40 class Instruction;
41 class StoreInst;
42 class LoadInst;
43 enum class ModRefInfo : uint8_t;
44 class raw_ostream;
45 class VAArgInst;
46 class Value;
47 
48 class AliasSet : public ilist_node<AliasSet> {
49   friend class AliasSetTracker;
50 
51   // Forwarding pointer.
52   AliasSet *Forward = nullptr;
53 
54   /// Memory locations in this alias set.
55   SmallVector<MemoryLocation, 0> MemoryLocs;
56 
57   /// All instructions without a specific address in this alias set.
58   std::vector<AssertingVH<Instruction>> UnknownInsts;
59 
60   /// Number of nodes pointing to this AliasSet plus the number of AliasSets
61   /// forwarding to it.
62   unsigned RefCount : 27;
63 
64   // Signifies that this set should be considered to alias any pointer.
65   // Use when the tracker holding this set is saturated.
66   unsigned AliasAny : 1;
67 
68   /// The kinds of access this alias set models.
69   ///
70   /// We keep track of whether this alias set merely refers to the locations of
71   /// memory (and not any particular access), whether it modifies or references
72   /// the memory, or whether it does both. The lattice goes from "NoAccess" to
73   /// either RefAccess or ModAccess, then to ModRefAccess as necessary.
74   enum AccessLattice {
75     NoAccess = 0,
76     RefAccess = 1,
77     ModAccess = 2,
78     ModRefAccess = RefAccess | ModAccess
79   };
80   unsigned Access : 2;
81 
82   /// The kind of alias relationship between pointers of the set.
83   ///
84   /// These represent conservatively correct alias results between any members
85   /// of the set. We represent these independently of the values of alias
86   /// results in order to pack it into a single bit. Lattice goes from
87   /// MustAlias to MayAlias.
88   enum AliasLattice {
89     SetMustAlias = 0, SetMayAlias = 1
90   };
91   unsigned Alias : 1;
92 
93   void addRef() { ++RefCount; }
94 
95   void dropRef(AliasSetTracker &AST) {
96     assert(RefCount >= 1 && "Invalid reference count detected!");
97     if (--RefCount == 0)
98       removeFromTracker(AST);
99   }
100 
101 public:
102   AliasSet(const AliasSet &) = delete;
103   AliasSet &operator=(const AliasSet &) = delete;
104 
105   /// Accessors...
106   bool isRef() const { return Access & RefAccess; }
107   bool isMod() const { return Access & ModAccess; }
108   bool isMustAlias() const { return Alias == SetMustAlias; }
109   bool isMayAlias()  const { return Alias == SetMayAlias; }
110 
111   /// Return true if this alias set should be ignored as part of the
112   /// AliasSetTracker object.
113   bool isForwardingAliasSet() const { return Forward; }
114 
115   /// Merge the specified alias set into this alias set.
116   void mergeSetIn(AliasSet &AS, AliasSetTracker &AST, BatchAAResults &BatchAA);
117 
118   // Alias Set iteration - Allow access to all of the memory locations which are
119   // part of this alias set.
120   using iterator = SmallVectorImpl<MemoryLocation>::const_iterator;
121   iterator begin() const { return MemoryLocs.begin(); }
122   iterator end() const { return MemoryLocs.end(); }
123 
124   unsigned size() const { return MemoryLocs.size(); }
125 
126   /// Retrieve the pointer values for the memory locations in this alias set.
127   /// The order matches that of the memory locations, but duplicate pointer
128   /// values are omitted.
129   using PointerVector = SmallVector<const Value *, 8>;
130   PointerVector getPointers() const;
131 
132   void print(raw_ostream &OS) const;
133   void dump() const;
134 
135 private:
136   // Can only be created by AliasSetTracker.
137   AliasSet()
138       : RefCount(0), AliasAny(false), Access(NoAccess), Alias(SetMustAlias) {}
139 
140   void removeFromTracker(AliasSetTracker &AST);
141 
142   void addMemoryLocation(AliasSetTracker &AST, const MemoryLocation &MemLoc,
143                          bool KnownMustAlias = false);
144   void addUnknownInst(Instruction *I, BatchAAResults &AA);
145 
146 public:
147   /// If the specified memory location "may" (or must) alias one of the members
148   /// in the set return the appropriate AliasResult. Otherwise return NoAlias.
149   AliasResult aliasesMemoryLocation(const MemoryLocation &MemLoc,
150                                     BatchAAResults &AA) const;
151 
152   ModRefInfo aliasesUnknownInst(const Instruction *Inst,
153                                 BatchAAResults &AA) const;
154 };
155 
156 inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
157   AS.print(OS);
158   return OS;
159 }
160 
161 class AliasSetTracker {
162   BatchAAResults &AA;
163   ilist<AliasSet> AliasSets;
164 
165   using PointerMapType = DenseMap<AssertingVH<const Value>, AliasSet *>;
166 
167   // Map from pointer values to the alias set holding one or more memory
168   // locations with that pointer value.
169   PointerMapType PointerMap;
170 
171 public:
172   /// Create an empty collection of AliasSets, and use the specified alias
173   /// analysis object to disambiguate load and store addresses.
174   explicit AliasSetTracker(BatchAAResults &AA) : AA(AA) {}
175   ~AliasSetTracker() { clear(); }
176 
177   /// These methods are used to add different types of instructions to the alias
178   /// sets. Adding a new instruction can result in one of three actions
179   /// happening:
180   ///
181   ///   1. If the instruction doesn't alias any other sets, create a new set.
182   ///   2. If the instruction aliases exactly one set, add it to the set
183   ///   3. If the instruction aliases multiple sets, merge the sets, and add
184   ///      the instruction to the result.
185   ///
186   void add(const MemoryLocation &Loc);
187   void add(LoadInst *LI);
188   void add(StoreInst *SI);
189   void add(VAArgInst *VAAI);
190   void add(AnyMemSetInst *MSI);
191   void add(AnyMemTransferInst *MTI);
192   void add(Instruction *I);       // Dispatch to one of the other add methods...
193   void add(BasicBlock &BB);       // Add all instructions in basic block
194   void add(const AliasSetTracker &AST); // Add alias relations from another AST
195   void addUnknown(Instruction *I);
196 
197   void clear();
198 
199   /// Return the alias sets that are active.
200   const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
201 
202   /// Return the alias set which contains the specified memory location.  If
203   /// the memory location aliases two or more existing alias sets, will have
204   /// the effect of merging those alias sets before the single resulting alias
205   /// set is returned.
206   AliasSet &getAliasSetFor(const MemoryLocation &MemLoc);
207 
208   /// Return the underlying alias analysis object used by this tracker.
209   BatchAAResults &getAliasAnalysis() const { return AA; }
210 
211   using iterator = ilist<AliasSet>::iterator;
212   using const_iterator = ilist<AliasSet>::const_iterator;
213 
214   const_iterator begin() const { return AliasSets.begin(); }
215   const_iterator end()   const { return AliasSets.end(); }
216 
217   iterator begin() { return AliasSets.begin(); }
218   iterator end()   { return AliasSets.end(); }
219 
220   void print(raw_ostream &OS) const;
221   void dump() const;
222 
223 private:
224   friend class AliasSet;
225 
226   // The total number of memory locations contained in all alias sets.
227   unsigned TotalAliasSetSize = 0;
228 
229   // A non-null value signifies this AST is saturated. A saturated AST lumps
230   // all elements into a single "May" set.
231   AliasSet *AliasAnyAS = nullptr;
232 
233   void removeAliasSet(AliasSet *AS);
234 
235   // Update an alias set field to point to its real destination. If the field is
236   // pointing to a set that has been merged with another set and is forwarding,
237   // the field is updated to point to the set obtained by following the
238   // forwarding links. The Forward fields of intermediate alias sets are
239   // collapsed as well, and alias set reference counts are updated to reflect
240   // the new situation.
241   void collapseForwardingIn(AliasSet *&AS) {
242     if (AS->Forward) {
243       collapseForwardingIn(AS->Forward);
244       // Swap out AS for AS->Forward, while updating reference counts.
245       AliasSet *NewAS = AS->Forward;
246       NewAS->addRef();
247       AS->dropRef(*this);
248       AS = NewAS;
249     }
250   }
251 
252   AliasSet &addMemoryLocation(MemoryLocation Loc, AliasSet::AccessLattice E);
253   AliasSet *mergeAliasSetsForMemoryLocation(const MemoryLocation &MemLoc,
254                                             AliasSet *PtrAS,
255                                             bool &MustAliasAll);
256 
257   /// Merge all alias sets into a single set that is considered to alias
258   /// any memory location or instruction.
259   AliasSet &mergeAllAliasSets();
260 
261   AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
262 };
263 
264 inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) {
265   AST.print(OS);
266   return OS;
267 }
268 
269 class AliasSetsPrinterPass : public PassInfoMixin<AliasSetsPrinterPass> {
270   raw_ostream &OS;
271 
272 public:
273   explicit AliasSetsPrinterPass(raw_ostream &OS);
274   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
275   static bool isRequired() { return true; }
276 };
277 
278 } // end namespace llvm
279 
280 #endif // LLVM_ANALYSIS_ALIASSETTRACKER_H
281