| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 1 | //===- CFLAndersAliasAnalysis.cpp - Unification-based Alias Analysis ------===// | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | // | 
|  | 9 | // This file implements a CFL-based, summary-based alias analysis algorithm. It | 
|  | 10 | // differs from CFLSteensAliasAnalysis in its inclusion-based nature while | 
|  | 11 | // CFLSteensAliasAnalysis is unification-based. This pass has worse performance | 
|  | 12 | // than CFLSteensAliasAnalysis (the worst case complexity of | 
|  | 13 | // CFLAndersAliasAnalysis is cubic, while the worst case complexity of | 
|  | 14 | // CFLSteensAliasAnalysis is almost linear), but it is able to yield more | 
|  | 15 | // precise analysis result. The precision of this analysis is roughly the same | 
|  | 16 | // as that of an one level context-sensitive Andersen's algorithm. | 
|  | 17 | // | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 18 | // The algorithm used here is based on recursive state machine matching scheme | 
|  | 19 | // proposed in "Demand-driven alias analysis for C" by Xin Zheng and Radu | 
| Vedant Kumar | 1a8456d | 2018-03-02 18:57:02 +0000 | [diff] [blame] | 20 | // Rugina. The general idea is to extend the traditional transitive closure | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 21 | // algorithm to perform CFL matching along the way: instead of recording | 
|  | 22 | // "whether X is reachable from Y", we keep track of "whether X is reachable | 
|  | 23 | // from Y at state Z", where the "state" field indicates where we are in the CFL | 
|  | 24 | // matching process. To understand the matching better, it is advisable to have | 
|  | 25 | // the state machine shown in Figure 3 of the paper available when reading the | 
|  | 26 | // codes: all we do here is to selectively expand the transitive closure by | 
|  | 27 | // discarding edges that are not recognized by the state machine. | 
|  | 28 | // | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 29 | // There are two differences between our current implementation and the one | 
|  | 30 | // described in the paper: | 
|  | 31 | // - Our algorithm eagerly computes all alias pairs after the CFLGraph is built, | 
|  | 32 | // while in the paper the authors did the computation in a demand-driven | 
|  | 33 | // fashion. We did not implement the demand-driven algorithm due to the | 
|  | 34 | // additional coding complexity and higher memory profile, but if we found it | 
|  | 35 | // necessary we may switch to it eventually. | 
|  | 36 | // - In the paper the authors use a state machine that does not distinguish | 
|  | 37 | // value reads from value writes. For example, if Y is reachable from X at state | 
|  | 38 | // S3, it may be the case that X is written into Y, or it may be the case that | 
|  | 39 | // there's a third value Z that writes into both X and Y. To make that | 
|  | 40 | // distinction (which is crucial in building function summary as well as | 
|  | 41 | // retrieving mod-ref info), we choose to duplicate some of the states in the | 
|  | 42 | // paper's proposed state machine. The duplication does not change the set the | 
|  | 43 | // machine accepts. Given a pair of reachable values, it only provides more | 
|  | 44 | // detailed information on which value is being written into and which is being | 
|  | 45 | // read from. | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 46 | // | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 47 | //===----------------------------------------------------------------------===// | 
|  | 48 |  | 
|  | 49 | // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and | 
|  | 50 | // CFLAndersAA is interprocedural. This is *technically* A Bad Thing, because | 
|  | 51 | // FunctionPasses are only allowed to inspect the Function that they're being | 
|  | 52 | // run on. Realistically, this likely isn't a problem until we allow | 
|  | 53 | // FunctionPasses to run concurrently. | 
|  | 54 |  | 
|  | 55 | #include "llvm/Analysis/CFLAndersAliasAnalysis.h" | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 56 | #include "AliasAnalysisSummary.h" | 
| George Burgess IV | 1ca8aff | 2016-07-06 00:36:12 +0000 | [diff] [blame] | 57 | #include "CFLGraph.h" | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 58 | #include "llvm/ADT/DenseMap.h" | 
|  | 59 | #include "llvm/ADT/DenseMapInfo.h" | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 60 | #include "llvm/ADT/DenseSet.h" | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 61 | #include "llvm/ADT/None.h" | 
|  | 62 | #include "llvm/ADT/Optional.h" | 
|  | 63 | #include "llvm/ADT/STLExtras.h" | 
|  | 64 | #include "llvm/ADT/SmallVector.h" | 
|  | 65 | #include "llvm/ADT/iterator_range.h" | 
|  | 66 | #include "llvm/Analysis/AliasAnalysis.h" | 
|  | 67 | #include "llvm/Analysis/MemoryLocation.h" | 
|  | 68 | #include "llvm/IR/Argument.h" | 
|  | 69 | #include "llvm/IR/Function.h" | 
|  | 70 | #include "llvm/IR/PassManager.h" | 
|  | 71 | #include "llvm/IR/Type.h" | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 72 | #include "llvm/Pass.h" | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 73 | #include "llvm/Support/Casting.h" | 
|  | 74 | #include "llvm/Support/Compiler.h" | 
|  | 75 | #include "llvm/Support/Debug.h" | 
|  | 76 | #include "llvm/Support/raw_ostream.h" | 
|  | 77 | #include <algorithm> | 
|  | 78 | #include <bitset> | 
|  | 79 | #include <cassert> | 
|  | 80 | #include <cstddef> | 
|  | 81 | #include <cstdint> | 
|  | 82 | #include <functional> | 
|  | 83 | #include <utility> | 
|  | 84 | #include <vector> | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 85 |  | 
|  | 86 | using namespace llvm; | 
| George Burgess IV | 1ca8aff | 2016-07-06 00:36:12 +0000 | [diff] [blame] | 87 | using namespace llvm::cflaa; | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 88 |  | 
|  | 89 | #define DEBUG_TYPE "cfl-anders-aa" | 
|  | 90 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 91 | CFLAndersAAResult::CFLAndersAAResult(const TargetLibraryInfo &TLI) : TLI(TLI) {} | 
|  | 92 | CFLAndersAAResult::CFLAndersAAResult(CFLAndersAAResult &&RHS) | 
|  | 93 | : AAResultBase(std::move(RHS)), TLI(RHS.TLI) {} | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 94 | CFLAndersAAResult::~CFLAndersAAResult() = default; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 95 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 96 | namespace { | 
|  | 97 |  | 
|  | 98 | enum class MatchState : uint8_t { | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 99 | // The following state represents S1 in the paper. | 
|  | 100 | FlowFromReadOnly = 0, | 
|  | 101 | // The following two states together represent S2 in the paper. | 
|  | 102 | // The 'NoReadWrite' suffix indicates that there exists an alias path that | 
|  | 103 | // does not contain assignment and reverse assignment edges. | 
|  | 104 | // The 'ReadOnly' suffix indicates that there exists an alias path that | 
|  | 105 | // contains reverse assignment edges only. | 
|  | 106 | FlowFromMemAliasNoReadWrite, | 
|  | 107 | FlowFromMemAliasReadOnly, | 
|  | 108 | // The following two states together represent S3 in the paper. | 
|  | 109 | // The 'WriteOnly' suffix indicates that there exists an alias path that | 
|  | 110 | // contains assignment edges only. | 
|  | 111 | // The 'ReadWrite' suffix indicates that there exists an alias path that | 
|  | 112 | // contains both assignment and reverse assignment edges. Note that if X and Y | 
|  | 113 | // are reachable at 'ReadWrite' state, it does NOT mean X is both read from | 
|  | 114 | // and written to Y. Instead, it means that a third value Z is written to both | 
|  | 115 | // X and Y. | 
|  | 116 | FlowToWriteOnly, | 
|  | 117 | FlowToReadWrite, | 
|  | 118 | // The following two states together represent S4 in the paper. | 
|  | 119 | FlowToMemAliasWriteOnly, | 
|  | 120 | FlowToMemAliasReadWrite, | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 121 | }; | 
|  | 122 |  | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 123 | using StateSet = std::bitset<7>; | 
|  | 124 |  | 
| George Burgess IV | 381fc0e | 2016-08-25 01:05:08 +0000 | [diff] [blame] | 125 | const unsigned ReadOnlyStateMask = | 
| George Burgess IV | 22a0f1a | 2016-07-19 21:35:47 +0000 | [diff] [blame] | 126 | (1U << static_cast<uint8_t>(MatchState::FlowFromReadOnly)) | | 
|  | 127 | (1U << static_cast<uint8_t>(MatchState::FlowFromMemAliasReadOnly)); | 
| George Burgess IV | 381fc0e | 2016-08-25 01:05:08 +0000 | [diff] [blame] | 128 | const unsigned WriteOnlyStateMask = | 
| George Burgess IV | 22a0f1a | 2016-07-19 21:35:47 +0000 | [diff] [blame] | 129 | (1U << static_cast<uint8_t>(MatchState::FlowToWriteOnly)) | | 
|  | 130 | (1U << static_cast<uint8_t>(MatchState::FlowToMemAliasWriteOnly)); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 131 |  | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 132 | // A pair that consists of a value and an offset | 
|  | 133 | struct OffsetValue { | 
|  | 134 | const Value *Val; | 
|  | 135 | int64_t Offset; | 
|  | 136 | }; | 
|  | 137 |  | 
|  | 138 | bool operator==(OffsetValue LHS, OffsetValue RHS) { | 
|  | 139 | return LHS.Val == RHS.Val && LHS.Offset == RHS.Offset; | 
|  | 140 | } | 
|  | 141 | bool operator<(OffsetValue LHS, OffsetValue RHS) { | 
|  | 142 | return std::less<const Value *>()(LHS.Val, RHS.Val) || | 
|  | 143 | (LHS.Val == RHS.Val && LHS.Offset < RHS.Offset); | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | // A pair that consists of an InstantiatedValue and an offset | 
|  | 147 | struct OffsetInstantiatedValue { | 
|  | 148 | InstantiatedValue IVal; | 
|  | 149 | int64_t Offset; | 
|  | 150 | }; | 
|  | 151 |  | 
|  | 152 | bool operator==(OffsetInstantiatedValue LHS, OffsetInstantiatedValue RHS) { | 
|  | 153 | return LHS.IVal == RHS.IVal && LHS.Offset == RHS.Offset; | 
|  | 154 | } | 
|  | 155 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 156 | // We use ReachabilitySet to keep track of value aliases (The nonterminal "V" in | 
|  | 157 | // the paper) during the analysis. | 
|  | 158 | class ReachabilitySet { | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 159 | using ValueStateMap = DenseMap<InstantiatedValue, StateSet>; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 160 | using ValueReachMap = DenseMap<InstantiatedValue, ValueStateMap>; | 
|  | 161 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 162 | ValueReachMap ReachMap; | 
|  | 163 |  | 
|  | 164 | public: | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 165 | using const_valuestate_iterator = ValueStateMap::const_iterator; | 
|  | 166 | using const_value_iterator = ValueReachMap::const_iterator; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 167 |  | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 168 | // Insert edge 'From->To' at state 'State' | 
|  | 169 | bool insert(InstantiatedValue From, InstantiatedValue To, MatchState State) { | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 170 | assert(From != To); | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 171 | auto &States = ReachMap[To][From]; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 172 | auto Idx = static_cast<size_t>(State); | 
|  | 173 | if (!States.test(Idx)) { | 
|  | 174 | States.set(Idx); | 
|  | 175 | return true; | 
|  | 176 | } | 
|  | 177 | return false; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | // Return the set of all ('From', 'State') pair for a given node 'To' | 
|  | 181 | iterator_range<const_valuestate_iterator> | 
|  | 182 | reachableValueAliases(InstantiatedValue V) const { | 
|  | 183 | auto Itr = ReachMap.find(V); | 
|  | 184 | if (Itr == ReachMap.end()) | 
|  | 185 | return make_range<const_valuestate_iterator>(const_valuestate_iterator(), | 
|  | 186 | const_valuestate_iterator()); | 
|  | 187 | return make_range<const_valuestate_iterator>(Itr->second.begin(), | 
|  | 188 | Itr->second.end()); | 
|  | 189 | } | 
|  | 190 |  | 
|  | 191 | iterator_range<const_value_iterator> value_mappings() const { | 
|  | 192 | return make_range<const_value_iterator>(ReachMap.begin(), ReachMap.end()); | 
|  | 193 | } | 
|  | 194 | }; | 
|  | 195 |  | 
|  | 196 | // We use AliasMemSet to keep track of all memory aliases (the nonterminal "M" | 
|  | 197 | // in the paper) during the analysis. | 
|  | 198 | class AliasMemSet { | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 199 | using MemSet = DenseSet<InstantiatedValue>; | 
|  | 200 | using MemMapType = DenseMap<InstantiatedValue, MemSet>; | 
|  | 201 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 202 | MemMapType MemMap; | 
|  | 203 |  | 
|  | 204 | public: | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 205 | using const_mem_iterator = MemSet::const_iterator; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 206 |  | 
|  | 207 | bool insert(InstantiatedValue LHS, InstantiatedValue RHS) { | 
|  | 208 | // Top-level values can never be memory aliases because one cannot take the | 
|  | 209 | // addresses of them | 
|  | 210 | assert(LHS.DerefLevel > 0 && RHS.DerefLevel > 0); | 
|  | 211 | return MemMap[LHS].insert(RHS).second; | 
|  | 212 | } | 
|  | 213 |  | 
|  | 214 | const MemSet *getMemoryAliases(InstantiatedValue V) const { | 
|  | 215 | auto Itr = MemMap.find(V); | 
|  | 216 | if (Itr == MemMap.end()) | 
|  | 217 | return nullptr; | 
|  | 218 | return &Itr->second; | 
|  | 219 | } | 
|  | 220 | }; | 
|  | 221 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 222 | // We use AliasAttrMap to keep track of the AliasAttr of each node. | 
|  | 223 | class AliasAttrMap { | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 224 | using MapType = DenseMap<InstantiatedValue, AliasAttrs>; | 
|  | 225 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 226 | MapType AttrMap; | 
|  | 227 |  | 
|  | 228 | public: | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 229 | using const_iterator = MapType::const_iterator; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 230 |  | 
|  | 231 | bool add(InstantiatedValue V, AliasAttrs Attr) { | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 232 | auto &OldAttr = AttrMap[V]; | 
|  | 233 | auto NewAttr = OldAttr | Attr; | 
|  | 234 | if (OldAttr == NewAttr) | 
|  | 235 | return false; | 
|  | 236 | OldAttr = NewAttr; | 
|  | 237 | return true; | 
|  | 238 | } | 
|  | 239 |  | 
|  | 240 | AliasAttrs getAttrs(InstantiatedValue V) const { | 
|  | 241 | AliasAttrs Attr; | 
|  | 242 | auto Itr = AttrMap.find(V); | 
|  | 243 | if (Itr != AttrMap.end()) | 
|  | 244 | Attr = Itr->second; | 
|  | 245 | return Attr; | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 | iterator_range<const_iterator> mappings() const { | 
|  | 249 | return make_range<const_iterator>(AttrMap.begin(), AttrMap.end()); | 
|  | 250 | } | 
|  | 251 | }; | 
|  | 252 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 253 | struct WorkListItem { | 
|  | 254 | InstantiatedValue From; | 
|  | 255 | InstantiatedValue To; | 
|  | 256 | MatchState State; | 
|  | 257 | }; | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 258 |  | 
|  | 259 | struct ValueSummary { | 
|  | 260 | struct Record { | 
|  | 261 | InterfaceValue IValue; | 
|  | 262 | unsigned DerefLevel; | 
|  | 263 | }; | 
|  | 264 | SmallVector<Record, 4> FromRecords, ToRecords; | 
|  | 265 | }; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 266 |  | 
|  | 267 | } // end anonymous namespace | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 268 |  | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 269 | namespace llvm { | 
|  | 270 |  | 
|  | 271 | // Specialize DenseMapInfo for OffsetValue. | 
|  | 272 | template <> struct DenseMapInfo<OffsetValue> { | 
|  | 273 | static OffsetValue getEmptyKey() { | 
|  | 274 | return OffsetValue{DenseMapInfo<const Value *>::getEmptyKey(), | 
|  | 275 | DenseMapInfo<int64_t>::getEmptyKey()}; | 
|  | 276 | } | 
|  | 277 |  | 
|  | 278 | static OffsetValue getTombstoneKey() { | 
|  | 279 | return OffsetValue{DenseMapInfo<const Value *>::getTombstoneKey(), | 
|  | 280 | DenseMapInfo<int64_t>::getEmptyKey()}; | 
|  | 281 | } | 
|  | 282 |  | 
|  | 283 | static unsigned getHashValue(const OffsetValue &OVal) { | 
|  | 284 | return DenseMapInfo<std::pair<const Value *, int64_t>>::getHashValue( | 
|  | 285 | std::make_pair(OVal.Val, OVal.Offset)); | 
|  | 286 | } | 
|  | 287 |  | 
|  | 288 | static bool isEqual(const OffsetValue &LHS, const OffsetValue &RHS) { | 
|  | 289 | return LHS == RHS; | 
|  | 290 | } | 
|  | 291 | }; | 
|  | 292 |  | 
|  | 293 | // Specialize DenseMapInfo for OffsetInstantiatedValue. | 
|  | 294 | template <> struct DenseMapInfo<OffsetInstantiatedValue> { | 
|  | 295 | static OffsetInstantiatedValue getEmptyKey() { | 
|  | 296 | return OffsetInstantiatedValue{ | 
|  | 297 | DenseMapInfo<InstantiatedValue>::getEmptyKey(), | 
|  | 298 | DenseMapInfo<int64_t>::getEmptyKey()}; | 
|  | 299 | } | 
|  | 300 |  | 
|  | 301 | static OffsetInstantiatedValue getTombstoneKey() { | 
|  | 302 | return OffsetInstantiatedValue{ | 
|  | 303 | DenseMapInfo<InstantiatedValue>::getTombstoneKey(), | 
|  | 304 | DenseMapInfo<int64_t>::getEmptyKey()}; | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | static unsigned getHashValue(const OffsetInstantiatedValue &OVal) { | 
|  | 308 | return DenseMapInfo<std::pair<InstantiatedValue, int64_t>>::getHashValue( | 
|  | 309 | std::make_pair(OVal.IVal, OVal.Offset)); | 
|  | 310 | } | 
|  | 311 |  | 
|  | 312 | static bool isEqual(const OffsetInstantiatedValue &LHS, | 
|  | 313 | const OffsetInstantiatedValue &RHS) { | 
|  | 314 | return LHS == RHS; | 
|  | 315 | } | 
|  | 316 | }; | 
|  | 317 |  | 
|  | 318 | } // end namespace llvm | 
|  | 319 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 320 | class CFLAndersAAResult::FunctionInfo { | 
|  | 321 | /// Map a value to other values that may alias it | 
|  | 322 | /// Since the alias relation is symmetric, to save some space we assume values | 
|  | 323 | /// are properly ordered: if a and b alias each other, and a < b, then b is in | 
|  | 324 | /// AliasMap[a] but not vice versa. | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 325 | DenseMap<const Value *, std::vector<OffsetValue>> AliasMap; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 326 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 327 | /// Map a value to its corresponding AliasAttrs | 
|  | 328 | DenseMap<const Value *, AliasAttrs> AttrMap; | 
|  | 329 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 330 | /// Summary of externally visible effects. | 
|  | 331 | AliasSummary Summary; | 
|  | 332 |  | 
| George Burgess IV | 777efb1 | 2016-08-02 22:17:25 +0000 | [diff] [blame] | 333 | Optional<AliasAttrs> getAttrs(const Value *) const; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 334 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 335 | public: | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 336 | FunctionInfo(const Function &, const SmallVectorImpl<Value *> &, | 
| Benjamin Kramer | 061f4a5 | 2017-01-13 14:39:03 +0000 | [diff] [blame] | 337 | const ReachabilitySet &, const AliasAttrMap &); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 338 |  | 
| George Burgess IV | 319be3a | 2018-05-25 21:16:58 +0000 | [diff] [blame] | 339 | bool mayAlias(const Value *, LocationSize, const Value *, LocationSize) const; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 340 | const AliasSummary &getAliasSummary() const { return Summary; } | 
|  | 341 | }; | 
|  | 342 |  | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 343 | static bool hasReadOnlyState(StateSet Set) { | 
| George Burgess IV | 22a0f1a | 2016-07-19 21:35:47 +0000 | [diff] [blame] | 344 | return (Set & StateSet(ReadOnlyStateMask)).any(); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 345 | } | 
|  | 346 |  | 
|  | 347 | static bool hasWriteOnlyState(StateSet Set) { | 
| George Burgess IV | 22a0f1a | 2016-07-19 21:35:47 +0000 | [diff] [blame] | 348 | return (Set & StateSet(WriteOnlyStateMask)).any(); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 349 | } | 
|  | 350 |  | 
|  | 351 | static Optional<InterfaceValue> | 
|  | 352 | getInterfaceValue(InstantiatedValue IValue, | 
|  | 353 | const SmallVectorImpl<Value *> &RetVals) { | 
|  | 354 | auto Val = IValue.Val; | 
|  | 355 |  | 
|  | 356 | Optional<unsigned> Index; | 
|  | 357 | if (auto Arg = dyn_cast<Argument>(Val)) | 
|  | 358 | Index = Arg->getArgNo() + 1; | 
|  | 359 | else if (is_contained(RetVals, Val)) | 
|  | 360 | Index = 0; | 
|  | 361 |  | 
|  | 362 | if (Index) | 
|  | 363 | return InterfaceValue{*Index, IValue.DerefLevel}; | 
|  | 364 | return None; | 
|  | 365 | } | 
|  | 366 |  | 
|  | 367 | static void populateAttrMap(DenseMap<const Value *, AliasAttrs> &AttrMap, | 
|  | 368 | const AliasAttrMap &AMap) { | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 369 | for (const auto &Mapping : AMap.mappings()) { | 
|  | 370 | auto IVal = Mapping.first; | 
|  | 371 |  | 
| George Burgess IV | 4c58266 | 2016-08-01 18:27:33 +0000 | [diff] [blame] | 372 | // Insert IVal into the map | 
|  | 373 | auto &Attr = AttrMap[IVal.Val]; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 374 | // AttrMap only cares about top-level values | 
|  | 375 | if (IVal.DerefLevel == 0) | 
| George Burgess IV | 4c58266 | 2016-08-01 18:27:33 +0000 | [diff] [blame] | 376 | Attr |= Mapping.second; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 377 | } | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 378 | } | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 379 |  | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 380 | static void | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 381 | populateAliasMap(DenseMap<const Value *, std::vector<OffsetValue>> &AliasMap, | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 382 | const ReachabilitySet &ReachSet) { | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 383 | for (const auto &OuterMapping : ReachSet.value_mappings()) { | 
|  | 384 | // AliasMap only cares about top-level values | 
|  | 385 | if (OuterMapping.first.DerefLevel > 0) | 
|  | 386 | continue; | 
|  | 387 |  | 
|  | 388 | auto Val = OuterMapping.first.Val; | 
|  | 389 | auto &AliasList = AliasMap[Val]; | 
|  | 390 | for (const auto &InnerMapping : OuterMapping.second) { | 
|  | 391 | // Again, AliasMap only cares about top-level values | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 392 | if (InnerMapping.first.DerefLevel == 0) | 
|  | 393 | AliasList.push_back(OffsetValue{InnerMapping.first.Val, UnknownOffset}); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 394 | } | 
|  | 395 |  | 
|  | 396 | // Sort AliasList for faster lookup | 
| Fangrui Song | 0cac726 | 2018-09-27 02:13:45 +0000 | [diff] [blame] | 397 | llvm::sort(AliasList); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 398 | } | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 399 | } | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 400 |  | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 401 | static void populateExternalRelations( | 
|  | 402 | SmallVectorImpl<ExternalRelation> &ExtRelations, const Function &Fn, | 
|  | 403 | const SmallVectorImpl<Value *> &RetVals, const ReachabilitySet &ReachSet) { | 
|  | 404 | // If a function only returns one of its argument X, then X will be both an | 
|  | 405 | // argument and a return value at the same time. This is an edge case that | 
|  | 406 | // needs special handling here. | 
|  | 407 | for (const auto &Arg : Fn.args()) { | 
|  | 408 | if (is_contained(RetVals, &Arg)) { | 
|  | 409 | auto ArgVal = InterfaceValue{Arg.getArgNo() + 1, 0}; | 
|  | 410 | auto RetVal = InterfaceValue{0, 0}; | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 411 | ExtRelations.push_back(ExternalRelation{ArgVal, RetVal, 0}); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 412 | } | 
|  | 413 | } | 
|  | 414 |  | 
|  | 415 | // Below is the core summary construction logic. | 
|  | 416 | // A naive solution of adding only the value aliases that are parameters or | 
|  | 417 | // return values in ReachSet to the summary won't work: It is possible that a | 
|  | 418 | // parameter P is written into an intermediate value I, and the function | 
|  | 419 | // subsequently returns *I. In that case, *I is does not value alias anything | 
|  | 420 | // in ReachSet, and the naive solution will miss a summary edge from (P, 1) to | 
|  | 421 | // (I, 1). | 
|  | 422 | // To account for the aforementioned case, we need to check each non-parameter | 
|  | 423 | // and non-return value for the possibility of acting as an intermediate. | 
|  | 424 | // 'ValueMap' here records, for each value, which InterfaceValues read from or | 
|  | 425 | // write into it. If both the read list and the write list of a given value | 
|  | 426 | // are non-empty, we know that a particular value is an intermidate and we | 
|  | 427 | // need to add summary edges from the writes to the reads. | 
|  | 428 | DenseMap<Value *, ValueSummary> ValueMap; | 
|  | 429 | for (const auto &OuterMapping : ReachSet.value_mappings()) { | 
|  | 430 | if (auto Dst = getInterfaceValue(OuterMapping.first, RetVals)) { | 
|  | 431 | for (const auto &InnerMapping : OuterMapping.second) { | 
|  | 432 | // If Src is a param/return value, we get a same-level assignment. | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 433 | if (auto Src = getInterfaceValue(InnerMapping.first, RetVals)) { | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 434 | // This may happen if both Dst and Src are return values | 
|  | 435 | if (*Dst == *Src) | 
|  | 436 | continue; | 
|  | 437 |  | 
|  | 438 | if (hasReadOnlyState(InnerMapping.second)) | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 439 | ExtRelations.push_back(ExternalRelation{*Dst, *Src, UnknownOffset}); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 440 | // No need to check for WriteOnly state, since ReachSet is symmetric | 
|  | 441 | } else { | 
|  | 442 | // If Src is not a param/return, add it to ValueMap | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 443 | auto SrcIVal = InnerMapping.first; | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 444 | if (hasReadOnlyState(InnerMapping.second)) | 
|  | 445 | ValueMap[SrcIVal.Val].FromRecords.push_back( | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 446 | ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 447 | if (hasWriteOnlyState(InnerMapping.second)) | 
|  | 448 | ValueMap[SrcIVal.Val].ToRecords.push_back( | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 449 | ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 450 | } | 
|  | 451 | } | 
|  | 452 | } | 
|  | 453 | } | 
|  | 454 |  | 
|  | 455 | for (const auto &Mapping : ValueMap) { | 
|  | 456 | for (const auto &FromRecord : Mapping.second.FromRecords) { | 
|  | 457 | for (const auto &ToRecord : Mapping.second.ToRecords) { | 
|  | 458 | auto ToLevel = ToRecord.DerefLevel; | 
|  | 459 | auto FromLevel = FromRecord.DerefLevel; | 
|  | 460 | // Same-level assignments should have already been processed by now | 
|  | 461 | if (ToLevel == FromLevel) | 
|  | 462 | continue; | 
|  | 463 |  | 
|  | 464 | auto SrcIndex = FromRecord.IValue.Index; | 
|  | 465 | auto SrcLevel = FromRecord.IValue.DerefLevel; | 
|  | 466 | auto DstIndex = ToRecord.IValue.Index; | 
|  | 467 | auto DstLevel = ToRecord.IValue.DerefLevel; | 
|  | 468 | if (ToLevel > FromLevel) | 
|  | 469 | SrcLevel += ToLevel - FromLevel; | 
|  | 470 | else | 
|  | 471 | DstLevel += FromLevel - ToLevel; | 
|  | 472 |  | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 473 | ExtRelations.push_back(ExternalRelation{ | 
|  | 474 | InterfaceValue{SrcIndex, SrcLevel}, | 
|  | 475 | InterfaceValue{DstIndex, DstLevel}, UnknownOffset}); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 476 | } | 
|  | 477 | } | 
|  | 478 | } | 
|  | 479 |  | 
|  | 480 | // Remove duplicates in ExtRelations | 
| Fangrui Song | 0cac726 | 2018-09-27 02:13:45 +0000 | [diff] [blame] | 481 | llvm::sort(ExtRelations); | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 482 | ExtRelations.erase(std::unique(ExtRelations.begin(), ExtRelations.end()), | 
|  | 483 | ExtRelations.end()); | 
|  | 484 | } | 
|  | 485 |  | 
|  | 486 | static void populateExternalAttributes( | 
|  | 487 | SmallVectorImpl<ExternalAttribute> &ExtAttributes, const Function &Fn, | 
|  | 488 | const SmallVectorImpl<Value *> &RetVals, const AliasAttrMap &AMap) { | 
|  | 489 | for (const auto &Mapping : AMap.mappings()) { | 
|  | 490 | if (auto IVal = getInterfaceValue(Mapping.first, RetVals)) { | 
|  | 491 | auto Attr = getExternallyVisibleAttrs(Mapping.second); | 
|  | 492 | if (Attr.any()) | 
|  | 493 | ExtAttributes.push_back(ExternalAttribute{*IVal, Attr}); | 
|  | 494 | } | 
|  | 495 | } | 
|  | 496 | } | 
|  | 497 |  | 
|  | 498 | CFLAndersAAResult::FunctionInfo::FunctionInfo( | 
|  | 499 | const Function &Fn, const SmallVectorImpl<Value *> &RetVals, | 
| Benjamin Kramer | 061f4a5 | 2017-01-13 14:39:03 +0000 | [diff] [blame] | 500 | const ReachabilitySet &ReachSet, const AliasAttrMap &AMap) { | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 501 | populateAttrMap(AttrMap, AMap); | 
|  | 502 | populateExternalAttributes(Summary.RetParamAttributes, Fn, RetVals, AMap); | 
|  | 503 | populateAliasMap(AliasMap, ReachSet); | 
|  | 504 | populateExternalRelations(Summary.RetParamRelations, Fn, RetVals, ReachSet); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 505 | } | 
|  | 506 |  | 
| George Burgess IV | 777efb1 | 2016-08-02 22:17:25 +0000 | [diff] [blame] | 507 | Optional<AliasAttrs> | 
|  | 508 | CFLAndersAAResult::FunctionInfo::getAttrs(const Value *V) const { | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 509 | assert(V != nullptr); | 
|  | 510 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 511 | auto Itr = AttrMap.find(V); | 
|  | 512 | if (Itr != AttrMap.end()) | 
| George Burgess IV | 777efb1 | 2016-08-02 22:17:25 +0000 | [diff] [blame] | 513 | return Itr->second; | 
|  | 514 | return None; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 515 | } | 
|  | 516 |  | 
| George Burgess IV | fefc42c | 2018-10-09 02:14:33 +0000 | [diff] [blame] | 517 | bool CFLAndersAAResult::FunctionInfo::mayAlias( | 
|  | 518 | const Value *LHS, LocationSize MaybeLHSSize, const Value *RHS, | 
|  | 519 | LocationSize MaybeRHSSize) const { | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 520 | assert(LHS && RHS); | 
|  | 521 |  | 
| George Burgess IV | 777efb1 | 2016-08-02 22:17:25 +0000 | [diff] [blame] | 522 | // Check if we've seen LHS and RHS before. Sometimes LHS or RHS can be created | 
|  | 523 | // after the analysis gets executed, and we want to be conservative in those | 
|  | 524 | // cases. | 
|  | 525 | auto MaybeAttrsA = getAttrs(LHS); | 
|  | 526 | auto MaybeAttrsB = getAttrs(RHS); | 
|  | 527 | if (!MaybeAttrsA || !MaybeAttrsB) | 
|  | 528 | return true; | 
|  | 529 |  | 
|  | 530 | // Check AliasAttrs before AliasMap lookup since it's cheaper | 
|  | 531 | auto AttrsA = *MaybeAttrsA; | 
|  | 532 | auto AttrsB = *MaybeAttrsB; | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 533 | if (hasUnknownOrCallerAttr(AttrsA)) | 
|  | 534 | return AttrsB.any(); | 
|  | 535 | if (hasUnknownOrCallerAttr(AttrsB)) | 
|  | 536 | return AttrsA.any(); | 
|  | 537 | if (isGlobalOrArgAttr(AttrsA)) | 
|  | 538 | return isGlobalOrArgAttr(AttrsB); | 
|  | 539 | if (isGlobalOrArgAttr(AttrsB)) | 
|  | 540 | return isGlobalOrArgAttr(AttrsA); | 
|  | 541 |  | 
|  | 542 | // At this point both LHS and RHS should point to locally allocated objects | 
|  | 543 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 544 | auto Itr = AliasMap.find(LHS); | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 545 | if (Itr != AliasMap.end()) { | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 546 |  | 
|  | 547 | // Find out all (X, Offset) where X == RHS | 
|  | 548 | auto Comparator = [](OffsetValue LHS, OffsetValue RHS) { | 
|  | 549 | return std::less<const Value *>()(LHS.Val, RHS.Val); | 
|  | 550 | }; | 
|  | 551 | #ifdef EXPENSIVE_CHECKS | 
|  | 552 | assert(std::is_sorted(Itr->second.begin(), Itr->second.end(), Comparator)); | 
|  | 553 | #endif | 
|  | 554 | auto RangePair = std::equal_range(Itr->second.begin(), Itr->second.end(), | 
|  | 555 | OffsetValue{RHS, 0}, Comparator); | 
|  | 556 |  | 
|  | 557 | if (RangePair.first != RangePair.second) { | 
| George Burgess IV | 6ef8002 | 2018-10-10 21:28:44 +0000 | [diff] [blame] | 558 | // Be conservative about unknown sizes | 
|  | 559 | if (MaybeLHSSize == LocationSize::unknown() || | 
|  | 560 | MaybeRHSSize == LocationSize::unknown()) | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 561 | return true; | 
|  | 562 |  | 
| George Burgess IV | f96e618 | 2018-10-09 03:18:56 +0000 | [diff] [blame] | 563 | const uint64_t LHSSize = MaybeLHSSize.getValue(); | 
|  | 564 | const uint64_t RHSSize = MaybeRHSSize.getValue(); | 
| George Burgess IV | fefc42c | 2018-10-09 02:14:33 +0000 | [diff] [blame] | 565 |  | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 566 | for (const auto &OVal : make_range(RangePair)) { | 
|  | 567 | // Be conservative about UnknownOffset | 
|  | 568 | if (OVal.Offset == UnknownOffset) | 
|  | 569 | return true; | 
|  | 570 |  | 
|  | 571 | // We know that LHS aliases (RHS + OVal.Offset) if the control flow | 
|  | 572 | // reaches here. The may-alias query essentially becomes integer | 
|  | 573 | // range-overlap queries over two ranges [OVal.Offset, OVal.Offset + | 
|  | 574 | // LHSSize) and [0, RHSSize). | 
|  | 575 |  | 
|  | 576 | // Try to be conservative on super large offsets | 
|  | 577 | if (LLVM_UNLIKELY(LHSSize > INT64_MAX || RHSSize > INT64_MAX)) | 
|  | 578 | return true; | 
|  | 579 |  | 
|  | 580 | auto LHSStart = OVal.Offset; | 
|  | 581 | // FIXME: Do we need to guard against integer overflow? | 
|  | 582 | auto LHSEnd = OVal.Offset + static_cast<int64_t>(LHSSize); | 
|  | 583 | auto RHSStart = 0; | 
|  | 584 | auto RHSEnd = static_cast<int64_t>(RHSSize); | 
|  | 585 | if (LHSEnd > RHSStart && LHSStart < RHSEnd) | 
|  | 586 | return true; | 
|  | 587 | } | 
|  | 588 | } | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 589 | } | 
|  | 590 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 591 | return false; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 592 | } | 
|  | 593 |  | 
|  | 594 | static void propagate(InstantiatedValue From, InstantiatedValue To, | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 595 | MatchState State, ReachabilitySet &ReachSet, | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 596 | std::vector<WorkListItem> &WorkList) { | 
|  | 597 | if (From == To) | 
|  | 598 | return; | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 599 | if (ReachSet.insert(From, To, State)) | 
|  | 600 | WorkList.push_back(WorkListItem{From, To, State}); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 601 | } | 
|  | 602 |  | 
|  | 603 | static void initializeWorkList(std::vector<WorkListItem> &WorkList, | 
|  | 604 | ReachabilitySet &ReachSet, | 
|  | 605 | const CFLGraph &Graph) { | 
|  | 606 | for (const auto &Mapping : Graph.value_mappings()) { | 
|  | 607 | auto Val = Mapping.first; | 
|  | 608 | auto &ValueInfo = Mapping.second; | 
|  | 609 | assert(ValueInfo.getNumLevels() > 0); | 
|  | 610 |  | 
|  | 611 | // Insert all immediate assignment neighbors to the worklist | 
|  | 612 | for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) { | 
|  | 613 | auto Src = InstantiatedValue{Val, I}; | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 614 | // If there's an assignment edge from X to Y, it means Y is reachable from | 
|  | 615 | // X at S2 and X is reachable from Y at S1 | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 616 | for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges) { | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 617 | propagate(Edge.Other, Src, MatchState::FlowFromReadOnly, ReachSet, | 
|  | 618 | WorkList); | 
|  | 619 | propagate(Src, Edge.Other, MatchState::FlowToWriteOnly, ReachSet, | 
|  | 620 | WorkList); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 621 | } | 
|  | 622 | } | 
|  | 623 | } | 
|  | 624 | } | 
|  | 625 |  | 
|  | 626 | static Optional<InstantiatedValue> getNodeBelow(const CFLGraph &Graph, | 
|  | 627 | InstantiatedValue V) { | 
|  | 628 | auto NodeBelow = InstantiatedValue{V.Val, V.DerefLevel + 1}; | 
|  | 629 | if (Graph.getNode(NodeBelow)) | 
|  | 630 | return NodeBelow; | 
|  | 631 | return None; | 
|  | 632 | } | 
|  | 633 |  | 
|  | 634 | static void processWorkListItem(const WorkListItem &Item, const CFLGraph &Graph, | 
|  | 635 | ReachabilitySet &ReachSet, AliasMemSet &MemSet, | 
|  | 636 | std::vector<WorkListItem> &WorkList) { | 
|  | 637 | auto FromNode = Item.From; | 
|  | 638 | auto ToNode = Item.To; | 
|  | 639 |  | 
|  | 640 | auto NodeInfo = Graph.getNode(ToNode); | 
|  | 641 | assert(NodeInfo != nullptr); | 
|  | 642 |  | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 643 | // TODO: propagate field offsets | 
|  | 644 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 645 | // FIXME: Here is a neat trick we can do: since both ReachSet and MemSet holds | 
|  | 646 | // relations that are symmetric, we could actually cut the storage by half by | 
|  | 647 | // sorting FromNode and ToNode before insertion happens. | 
|  | 648 |  | 
| Vedant Kumar | 1a8456d | 2018-03-02 18:57:02 +0000 | [diff] [blame] | 649 | // The newly added value alias pair may potentially generate more memory | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 650 | // alias pairs. Check for them here. | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 651 | auto FromNodeBelow = getNodeBelow(Graph, FromNode); | 
|  | 652 | auto ToNodeBelow = getNodeBelow(Graph, ToNode); | 
|  | 653 | if (FromNodeBelow && ToNodeBelow && | 
|  | 654 | MemSet.insert(*FromNodeBelow, *ToNodeBelow)) { | 
|  | 655 | propagate(*FromNodeBelow, *ToNodeBelow, | 
|  | 656 | MatchState::FlowFromMemAliasNoReadWrite, ReachSet, WorkList); | 
|  | 657 | for (const auto &Mapping : ReachSet.reachableValueAliases(*FromNodeBelow)) { | 
|  | 658 | auto Src = Mapping.first; | 
|  | 659 | auto MemAliasPropagate = [&](MatchState FromState, MatchState ToState) { | 
|  | 660 | if (Mapping.second.test(static_cast<size_t>(FromState))) | 
|  | 661 | propagate(Src, *ToNodeBelow, ToState, ReachSet, WorkList); | 
|  | 662 | }; | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 663 |  | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 664 | MemAliasPropagate(MatchState::FlowFromReadOnly, | 
|  | 665 | MatchState::FlowFromMemAliasReadOnly); | 
|  | 666 | MemAliasPropagate(MatchState::FlowToWriteOnly, | 
|  | 667 | MatchState::FlowToMemAliasWriteOnly); | 
|  | 668 | MemAliasPropagate(MatchState::FlowToReadWrite, | 
|  | 669 | MatchState::FlowToMemAliasReadWrite); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 670 | } | 
|  | 671 | } | 
|  | 672 |  | 
|  | 673 | // This is the core of the state machine walking algorithm. We expand ReachSet | 
|  | 674 | // based on which state we are at (which in turn dictates what edges we | 
|  | 675 | // should examine) | 
|  | 676 | // From a high-level point of view, the state machine here guarantees two | 
|  | 677 | // properties: | 
|  | 678 | // - If *X and *Y are memory aliases, then X and Y are value aliases | 
|  | 679 | // - If Y is an alias of X, then reverse assignment edges (if there is any) | 
|  | 680 | // should precede any assignment edges on the path from X to Y. | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 681 | auto NextAssignState = [&](MatchState State) { | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 682 | for (const auto &AssignEdge : NodeInfo->Edges) | 
|  | 683 | propagate(FromNode, AssignEdge.Other, State, ReachSet, WorkList); | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 684 | }; | 
|  | 685 | auto NextRevAssignState = [&](MatchState State) { | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 686 | for (const auto &RevAssignEdge : NodeInfo->ReverseEdges) | 
|  | 687 | propagate(FromNode, RevAssignEdge.Other, State, ReachSet, WorkList); | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 688 | }; | 
|  | 689 | auto NextMemState = [&](MatchState State) { | 
|  | 690 | if (auto AliasSet = MemSet.getMemoryAliases(ToNode)) { | 
|  | 691 | for (const auto &MemAlias : *AliasSet) | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 692 | propagate(FromNode, MemAlias, State, ReachSet, WorkList); | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 693 | } | 
|  | 694 | }; | 
|  | 695 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 696 | switch (Item.State) { | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 697 | case MatchState::FlowFromReadOnly: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 698 | NextRevAssignState(MatchState::FlowFromReadOnly); | 
|  | 699 | NextAssignState(MatchState::FlowToReadWrite); | 
|  | 700 | NextMemState(MatchState::FlowFromMemAliasReadOnly); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 701 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 702 |  | 
|  | 703 | case MatchState::FlowFromMemAliasNoReadWrite: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 704 | NextRevAssignState(MatchState::FlowFromReadOnly); | 
|  | 705 | NextAssignState(MatchState::FlowToWriteOnly); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 706 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 707 |  | 
|  | 708 | case MatchState::FlowFromMemAliasReadOnly: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 709 | NextRevAssignState(MatchState::FlowFromReadOnly); | 
|  | 710 | NextAssignState(MatchState::FlowToReadWrite); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 711 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 712 |  | 
|  | 713 | case MatchState::FlowToWriteOnly: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 714 | NextAssignState(MatchState::FlowToWriteOnly); | 
|  | 715 | NextMemState(MatchState::FlowToMemAliasWriteOnly); | 
|  | 716 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 717 |  | 
|  | 718 | case MatchState::FlowToReadWrite: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 719 | NextAssignState(MatchState::FlowToReadWrite); | 
|  | 720 | NextMemState(MatchState::FlowToMemAliasReadWrite); | 
|  | 721 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 722 |  | 
|  | 723 | case MatchState::FlowToMemAliasWriteOnly: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 724 | NextAssignState(MatchState::FlowToWriteOnly); | 
|  | 725 | break; | 
| Eugene Zelenko | 530851c | 2017-08-11 21:30:02 +0000 | [diff] [blame] | 726 |  | 
|  | 727 | case MatchState::FlowToMemAliasReadWrite: | 
| George Burgess IV | c01b42f | 2016-07-19 20:38:21 +0000 | [diff] [blame] | 728 | NextAssignState(MatchState::FlowToReadWrite); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 729 | break; | 
|  | 730 | } | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 731 | } | 
|  | 732 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 733 | static AliasAttrMap buildAttrMap(const CFLGraph &Graph, | 
|  | 734 | const ReachabilitySet &ReachSet) { | 
|  | 735 | AliasAttrMap AttrMap; | 
|  | 736 | std::vector<InstantiatedValue> WorkList, NextList; | 
|  | 737 |  | 
|  | 738 | // Initialize each node with its original AliasAttrs in CFLGraph | 
|  | 739 | for (const auto &Mapping : Graph.value_mappings()) { | 
|  | 740 | auto Val = Mapping.first; | 
|  | 741 | auto &ValueInfo = Mapping.second; | 
|  | 742 | for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) { | 
|  | 743 | auto Node = InstantiatedValue{Val, I}; | 
|  | 744 | AttrMap.add(Node, ValueInfo.getNodeInfoAtLevel(I).Attr); | 
|  | 745 | WorkList.push_back(Node); | 
|  | 746 | } | 
|  | 747 | } | 
|  | 748 |  | 
|  | 749 | while (!WorkList.empty()) { | 
|  | 750 | for (const auto &Dst : WorkList) { | 
|  | 751 | auto DstAttr = AttrMap.getAttrs(Dst); | 
|  | 752 | if (DstAttr.none()) | 
|  | 753 | continue; | 
|  | 754 |  | 
|  | 755 | // Propagate attr on the same level | 
|  | 756 | for (const auto &Mapping : ReachSet.reachableValueAliases(Dst)) { | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 757 | auto Src = Mapping.first; | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 758 | if (AttrMap.add(Src, DstAttr)) | 
|  | 759 | NextList.push_back(Src); | 
|  | 760 | } | 
|  | 761 |  | 
|  | 762 | // Propagate attr to the levels below | 
|  | 763 | auto DstBelow = getNodeBelow(Graph, Dst); | 
|  | 764 | while (DstBelow) { | 
|  | 765 | if (AttrMap.add(*DstBelow, DstAttr)) { | 
|  | 766 | NextList.push_back(*DstBelow); | 
|  | 767 | break; | 
|  | 768 | } | 
|  | 769 | DstBelow = getNodeBelow(Graph, *DstBelow); | 
|  | 770 | } | 
|  | 771 | } | 
|  | 772 | WorkList.swap(NextList); | 
|  | 773 | NextList.clear(); | 
|  | 774 | } | 
|  | 775 |  | 
|  | 776 | return AttrMap; | 
|  | 777 | } | 
|  | 778 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 779 | CFLAndersAAResult::FunctionInfo | 
|  | 780 | CFLAndersAAResult::buildInfoFrom(const Function &Fn) { | 
|  | 781 | CFLGraphBuilder<CFLAndersAAResult> GraphBuilder( | 
|  | 782 | *this, TLI, | 
|  | 783 | // Cast away the constness here due to GraphBuilder's API requirement | 
|  | 784 | const_cast<Function &>(Fn)); | 
|  | 785 | auto &Graph = GraphBuilder.getCFLGraph(); | 
|  | 786 |  | 
|  | 787 | ReachabilitySet ReachSet; | 
|  | 788 | AliasMemSet MemSet; | 
|  | 789 |  | 
|  | 790 | std::vector<WorkListItem> WorkList, NextList; | 
|  | 791 | initializeWorkList(WorkList, ReachSet, Graph); | 
| George Burgess IV | c652617 | 2018-05-17 21:56:39 +0000 | [diff] [blame] | 792 | // TODO: make sure we don't stop before the fix point is reached | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 793 | while (!WorkList.empty()) { | 
|  | 794 | for (const auto &Item : WorkList) | 
|  | 795 | processWorkListItem(Item, Graph, ReachSet, MemSet, NextList); | 
|  | 796 |  | 
|  | 797 | NextList.swap(WorkList); | 
|  | 798 | NextList.clear(); | 
|  | 799 | } | 
|  | 800 |  | 
| George Burgess IV | 22682e2 | 2016-07-15 20:02:49 +0000 | [diff] [blame] | 801 | // Now that we have all the reachability info, propagate AliasAttrs according | 
|  | 802 | // to it | 
|  | 803 | auto IValueAttrMap = buildAttrMap(Graph, ReachSet); | 
|  | 804 |  | 
| George Burgess IV | 3b05984 | 2016-07-19 20:47:15 +0000 | [diff] [blame] | 805 | return FunctionInfo(Fn, GraphBuilder.getReturnValues(), ReachSet, | 
|  | 806 | std::move(IValueAttrMap)); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 807 | } | 
|  | 808 |  | 
|  | 809 | void CFLAndersAAResult::scan(const Function &Fn) { | 
|  | 810 | auto InsertPair = Cache.insert(std::make_pair(&Fn, Optional<FunctionInfo>())); | 
|  | 811 | (void)InsertPair; | 
|  | 812 | assert(InsertPair.second && | 
|  | 813 | "Trying to scan a function that has already been cached"); | 
|  | 814 |  | 
|  | 815 | // Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call | 
|  | 816 | // may get evaluated after operator[], potentially triggering a DenseMap | 
|  | 817 | // resize and invalidating the reference returned by operator[] | 
|  | 818 | auto FunInfo = buildInfoFrom(Fn); | 
|  | 819 | Cache[&Fn] = std::move(FunInfo); | 
| Davide Italiano | e34a806 | 2017-06-26 23:59:14 +0000 | [diff] [blame] | 820 | Handles.emplace_front(const_cast<Function *>(&Fn), this); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 821 | } | 
|  | 822 |  | 
| Davide Italiano | e34a806 | 2017-06-26 23:59:14 +0000 | [diff] [blame] | 823 | void CFLAndersAAResult::evict(const Function *Fn) { Cache.erase(Fn); } | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 824 |  | 
|  | 825 | const Optional<CFLAndersAAResult::FunctionInfo> & | 
|  | 826 | CFLAndersAAResult::ensureCached(const Function &Fn) { | 
|  | 827 | auto Iter = Cache.find(&Fn); | 
|  | 828 | if (Iter == Cache.end()) { | 
|  | 829 | scan(Fn); | 
|  | 830 | Iter = Cache.find(&Fn); | 
|  | 831 | assert(Iter != Cache.end()); | 
|  | 832 | assert(Iter->second.hasValue()); | 
|  | 833 | } | 
|  | 834 | return Iter->second; | 
|  | 835 | } | 
|  | 836 |  | 
|  | 837 | const AliasSummary *CFLAndersAAResult::getAliasSummary(const Function &Fn) { | 
|  | 838 | auto &FunInfo = ensureCached(Fn); | 
|  | 839 | if (FunInfo.hasValue()) | 
|  | 840 | return &FunInfo->getAliasSummary(); | 
|  | 841 | else | 
|  | 842 | return nullptr; | 
|  | 843 | } | 
|  | 844 |  | 
|  | 845 | AliasResult CFLAndersAAResult::query(const MemoryLocation &LocA, | 
|  | 846 | const MemoryLocation &LocB) { | 
|  | 847 | auto *ValA = LocA.Ptr; | 
|  | 848 | auto *ValB = LocB.Ptr; | 
|  | 849 |  | 
|  | 850 | if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy()) | 
|  | 851 | return NoAlias; | 
|  | 852 |  | 
|  | 853 | auto *Fn = parentFunctionOfValue(ValA); | 
|  | 854 | if (!Fn) { | 
|  | 855 | Fn = parentFunctionOfValue(ValB); | 
|  | 856 | if (!Fn) { | 
|  | 857 | // The only times this is known to happen are when globals + InlineAsm are | 
|  | 858 | // involved | 
| Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 859 | LLVM_DEBUG( | 
|  | 860 | dbgs() | 
|  | 861 | << "CFLAndersAA: could not extract parent function information.\n"); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 862 | return MayAlias; | 
|  | 863 | } | 
|  | 864 | } else { | 
|  | 865 | assert(!parentFunctionOfValue(ValB) || parentFunctionOfValue(ValB) == Fn); | 
|  | 866 | } | 
|  | 867 |  | 
|  | 868 | assert(Fn != nullptr); | 
|  | 869 | auto &FunInfo = ensureCached(*Fn); | 
|  | 870 |  | 
|  | 871 | // AliasMap lookup | 
| George Burgess IV | 4ec1753 | 2016-07-22 22:30:48 +0000 | [diff] [blame] | 872 | if (FunInfo->mayAlias(ValA, LocA.Size, ValB, LocB.Size)) | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 873 | return MayAlias; | 
|  | 874 | return NoAlias; | 
|  | 875 | } | 
|  | 876 |  | 
|  | 877 | AliasResult CFLAndersAAResult::alias(const MemoryLocation &LocA, | 
|  | 878 | const MemoryLocation &LocB) { | 
|  | 879 | if (LocA.Ptr == LocB.Ptr) | 
| Nuno Lopes | 7829506 | 2017-08-09 17:02:18 +0000 | [diff] [blame] | 880 | return MustAlias; | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 881 |  | 
|  | 882 | // Comparisons between global variables and other constants should be | 
|  | 883 | // handled by BasicAA. | 
|  | 884 | // CFLAndersAA may report NoAlias when comparing a GlobalValue and | 
|  | 885 | // ConstantExpr, but every query needs to have at least one Value tied to a | 
|  | 886 | // Function, and neither GlobalValues nor ConstantExprs are. | 
|  | 887 | if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr)) | 
|  | 888 | return AAResultBase::alias(LocA, LocB); | 
|  | 889 |  | 
|  | 890 | AliasResult QueryResult = query(LocA, LocB); | 
|  | 891 | if (QueryResult == MayAlias) | 
|  | 892 | return AAResultBase::alias(LocA, LocB); | 
|  | 893 |  | 
|  | 894 | return QueryResult; | 
|  | 895 | } | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 896 |  | 
| Chandler Carruth | dab4eae | 2016-11-23 17:53:26 +0000 | [diff] [blame] | 897 | AnalysisKey CFLAndersAA::Key; | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 898 |  | 
| Sean Silva | 36e0d01 | 2016-08-09 00:28:15 +0000 | [diff] [blame] | 899 | CFLAndersAAResult CFLAndersAA::run(Function &F, FunctionAnalysisManager &AM) { | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 900 | return CFLAndersAAResult(AM.getResult<TargetLibraryAnalysis>(F)); | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 901 | } | 
|  | 902 |  | 
|  | 903 | char CFLAndersAAWrapperPass::ID = 0; | 
|  | 904 | INITIALIZE_PASS(CFLAndersAAWrapperPass, "cfl-anders-aa", | 
|  | 905 | "Inclusion-Based CFL Alias Analysis", false, true) | 
|  | 906 |  | 
|  | 907 | ImmutablePass *llvm::createCFLAndersAAWrapperPass() { | 
|  | 908 | return new CFLAndersAAWrapperPass(); | 
|  | 909 | } | 
|  | 910 |  | 
|  | 911 | CFLAndersAAWrapperPass::CFLAndersAAWrapperPass() : ImmutablePass(ID) { | 
|  | 912 | initializeCFLAndersAAWrapperPassPass(*PassRegistry::getPassRegistry()); | 
|  | 913 | } | 
|  | 914 |  | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 915 | void CFLAndersAAWrapperPass::initializePass() { | 
|  | 916 | auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>(); | 
|  | 917 | Result.reset(new CFLAndersAAResult(TLIWP.getTLI())); | 
|  | 918 | } | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 919 |  | 
|  | 920 | void CFLAndersAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | 921 | AU.setPreservesAll(); | 
| George Burgess IV | 6d30aa0 | 2016-07-15 19:53:25 +0000 | [diff] [blame] | 922 | AU.addRequired<TargetLibraryInfoWrapperPass>(); | 
| George Burgess IV | bfa401e | 2016-07-06 00:26:41 +0000 | [diff] [blame] | 923 | } |