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