Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [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 |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file defines the generic AliasAnalysis interface, which is used as the |
| 10 | // common interface used by all clients of alias analysis information, and |
| 11 | // implemented by all alias analysis implementations. Mod/Ref information is |
| 12 | // also captured by this interface. |
| 13 | // |
| 14 | // Implementations of this interface must implement the various virtual methods, |
| 15 | // which automatically provides functionality for the entire suite of client |
| 16 | // APIs. |
| 17 | // |
| 18 | // This API identifies memory regions with the MemoryLocation class. The pointer |
| 19 | // component specifies the base memory address of the region. The Size specifies |
| 20 | // the maximum size (in address units) of the memory region, or |
| 21 | // MemoryLocation::UnknownSize if the size is not known. The TBAA tag |
| 22 | // identifies the "type" of the memory reference; see the |
| 23 | // TypeBasedAliasAnalysis class for details. |
| 24 | // |
| 25 | // Some non-obvious details include: |
| 26 | // - Pointers that point to two completely different objects in memory never |
| 27 | // alias, regardless of the value of the Size component. |
| 28 | // - NoAlias doesn't imply inequal pointers. The most obvious example of this |
| 29 | // is two pointers to constant memory. Even if they are equal, constant |
| 30 | // memory is never stored to, so there will never be any dependencies. |
| 31 | // In this and other situations, the pointers may be both NoAlias and |
| 32 | // MustAlias at the same time. The current API can only return one result, |
| 33 | // though this is rarely a problem in practice. |
| 34 | // |
| 35 | //===----------------------------------------------------------------------===// |
| 36 | |
| 37 | #ifndef LLVM_ANALYSIS_ALIASANALYSIS_H |
| 38 | #define LLVM_ANALYSIS_ALIASANALYSIS_H |
| 39 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 40 | #include "llvm/ADT/DenseMap.h" |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 41 | #include "llvm/ADT/None.h" |
| 42 | #include "llvm/ADT/Optional.h" |
| 43 | #include "llvm/ADT/SmallVector.h" |
| 44 | #include "llvm/Analysis/MemoryLocation.h" |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 45 | #include "llvm/IR/PassManager.h" |
| 46 | #include "llvm/Pass.h" |
| 47 | #include <cstdint> |
| 48 | #include <functional> |
| 49 | #include <memory> |
| 50 | #include <vector> |
| 51 | |
| 52 | namespace llvm { |
| 53 | |
| 54 | class AnalysisUsage; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 55 | class AtomicCmpXchgInst; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 56 | class BasicAAResult; |
| 57 | class BasicBlock; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 58 | class CatchPadInst; |
| 59 | class CatchReturnInst; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 60 | class DominatorTree; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 61 | class FenceInst; |
| 62 | class Function; |
| 63 | class InvokeInst; |
| 64 | class PreservedAnalyses; |
| 65 | class TargetLibraryInfo; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 66 | class Value; |
| 67 | |
| 68 | /// The possible results of an alias query. |
| 69 | /// |
| 70 | /// These results are always computed between two MemoryLocation objects as |
| 71 | /// a query to some alias analysis. |
| 72 | /// |
| 73 | /// Note that these are unscoped enumerations because we would like to support |
| 74 | /// implicitly testing a result for the existence of any possible aliasing with |
| 75 | /// a conversion to bool, but an "enum class" doesn't support this. The |
| 76 | /// canonical names from the literature are suffixed and unique anyways, and so |
| 77 | /// they serve as global constants in LLVM for these results. |
| 78 | /// |
| 79 | /// See docs/AliasAnalysis.html for more information on the specific meanings |
| 80 | /// of these values. |
| 81 | enum AliasResult : uint8_t { |
| 82 | /// The two locations do not alias at all. |
| 83 | /// |
| 84 | /// This value is arranged to convert to false, while all other values |
| 85 | /// convert to true. This allows a boolean context to convert the result to |
| 86 | /// a binary flag indicating whether there is the possibility of aliasing. |
| 87 | NoAlias = 0, |
| 88 | /// The two locations may or may not alias. This is the least precise result. |
| 89 | MayAlias, |
| 90 | /// The two locations alias, but only due to a partial overlap. |
| 91 | PartialAlias, |
| 92 | /// The two locations precisely alias each other. |
| 93 | MustAlias, |
| 94 | }; |
| 95 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 96 | /// << operator for AliasResult. |
| 97 | raw_ostream &operator<<(raw_ostream &OS, AliasResult AR); |
| 98 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 99 | /// Flags indicating whether a memory access modifies or references memory. |
| 100 | /// |
| 101 | /// This is no access at all, a modification, a reference, or both |
| 102 | /// a modification and a reference. These are specifically structured such that |
| 103 | /// they form a three bit matrix and bit-tests for 'mod' or 'ref' or 'must' |
| 104 | /// work with any of the possible values. |
| 105 | enum class ModRefInfo : uint8_t { |
| 106 | /// Must is provided for completeness, but no routines will return only |
| 107 | /// Must today. See definition of Must below. |
| 108 | Must = 0, |
| 109 | /// The access may reference the value stored in memory, |
| 110 | /// a mustAlias relation was found, and no mayAlias or partialAlias found. |
| 111 | MustRef = 1, |
| 112 | /// The access may modify the value stored in memory, |
| 113 | /// a mustAlias relation was found, and no mayAlias or partialAlias found. |
| 114 | MustMod = 2, |
| 115 | /// The access may reference, modify or both the value stored in memory, |
| 116 | /// a mustAlias relation was found, and no mayAlias or partialAlias found. |
| 117 | MustModRef = MustRef | MustMod, |
| 118 | /// The access neither references nor modifies the value stored in memory. |
| 119 | NoModRef = 4, |
| 120 | /// The access may reference the value stored in memory. |
| 121 | Ref = NoModRef | MustRef, |
| 122 | /// The access may modify the value stored in memory. |
| 123 | Mod = NoModRef | MustMod, |
| 124 | /// The access may reference and may modify the value stored in memory. |
| 125 | ModRef = Ref | Mod, |
| 126 | |
| 127 | /// About Must: |
| 128 | /// Must is set in a best effort manner. |
| 129 | /// We usually do not try our best to infer Must, instead it is merely |
| 130 | /// another piece of "free" information that is presented when available. |
| 131 | /// Must set means there was certainly a MustAlias found. For calls, |
| 132 | /// where multiple arguments are checked (argmemonly), this translates to |
| 133 | /// only MustAlias or NoAlias was found. |
| 134 | /// Must is not set for RAR accesses, even if the two locations must |
| 135 | /// alias. The reason is that two read accesses translate to an early return |
| 136 | /// of NoModRef. An additional alias check to set Must may be |
| 137 | /// expensive. Other cases may also not set Must(e.g. callCapturesBefore). |
| 138 | /// We refer to Must being *set* when the most significant bit is *cleared*. |
| 139 | /// Conversely we *clear* Must information by *setting* the Must bit to 1. |
| 140 | }; |
| 141 | |
| 142 | LLVM_NODISCARD inline bool isNoModRef(const ModRefInfo MRI) { |
| 143 | return (static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef)) == |
| 144 | static_cast<int>(ModRefInfo::Must); |
| 145 | } |
| 146 | LLVM_NODISCARD inline bool isModOrRefSet(const ModRefInfo MRI) { |
| 147 | return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef); |
| 148 | } |
| 149 | LLVM_NODISCARD inline bool isModAndRefSet(const ModRefInfo MRI) { |
| 150 | return (static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef)) == |
| 151 | static_cast<int>(ModRefInfo::MustModRef); |
| 152 | } |
| 153 | LLVM_NODISCARD inline bool isModSet(const ModRefInfo MRI) { |
| 154 | return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustMod); |
| 155 | } |
| 156 | LLVM_NODISCARD inline bool isRefSet(const ModRefInfo MRI) { |
| 157 | return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustRef); |
| 158 | } |
| 159 | LLVM_NODISCARD inline bool isMustSet(const ModRefInfo MRI) { |
| 160 | return !(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::NoModRef)); |
| 161 | } |
| 162 | |
| 163 | LLVM_NODISCARD inline ModRefInfo setMod(const ModRefInfo MRI) { |
| 164 | return ModRefInfo(static_cast<int>(MRI) | |
| 165 | static_cast<int>(ModRefInfo::MustMod)); |
| 166 | } |
| 167 | LLVM_NODISCARD inline ModRefInfo setRef(const ModRefInfo MRI) { |
| 168 | return ModRefInfo(static_cast<int>(MRI) | |
| 169 | static_cast<int>(ModRefInfo::MustRef)); |
| 170 | } |
| 171 | LLVM_NODISCARD inline ModRefInfo setMust(const ModRefInfo MRI) { |
| 172 | return ModRefInfo(static_cast<int>(MRI) & |
| 173 | static_cast<int>(ModRefInfo::MustModRef)); |
| 174 | } |
| 175 | LLVM_NODISCARD inline ModRefInfo setModAndRef(const ModRefInfo MRI) { |
| 176 | return ModRefInfo(static_cast<int>(MRI) | |
| 177 | static_cast<int>(ModRefInfo::MustModRef)); |
| 178 | } |
| 179 | LLVM_NODISCARD inline ModRefInfo clearMod(const ModRefInfo MRI) { |
| 180 | return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref)); |
| 181 | } |
| 182 | LLVM_NODISCARD inline ModRefInfo clearRef(const ModRefInfo MRI) { |
| 183 | return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod)); |
| 184 | } |
| 185 | LLVM_NODISCARD inline ModRefInfo clearMust(const ModRefInfo MRI) { |
| 186 | return ModRefInfo(static_cast<int>(MRI) | |
| 187 | static_cast<int>(ModRefInfo::NoModRef)); |
| 188 | } |
| 189 | LLVM_NODISCARD inline ModRefInfo unionModRef(const ModRefInfo MRI1, |
| 190 | const ModRefInfo MRI2) { |
| 191 | return ModRefInfo(static_cast<int>(MRI1) | static_cast<int>(MRI2)); |
| 192 | } |
| 193 | LLVM_NODISCARD inline ModRefInfo intersectModRef(const ModRefInfo MRI1, |
| 194 | const ModRefInfo MRI2) { |
| 195 | return ModRefInfo(static_cast<int>(MRI1) & static_cast<int>(MRI2)); |
| 196 | } |
| 197 | |
| 198 | /// The locations at which a function might access memory. |
| 199 | /// |
| 200 | /// These are primarily used in conjunction with the \c AccessKind bits to |
| 201 | /// describe both the nature of access and the locations of access for a |
| 202 | /// function call. |
| 203 | enum FunctionModRefLocation { |
| 204 | /// Base case is no access to memory. |
| 205 | FMRL_Nowhere = 0, |
| 206 | /// Access to memory via argument pointers. |
| 207 | FMRL_ArgumentPointees = 8, |
| 208 | /// Memory that is inaccessible via LLVM IR. |
| 209 | FMRL_InaccessibleMem = 16, |
| 210 | /// Access to any memory. |
| 211 | FMRL_Anywhere = 32 | FMRL_InaccessibleMem | FMRL_ArgumentPointees |
| 212 | }; |
| 213 | |
| 214 | /// Summary of how a function affects memory in the program. |
| 215 | /// |
| 216 | /// Loads from constant globals are not considered memory accesses for this |
| 217 | /// interface. Also, functions may freely modify stack space local to their |
| 218 | /// invocation without having to report it through these interfaces. |
| 219 | enum FunctionModRefBehavior { |
| 220 | /// This function does not perform any non-local loads or stores to memory. |
| 221 | /// |
| 222 | /// This property corresponds to the GCC 'const' attribute. |
| 223 | /// This property corresponds to the LLVM IR 'readnone' attribute. |
| 224 | /// This property corresponds to the IntrNoMem LLVM intrinsic flag. |
| 225 | FMRB_DoesNotAccessMemory = |
| 226 | FMRL_Nowhere | static_cast<int>(ModRefInfo::NoModRef), |
| 227 | |
| 228 | /// The only memory references in this function (if it has any) are |
| 229 | /// non-volatile loads from objects pointed to by its pointer-typed |
| 230 | /// arguments, with arbitrary offsets. |
| 231 | /// |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 232 | /// This property corresponds to the combination of the IntrReadMem |
| 233 | /// and IntrArgMemOnly LLVM intrinsic flags. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 234 | FMRB_OnlyReadsArgumentPointees = |
| 235 | FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::Ref), |
| 236 | |
| 237 | /// The only memory references in this function (if it has any) are |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 238 | /// non-volatile stores from objects pointed to by its pointer-typed |
| 239 | /// arguments, with arbitrary offsets. |
| 240 | /// |
| 241 | /// This property corresponds to the combination of the IntrWriteMem |
| 242 | /// and IntrArgMemOnly LLVM intrinsic flags. |
| 243 | FMRB_OnlyWritesArgumentPointees = |
| 244 | FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::Mod), |
| 245 | |
| 246 | /// The only memory references in this function (if it has any) are |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 247 | /// non-volatile loads and stores from objects pointed to by its |
| 248 | /// pointer-typed arguments, with arbitrary offsets. |
| 249 | /// |
| 250 | /// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag. |
| 251 | FMRB_OnlyAccessesArgumentPointees = |
| 252 | FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::ModRef), |
| 253 | |
| 254 | /// The only memory references in this function (if it has any) are |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 255 | /// reads of memory that is otherwise inaccessible via LLVM IR. |
| 256 | /// |
| 257 | /// This property corresponds to the LLVM IR inaccessiblememonly attribute. |
| 258 | FMRB_OnlyReadsInaccessibleMem = |
| 259 | FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::Ref), |
| 260 | |
| 261 | /// The only memory references in this function (if it has any) are |
| 262 | /// writes to memory that is otherwise inaccessible via LLVM IR. |
| 263 | /// |
| 264 | /// This property corresponds to the LLVM IR inaccessiblememonly attribute. |
| 265 | FMRB_OnlyWritesInaccessibleMem = |
| 266 | FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::Mod), |
| 267 | |
| 268 | /// The only memory references in this function (if it has any) are |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 269 | /// references of memory that is otherwise inaccessible via LLVM IR. |
| 270 | /// |
| 271 | /// This property corresponds to the LLVM IR inaccessiblememonly attribute. |
| 272 | FMRB_OnlyAccessesInaccessibleMem = |
| 273 | FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::ModRef), |
| 274 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 275 | /// The function may perform non-volatile loads from objects pointed |
| 276 | /// to by its pointer-typed arguments, with arbitrary offsets, and |
| 277 | /// it may also perform loads of memory that is otherwise |
| 278 | /// inaccessible via LLVM IR. |
| 279 | /// |
| 280 | /// This property corresponds to the LLVM IR |
| 281 | /// inaccessiblemem_or_argmemonly attribute. |
| 282 | FMRB_OnlyReadsInaccessibleOrArgMem = FMRL_InaccessibleMem | |
| 283 | FMRL_ArgumentPointees | |
| 284 | static_cast<int>(ModRefInfo::Ref), |
| 285 | |
| 286 | /// The function may perform non-volatile stores to objects pointed |
| 287 | /// to by its pointer-typed arguments, with arbitrary offsets, and |
| 288 | /// it may also perform stores of memory that is otherwise |
| 289 | /// inaccessible via LLVM IR. |
| 290 | /// |
| 291 | /// This property corresponds to the LLVM IR |
| 292 | /// inaccessiblemem_or_argmemonly attribute. |
| 293 | FMRB_OnlyWritesInaccessibleOrArgMem = FMRL_InaccessibleMem | |
| 294 | FMRL_ArgumentPointees | |
| 295 | static_cast<int>(ModRefInfo::Mod), |
| 296 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 297 | /// The function may perform non-volatile loads and stores of objects |
| 298 | /// pointed to by its pointer-typed arguments, with arbitrary offsets, and |
| 299 | /// it may also perform loads and stores of memory that is otherwise |
| 300 | /// inaccessible via LLVM IR. |
| 301 | /// |
| 302 | /// This property corresponds to the LLVM IR |
| 303 | /// inaccessiblemem_or_argmemonly attribute. |
| 304 | FMRB_OnlyAccessesInaccessibleOrArgMem = FMRL_InaccessibleMem | |
| 305 | FMRL_ArgumentPointees | |
| 306 | static_cast<int>(ModRefInfo::ModRef), |
| 307 | |
| 308 | /// This function does not perform any non-local stores or volatile loads, |
| 309 | /// but may read from any memory location. |
| 310 | /// |
| 311 | /// This property corresponds to the GCC 'pure' attribute. |
| 312 | /// This property corresponds to the LLVM IR 'readonly' attribute. |
| 313 | /// This property corresponds to the IntrReadMem LLVM intrinsic flag. |
| 314 | FMRB_OnlyReadsMemory = FMRL_Anywhere | static_cast<int>(ModRefInfo::Ref), |
| 315 | |
| 316 | // This function does not read from memory anywhere, but may write to any |
| 317 | // memory location. |
| 318 | // |
| 319 | // This property corresponds to the LLVM IR 'writeonly' attribute. |
| 320 | // This property corresponds to the IntrWriteMem LLVM intrinsic flag. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 321 | FMRB_OnlyWritesMemory = FMRL_Anywhere | static_cast<int>(ModRefInfo::Mod), |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 322 | |
| 323 | /// This indicates that the function could not be classified into one of the |
| 324 | /// behaviors above. |
| 325 | FMRB_UnknownModRefBehavior = |
| 326 | FMRL_Anywhere | static_cast<int>(ModRefInfo::ModRef) |
| 327 | }; |
| 328 | |
| 329 | // Wrapper method strips bits significant only in FunctionModRefBehavior, |
| 330 | // to obtain a valid ModRefInfo. The benefit of using the wrapper is that if |
| 331 | // ModRefInfo enum changes, the wrapper can be updated to & with the new enum |
| 332 | // entry with all bits set to 1. |
| 333 | LLVM_NODISCARD inline ModRefInfo |
| 334 | createModRefInfo(const FunctionModRefBehavior FMRB) { |
| 335 | return ModRefInfo(FMRB & static_cast<int>(ModRefInfo::ModRef)); |
| 336 | } |
| 337 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 338 | /// This class stores info we want to provide to or retain within an alias |
| 339 | /// query. By default, the root query is stateless and starts with a freshly |
| 340 | /// constructed info object. Specific alias analyses can use this query info to |
| 341 | /// store per-query state that is important for recursive or nested queries to |
| 342 | /// avoid recomputing. To enable preserving this state across multiple queries |
| 343 | /// where safe (due to the IR not changing), use a `BatchAAResults` wrapper. |
| 344 | /// The information stored in an `AAQueryInfo` is currently limitted to the |
| 345 | /// caches used by BasicAA, but can further be extended to fit other AA needs. |
| 346 | class AAQueryInfo { |
| 347 | public: |
| 348 | using LocPair = std::pair<MemoryLocation, MemoryLocation>; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 349 | struct CacheEntry { |
| 350 | AliasResult Result; |
| 351 | /// Number of times a NoAlias assumption has been used. |
| 352 | /// 0 for assumptions that have not been used, -1 for definitive results. |
| 353 | int NumAssumptionUses; |
| 354 | /// Whether this is a definitive (non-assumption) result. |
| 355 | bool isDefinitive() const { return NumAssumptionUses < 0; } |
| 356 | }; |
| 357 | using AliasCacheT = SmallDenseMap<LocPair, CacheEntry, 8>; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 358 | AliasCacheT AliasCache; |
| 359 | |
| 360 | using IsCapturedCacheT = SmallDenseMap<const Value *, bool, 8>; |
| 361 | IsCapturedCacheT IsCapturedCache; |
| 362 | |
| 363 | AAQueryInfo() : AliasCache(), IsCapturedCache() {} |
| 364 | }; |
| 365 | |
| 366 | class BatchAAResults; |
| 367 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 368 | class AAResults { |
| 369 | public: |
| 370 | // Make these results default constructable and movable. We have to spell |
| 371 | // these out because MSVC won't synthesize them. |
| 372 | AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {} |
| 373 | AAResults(AAResults &&Arg); |
| 374 | ~AAResults(); |
| 375 | |
| 376 | /// Register a specific AA result. |
| 377 | template <typename AAResultT> void addAAResult(AAResultT &AAResult) { |
| 378 | // FIXME: We should use a much lighter weight system than the usual |
| 379 | // polymorphic pattern because we don't own AAResult. It should |
| 380 | // ideally involve two pointers and no separate allocation. |
| 381 | AAs.emplace_back(new Model<AAResultT>(AAResult, *this)); |
| 382 | } |
| 383 | |
| 384 | /// Register a function analysis ID that the results aggregation depends on. |
| 385 | /// |
| 386 | /// This is used in the new pass manager to implement the invalidation logic |
| 387 | /// where we must invalidate the results aggregation if any of our component |
| 388 | /// analyses become invalid. |
| 389 | void addAADependencyID(AnalysisKey *ID) { AADeps.push_back(ID); } |
| 390 | |
| 391 | /// Handle invalidation events in the new pass manager. |
| 392 | /// |
| 393 | /// The aggregation is invalidated if any of the underlying analyses is |
| 394 | /// invalidated. |
| 395 | bool invalidate(Function &F, const PreservedAnalyses &PA, |
| 396 | FunctionAnalysisManager::Invalidator &Inv); |
| 397 | |
| 398 | //===--------------------------------------------------------------------===// |
| 399 | /// \name Alias Queries |
| 400 | /// @{ |
| 401 | |
| 402 | /// The main low level interface to the alias analysis implementation. |
| 403 | /// Returns an AliasResult indicating whether the two pointers are aliased to |
| 404 | /// each other. This is the interface that must be implemented by specific |
| 405 | /// alias analysis implementations. |
| 406 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); |
| 407 | |
| 408 | /// A convenience wrapper around the primary \c alias interface. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 409 | AliasResult alias(const Value *V1, LocationSize V1Size, const Value *V2, |
| 410 | LocationSize V2Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 411 | return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); |
| 412 | } |
| 413 | |
| 414 | /// A convenience wrapper around the primary \c alias interface. |
| 415 | AliasResult alias(const Value *V1, const Value *V2) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 416 | return alias(MemoryLocation::getBeforeOrAfter(V1), |
| 417 | MemoryLocation::getBeforeOrAfter(V2)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | /// A trivial helper function to check to see if the specified pointers are |
| 421 | /// no-alias. |
| 422 | bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { |
| 423 | return alias(LocA, LocB) == NoAlias; |
| 424 | } |
| 425 | |
| 426 | /// A convenience wrapper around the \c isNoAlias helper interface. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 427 | bool isNoAlias(const Value *V1, LocationSize V1Size, const Value *V2, |
| 428 | LocationSize V2Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 429 | return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); |
| 430 | } |
| 431 | |
| 432 | /// A convenience wrapper around the \c isNoAlias helper interface. |
| 433 | bool isNoAlias(const Value *V1, const Value *V2) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 434 | return isNoAlias(MemoryLocation::getBeforeOrAfter(V1), |
| 435 | MemoryLocation::getBeforeOrAfter(V2)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 436 | } |
| 437 | |
| 438 | /// A trivial helper function to check to see if the specified pointers are |
| 439 | /// must-alias. |
| 440 | bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { |
| 441 | return alias(LocA, LocB) == MustAlias; |
| 442 | } |
| 443 | |
| 444 | /// A convenience wrapper around the \c isMustAlias helper interface. |
| 445 | bool isMustAlias(const Value *V1, const Value *V2) { |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 446 | return alias(V1, LocationSize::precise(1), V2, LocationSize::precise(1)) == |
| 447 | MustAlias; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 448 | } |
| 449 | |
| 450 | /// Checks whether the given location points to constant memory, or if |
| 451 | /// \p OrLocal is true whether it points to a local alloca. |
| 452 | bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false); |
| 453 | |
| 454 | /// A convenience wrapper around the primary \c pointsToConstantMemory |
| 455 | /// interface. |
| 456 | bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 457 | return pointsToConstantMemory(MemoryLocation::getBeforeOrAfter(P), OrLocal); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | /// @} |
| 461 | //===--------------------------------------------------------------------===// |
| 462 | /// \name Simple mod/ref information |
| 463 | /// @{ |
| 464 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 465 | /// Get the ModRef info associated with a pointer argument of a call. The |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 466 | /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note |
| 467 | /// that these bits do not necessarily account for the overall behavior of |
| 468 | /// the function, but rather only provide additional per-argument |
| 469 | /// information. This never sets ModRefInfo::Must. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 470 | ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 471 | |
| 472 | /// Return the behavior of the given call site. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 473 | FunctionModRefBehavior getModRefBehavior(const CallBase *Call); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 474 | |
| 475 | /// Return the behavior when calling the given function. |
| 476 | FunctionModRefBehavior getModRefBehavior(const Function *F); |
| 477 | |
| 478 | /// Checks if the specified call is known to never read or write memory. |
| 479 | /// |
| 480 | /// Note that if the call only reads from known-constant memory, it is also |
| 481 | /// legal to return true. Also, calls that unwind the stack are legal for |
| 482 | /// this predicate. |
| 483 | /// |
| 484 | /// Many optimizations (such as CSE and LICM) can be performed on such calls |
| 485 | /// without worrying about aliasing properties, and many calls have this |
| 486 | /// property (e.g. calls to 'sin' and 'cos'). |
| 487 | /// |
| 488 | /// This property corresponds to the GCC 'const' attribute. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 489 | bool doesNotAccessMemory(const CallBase *Call) { |
| 490 | return getModRefBehavior(Call) == FMRB_DoesNotAccessMemory; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 491 | } |
| 492 | |
| 493 | /// Checks if the specified function is known to never read or write memory. |
| 494 | /// |
| 495 | /// Note that if the function only reads from known-constant memory, it is |
| 496 | /// also legal to return true. Also, function that unwind the stack are legal |
| 497 | /// for this predicate. |
| 498 | /// |
| 499 | /// Many optimizations (such as CSE and LICM) can be performed on such calls |
| 500 | /// to such functions without worrying about aliasing properties, and many |
| 501 | /// functions have this property (e.g. 'sin' and 'cos'). |
| 502 | /// |
| 503 | /// This property corresponds to the GCC 'const' attribute. |
| 504 | bool doesNotAccessMemory(const Function *F) { |
| 505 | return getModRefBehavior(F) == FMRB_DoesNotAccessMemory; |
| 506 | } |
| 507 | |
| 508 | /// Checks if the specified call is known to only read from non-volatile |
| 509 | /// memory (or not access memory at all). |
| 510 | /// |
| 511 | /// Calls that unwind the stack are legal for this predicate. |
| 512 | /// |
| 513 | /// This property allows many common optimizations to be performed in the |
| 514 | /// absence of interfering store instructions, such as CSE of strlen calls. |
| 515 | /// |
| 516 | /// This property corresponds to the GCC 'pure' attribute. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 517 | bool onlyReadsMemory(const CallBase *Call) { |
| 518 | return onlyReadsMemory(getModRefBehavior(Call)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 519 | } |
| 520 | |
| 521 | /// Checks if the specified function is known to only read from non-volatile |
| 522 | /// memory (or not access memory at all). |
| 523 | /// |
| 524 | /// Functions that unwind the stack are legal for this predicate. |
| 525 | /// |
| 526 | /// This property allows many common optimizations to be performed in the |
| 527 | /// absence of interfering store instructions, such as CSE of strlen calls. |
| 528 | /// |
| 529 | /// This property corresponds to the GCC 'pure' attribute. |
| 530 | bool onlyReadsMemory(const Function *F) { |
| 531 | return onlyReadsMemory(getModRefBehavior(F)); |
| 532 | } |
| 533 | |
| 534 | /// Checks if functions with the specified behavior are known to only read |
| 535 | /// from non-volatile memory (or not access memory at all). |
| 536 | static bool onlyReadsMemory(FunctionModRefBehavior MRB) { |
| 537 | return !isModSet(createModRefInfo(MRB)); |
| 538 | } |
| 539 | |
| 540 | /// Checks if functions with the specified behavior are known to only write |
| 541 | /// memory (or not access memory at all). |
| 542 | static bool doesNotReadMemory(FunctionModRefBehavior MRB) { |
| 543 | return !isRefSet(createModRefInfo(MRB)); |
| 544 | } |
| 545 | |
| 546 | /// Checks if functions with the specified behavior are known to read and |
| 547 | /// write at most from objects pointed to by their pointer-typed arguments |
| 548 | /// (with arbitrary offsets). |
| 549 | static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 550 | return !((unsigned)MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 551 | } |
| 552 | |
| 553 | /// Checks if functions with the specified behavior are known to potentially |
| 554 | /// read or write from objects pointed to be their pointer-typed arguments |
| 555 | /// (with arbitrary offsets). |
| 556 | static bool doesAccessArgPointees(FunctionModRefBehavior MRB) { |
| 557 | return isModOrRefSet(createModRefInfo(MRB)) && |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 558 | ((unsigned)MRB & FMRL_ArgumentPointees); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 559 | } |
| 560 | |
| 561 | /// Checks if functions with the specified behavior are known to read and |
| 562 | /// write at most from memory that is inaccessible from LLVM IR. |
| 563 | static bool onlyAccessesInaccessibleMem(FunctionModRefBehavior MRB) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 564 | return !((unsigned)MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 565 | } |
| 566 | |
| 567 | /// Checks if functions with the specified behavior are known to potentially |
| 568 | /// read or write from memory that is inaccessible from LLVM IR. |
| 569 | static bool doesAccessInaccessibleMem(FunctionModRefBehavior MRB) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 570 | return isModOrRefSet(createModRefInfo(MRB)) && |
| 571 | ((unsigned)MRB & FMRL_InaccessibleMem); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 572 | } |
| 573 | |
| 574 | /// Checks if functions with the specified behavior are known to read and |
| 575 | /// write at most from memory that is inaccessible from LLVM IR or objects |
| 576 | /// pointed to by their pointer-typed arguments (with arbitrary offsets). |
| 577 | static bool onlyAccessesInaccessibleOrArgMem(FunctionModRefBehavior MRB) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 578 | return !((unsigned)MRB & FMRL_Anywhere & |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 579 | ~(FMRL_InaccessibleMem | FMRL_ArgumentPointees)); |
| 580 | } |
| 581 | |
| 582 | /// getModRefInfo (for call sites) - Return information about whether |
| 583 | /// a particular call site modifies or reads the specified memory location. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 584 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 585 | |
| 586 | /// getModRefInfo (for call sites) - A convenience wrapper. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 587 | ModRefInfo getModRefInfo(const CallBase *Call, const Value *P, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 588 | LocationSize Size) { |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 589 | return getModRefInfo(Call, MemoryLocation(P, Size)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 590 | } |
| 591 | |
| 592 | /// getModRefInfo (for loads) - Return information about whether |
| 593 | /// a particular load modifies or reads the specified memory location. |
| 594 | ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc); |
| 595 | |
| 596 | /// getModRefInfo (for loads) - A convenience wrapper. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 597 | ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, |
| 598 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 599 | return getModRefInfo(L, MemoryLocation(P, Size)); |
| 600 | } |
| 601 | |
| 602 | /// getModRefInfo (for stores) - Return information about whether |
| 603 | /// a particular store modifies or reads the specified memory location. |
| 604 | ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc); |
| 605 | |
| 606 | /// getModRefInfo (for stores) - A convenience wrapper. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 607 | ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, |
| 608 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 609 | return getModRefInfo(S, MemoryLocation(P, Size)); |
| 610 | } |
| 611 | |
| 612 | /// getModRefInfo (for fences) - Return information about whether |
| 613 | /// a particular store modifies or reads the specified memory location. |
| 614 | ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc); |
| 615 | |
| 616 | /// getModRefInfo (for fences) - A convenience wrapper. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 617 | ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, |
| 618 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 619 | return getModRefInfo(S, MemoryLocation(P, Size)); |
| 620 | } |
| 621 | |
| 622 | /// getModRefInfo (for cmpxchges) - Return information about whether |
| 623 | /// a particular cmpxchg modifies or reads the specified memory location. |
| 624 | ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, |
| 625 | const MemoryLocation &Loc); |
| 626 | |
| 627 | /// getModRefInfo (for cmpxchges) - A convenience wrapper. |
| 628 | ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P, |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 629 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 630 | return getModRefInfo(CX, MemoryLocation(P, Size)); |
| 631 | } |
| 632 | |
| 633 | /// getModRefInfo (for atomicrmws) - Return information about whether |
| 634 | /// a particular atomicrmw modifies or reads the specified memory location. |
| 635 | ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc); |
| 636 | |
| 637 | /// getModRefInfo (for atomicrmws) - A convenience wrapper. |
| 638 | ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P, |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 639 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 640 | return getModRefInfo(RMW, MemoryLocation(P, Size)); |
| 641 | } |
| 642 | |
| 643 | /// getModRefInfo (for va_args) - Return information about whether |
| 644 | /// a particular va_arg modifies or reads the specified memory location. |
| 645 | ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc); |
| 646 | |
| 647 | /// getModRefInfo (for va_args) - A convenience wrapper. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 648 | ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, |
| 649 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 650 | return getModRefInfo(I, MemoryLocation(P, Size)); |
| 651 | } |
| 652 | |
| 653 | /// getModRefInfo (for catchpads) - Return information about whether |
| 654 | /// a particular catchpad modifies or reads the specified memory location. |
| 655 | ModRefInfo getModRefInfo(const CatchPadInst *I, const MemoryLocation &Loc); |
| 656 | |
| 657 | /// getModRefInfo (for catchpads) - A convenience wrapper. |
| 658 | ModRefInfo getModRefInfo(const CatchPadInst *I, const Value *P, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 659 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 660 | return getModRefInfo(I, MemoryLocation(P, Size)); |
| 661 | } |
| 662 | |
| 663 | /// getModRefInfo (for catchrets) - Return information about whether |
| 664 | /// a particular catchret modifies or reads the specified memory location. |
| 665 | ModRefInfo getModRefInfo(const CatchReturnInst *I, const MemoryLocation &Loc); |
| 666 | |
| 667 | /// getModRefInfo (for catchrets) - A convenience wrapper. |
| 668 | ModRefInfo getModRefInfo(const CatchReturnInst *I, const Value *P, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 669 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 670 | return getModRefInfo(I, MemoryLocation(P, Size)); |
| 671 | } |
| 672 | |
| 673 | /// Check whether or not an instruction may read or write the optionally |
| 674 | /// specified memory location. |
| 675 | /// |
| 676 | /// |
| 677 | /// An instruction that doesn't read or write memory may be trivially LICM'd |
| 678 | /// for example. |
| 679 | /// |
| 680 | /// For function calls, this delegates to the alias-analysis specific |
| 681 | /// call-site mod-ref behavior queries. Otherwise it delegates to the specific |
| 682 | /// helpers above. |
| 683 | ModRefInfo getModRefInfo(const Instruction *I, |
| 684 | const Optional<MemoryLocation> &OptLoc) { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 685 | AAQueryInfo AAQIP; |
| 686 | return getModRefInfo(I, OptLoc, AAQIP); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 687 | } |
| 688 | |
| 689 | /// A convenience wrapper for constructing the memory location. |
| 690 | ModRefInfo getModRefInfo(const Instruction *I, const Value *P, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 691 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 692 | return getModRefInfo(I, MemoryLocation(P, Size)); |
| 693 | } |
| 694 | |
| 695 | /// Return information about whether a call and an instruction may refer to |
| 696 | /// the same memory locations. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 697 | ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 698 | |
| 699 | /// Return information about whether two call sites may refer to the same set |
| 700 | /// of memory locations. See the AA documentation for details: |
| 701 | /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 702 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 703 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 704 | /// Return information about whether a particular call site modifies |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 705 | /// or reads the specified memory location \p MemLoc before instruction \p I |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 706 | /// in a BasicBlock. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 707 | /// Early exits in callCapturesBefore may lead to ModRefInfo::Must not being |
| 708 | /// set. |
| 709 | ModRefInfo callCapturesBefore(const Instruction *I, |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 710 | const MemoryLocation &MemLoc, DominatorTree *DT); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 711 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 712 | /// A convenience wrapper to synthesize a memory location. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 713 | ModRefInfo callCapturesBefore(const Instruction *I, const Value *P, |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 714 | LocationSize Size, DominatorTree *DT) { |
| 715 | return callCapturesBefore(I, MemoryLocation(P, Size), DT); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 716 | } |
| 717 | |
| 718 | /// @} |
| 719 | //===--------------------------------------------------------------------===// |
| 720 | /// \name Higher level methods for querying mod/ref information. |
| 721 | /// @{ |
| 722 | |
| 723 | /// Check if it is possible for execution of the specified basic block to |
| 724 | /// modify the location Loc. |
| 725 | bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc); |
| 726 | |
| 727 | /// A convenience wrapper synthesizing a memory location. |
| 728 | bool canBasicBlockModify(const BasicBlock &BB, const Value *P, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 729 | LocationSize Size) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 730 | return canBasicBlockModify(BB, MemoryLocation(P, Size)); |
| 731 | } |
| 732 | |
| 733 | /// Check if it is possible for the execution of the specified instructions |
| 734 | /// to mod\ref (according to the mode) the location Loc. |
| 735 | /// |
| 736 | /// The instructions to consider are all of the instructions in the range of |
| 737 | /// [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. |
| 738 | bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, |
| 739 | const MemoryLocation &Loc, |
| 740 | const ModRefInfo Mode); |
| 741 | |
| 742 | /// A convenience wrapper synthesizing a memory location. |
| 743 | bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 744 | const Value *Ptr, LocationSize Size, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 745 | const ModRefInfo Mode) { |
| 746 | return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); |
| 747 | } |
| 748 | |
| 749 | private: |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 750 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, |
| 751 | AAQueryInfo &AAQI); |
| 752 | bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, |
| 753 | bool OrLocal = false); |
| 754 | ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call2, |
| 755 | AAQueryInfo &AAQIP); |
| 756 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, |
| 757 | AAQueryInfo &AAQI); |
| 758 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, |
| 759 | AAQueryInfo &AAQI); |
| 760 | ModRefInfo getModRefInfo(const VAArgInst *V, const MemoryLocation &Loc, |
| 761 | AAQueryInfo &AAQI); |
| 762 | ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc, |
| 763 | AAQueryInfo &AAQI); |
| 764 | ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc, |
| 765 | AAQueryInfo &AAQI); |
| 766 | ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc, |
| 767 | AAQueryInfo &AAQI); |
| 768 | ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, |
| 769 | const MemoryLocation &Loc, AAQueryInfo &AAQI); |
| 770 | ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc, |
| 771 | AAQueryInfo &AAQI); |
| 772 | ModRefInfo getModRefInfo(const CatchPadInst *I, const MemoryLocation &Loc, |
| 773 | AAQueryInfo &AAQI); |
| 774 | ModRefInfo getModRefInfo(const CatchReturnInst *I, const MemoryLocation &Loc, |
| 775 | AAQueryInfo &AAQI); |
| 776 | ModRefInfo getModRefInfo(const Instruction *I, |
| 777 | const Optional<MemoryLocation> &OptLoc, |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 778 | AAQueryInfo &AAQIP); |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 779 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 780 | class Concept; |
| 781 | |
| 782 | template <typename T> class Model; |
| 783 | |
| 784 | template <typename T> friend class AAResultBase; |
| 785 | |
| 786 | const TargetLibraryInfo &TLI; |
| 787 | |
| 788 | std::vector<std::unique_ptr<Concept>> AAs; |
| 789 | |
| 790 | std::vector<AnalysisKey *> AADeps; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 791 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 792 | /// Query depth used to distinguish recursive queries. |
| 793 | unsigned Depth = 0; |
| 794 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 795 | friend class BatchAAResults; |
| 796 | }; |
| 797 | |
| 798 | /// This class is a wrapper over an AAResults, and it is intended to be used |
| 799 | /// only when there are no IR changes inbetween queries. BatchAAResults is |
| 800 | /// reusing the same `AAQueryInfo` to preserve the state across queries, |
| 801 | /// esentially making AA work in "batch mode". The internal state cannot be |
| 802 | /// cleared, so to go "out-of-batch-mode", the user must either use AAResults, |
| 803 | /// or create a new BatchAAResults. |
| 804 | class BatchAAResults { |
| 805 | AAResults &AA; |
| 806 | AAQueryInfo AAQI; |
| 807 | |
| 808 | public: |
| 809 | BatchAAResults(AAResults &AAR) : AA(AAR), AAQI() {} |
| 810 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { |
| 811 | return AA.alias(LocA, LocB, AAQI); |
| 812 | } |
| 813 | bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false) { |
| 814 | return AA.pointsToConstantMemory(Loc, AAQI, OrLocal); |
| 815 | } |
| 816 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { |
| 817 | return AA.getModRefInfo(Call, Loc, AAQI); |
| 818 | } |
| 819 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { |
| 820 | return AA.getModRefInfo(Call1, Call2, AAQI); |
| 821 | } |
| 822 | ModRefInfo getModRefInfo(const Instruction *I, |
| 823 | const Optional<MemoryLocation> &OptLoc) { |
| 824 | return AA.getModRefInfo(I, OptLoc, AAQI); |
| 825 | } |
| 826 | ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call2) { |
| 827 | return AA.getModRefInfo(I, Call2, AAQI); |
| 828 | } |
| 829 | ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { |
| 830 | return AA.getArgModRefInfo(Call, ArgIdx); |
| 831 | } |
| 832 | FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { |
| 833 | return AA.getModRefBehavior(Call); |
| 834 | } |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 835 | bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { |
| 836 | return alias(LocA, LocB) == MustAlias; |
| 837 | } |
| 838 | bool isMustAlias(const Value *V1, const Value *V2) { |
| 839 | return alias(MemoryLocation(V1, LocationSize::precise(1)), |
| 840 | MemoryLocation(V2, LocationSize::precise(1))) == MustAlias; |
| 841 | } |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 842 | }; |
| 843 | |
| 844 | /// Temporary typedef for legacy code that uses a generic \c AliasAnalysis |
| 845 | /// pointer or reference. |
| 846 | using AliasAnalysis = AAResults; |
| 847 | |
| 848 | /// A private abstract base class describing the concept of an individual alias |
| 849 | /// analysis implementation. |
| 850 | /// |
| 851 | /// This interface is implemented by any \c Model instantiation. It is also the |
| 852 | /// interface which a type used to instantiate the model must provide. |
| 853 | /// |
| 854 | /// All of these methods model methods by the same name in the \c |
| 855 | /// AAResults class. Only differences and specifics to how the |
| 856 | /// implementations are called are documented here. |
| 857 | class AAResults::Concept { |
| 858 | public: |
| 859 | virtual ~Concept() = 0; |
| 860 | |
| 861 | /// An update API used internally by the AAResults to provide |
| 862 | /// a handle back to the top level aggregation. |
| 863 | virtual void setAAResults(AAResults *NewAAR) = 0; |
| 864 | |
| 865 | //===--------------------------------------------------------------------===// |
| 866 | /// \name Alias Queries |
| 867 | /// @{ |
| 868 | |
| 869 | /// The main low level interface to the alias analysis implementation. |
| 870 | /// Returns an AliasResult indicating whether the two pointers are aliased to |
| 871 | /// each other. This is the interface that must be implemented by specific |
| 872 | /// alias analysis implementations. |
| 873 | virtual AliasResult alias(const MemoryLocation &LocA, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 874 | const MemoryLocation &LocB, AAQueryInfo &AAQI) = 0; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 875 | |
| 876 | /// Checks whether the given location points to constant memory, or if |
| 877 | /// \p OrLocal is true whether it points to a local alloca. |
| 878 | virtual bool pointsToConstantMemory(const MemoryLocation &Loc, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 879 | AAQueryInfo &AAQI, bool OrLocal) = 0; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 880 | |
| 881 | /// @} |
| 882 | //===--------------------------------------------------------------------===// |
| 883 | /// \name Simple mod/ref information |
| 884 | /// @{ |
| 885 | |
| 886 | /// Get the ModRef info associated with a pointer argument of a callsite. The |
| 887 | /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note |
| 888 | /// that these bits do not necessarily account for the overall behavior of |
| 889 | /// the function, but rather only provide additional per-argument |
| 890 | /// information. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 891 | virtual ModRefInfo getArgModRefInfo(const CallBase *Call, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 892 | unsigned ArgIdx) = 0; |
| 893 | |
| 894 | /// Return the behavior of the given call site. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 895 | virtual FunctionModRefBehavior getModRefBehavior(const CallBase *Call) = 0; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 896 | |
| 897 | /// Return the behavior when calling the given function. |
| 898 | virtual FunctionModRefBehavior getModRefBehavior(const Function *F) = 0; |
| 899 | |
| 900 | /// getModRefInfo (for call sites) - Return information about whether |
| 901 | /// a particular call site modifies or reads the specified memory location. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 902 | virtual ModRefInfo getModRefInfo(const CallBase *Call, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 903 | const MemoryLocation &Loc, |
| 904 | AAQueryInfo &AAQI) = 0; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 905 | |
| 906 | /// Return information about whether two call sites may refer to the same set |
| 907 | /// of memory locations. See the AA documentation for details: |
| 908 | /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 909 | virtual ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, |
| 910 | AAQueryInfo &AAQI) = 0; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 911 | |
| 912 | /// @} |
| 913 | }; |
| 914 | |
| 915 | /// A private class template which derives from \c Concept and wraps some other |
| 916 | /// type. |
| 917 | /// |
| 918 | /// This models the concept by directly forwarding each interface point to the |
| 919 | /// wrapped type which must implement a compatible interface. This provides |
| 920 | /// a type erased binding. |
| 921 | template <typename AAResultT> class AAResults::Model final : public Concept { |
| 922 | AAResultT &Result; |
| 923 | |
| 924 | public: |
| 925 | explicit Model(AAResultT &Result, AAResults &AAR) : Result(Result) { |
| 926 | Result.setAAResults(&AAR); |
| 927 | } |
| 928 | ~Model() override = default; |
| 929 | |
| 930 | void setAAResults(AAResults *NewAAR) override { Result.setAAResults(NewAAR); } |
| 931 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 932 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, |
| 933 | AAQueryInfo &AAQI) override { |
| 934 | return Result.alias(LocA, LocB, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 935 | } |
| 936 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 937 | bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 938 | bool OrLocal) override { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 939 | return Result.pointsToConstantMemory(Loc, AAQI, OrLocal); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 940 | } |
| 941 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 942 | ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override { |
| 943 | return Result.getArgModRefInfo(Call, ArgIdx); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 944 | } |
| 945 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 946 | FunctionModRefBehavior getModRefBehavior(const CallBase *Call) override { |
| 947 | return Result.getModRefBehavior(Call); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 948 | } |
| 949 | |
| 950 | FunctionModRefBehavior getModRefBehavior(const Function *F) override { |
| 951 | return Result.getModRefBehavior(F); |
| 952 | } |
| 953 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 954 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, |
| 955 | AAQueryInfo &AAQI) override { |
| 956 | return Result.getModRefInfo(Call, Loc, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 957 | } |
| 958 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 959 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, |
| 960 | AAQueryInfo &AAQI) override { |
| 961 | return Result.getModRefInfo(Call1, Call2, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 962 | } |
| 963 | }; |
| 964 | |
| 965 | /// A CRTP-driven "mixin" base class to help implement the function alias |
| 966 | /// analysis results concept. |
| 967 | /// |
| 968 | /// Because of the nature of many alias analysis implementations, they often |
| 969 | /// only implement a subset of the interface. This base class will attempt to |
| 970 | /// implement the remaining portions of the interface in terms of simpler forms |
| 971 | /// of the interface where possible, and otherwise provide conservatively |
| 972 | /// correct fallback implementations. |
| 973 | /// |
| 974 | /// Implementors of an alias analysis should derive from this CRTP, and then |
| 975 | /// override specific methods that they wish to customize. There is no need to |
| 976 | /// use virtual anywhere, the CRTP base class does static dispatch to the |
| 977 | /// derived type passed into it. |
| 978 | template <typename DerivedT> class AAResultBase { |
| 979 | // Expose some parts of the interface only to the AAResults::Model |
| 980 | // for wrapping. Specifically, this allows the model to call our |
| 981 | // setAAResults method without exposing it as a fully public API. |
| 982 | friend class AAResults::Model<DerivedT>; |
| 983 | |
| 984 | /// A pointer to the AAResults object that this AAResult is |
| 985 | /// aggregated within. May be null if not aggregated. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 986 | AAResults *AAR = nullptr; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 987 | |
| 988 | /// Helper to dispatch calls back through the derived type. |
| 989 | DerivedT &derived() { return static_cast<DerivedT &>(*this); } |
| 990 | |
| 991 | /// A setter for the AAResults pointer, which is used to satisfy the |
| 992 | /// AAResults::Model contract. |
| 993 | void setAAResults(AAResults *NewAAR) { AAR = NewAAR; } |
| 994 | |
| 995 | protected: |
| 996 | /// This proxy class models a common pattern where we delegate to either the |
| 997 | /// top-level \c AAResults aggregation if one is registered, or to the |
| 998 | /// current result if none are registered. |
| 999 | class AAResultsProxy { |
| 1000 | AAResults *AAR; |
| 1001 | DerivedT &CurrentResult; |
| 1002 | |
| 1003 | public: |
| 1004 | AAResultsProxy(AAResults *AAR, DerivedT &CurrentResult) |
| 1005 | : AAR(AAR), CurrentResult(CurrentResult) {} |
| 1006 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1007 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, |
| 1008 | AAQueryInfo &AAQI) { |
| 1009 | return AAR ? AAR->alias(LocA, LocB, AAQI) |
| 1010 | : CurrentResult.alias(LocA, LocB, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1011 | } |
| 1012 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1013 | bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, |
| 1014 | bool OrLocal) { |
| 1015 | return AAR ? AAR->pointsToConstantMemory(Loc, AAQI, OrLocal) |
| 1016 | : CurrentResult.pointsToConstantMemory(Loc, AAQI, OrLocal); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1017 | } |
| 1018 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1019 | ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { |
| 1020 | return AAR ? AAR->getArgModRefInfo(Call, ArgIdx) |
| 1021 | : CurrentResult.getArgModRefInfo(Call, ArgIdx); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1022 | } |
| 1023 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1024 | FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { |
| 1025 | return AAR ? AAR->getModRefBehavior(Call) |
| 1026 | : CurrentResult.getModRefBehavior(Call); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1027 | } |
| 1028 | |
| 1029 | FunctionModRefBehavior getModRefBehavior(const Function *F) { |
| 1030 | return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F); |
| 1031 | } |
| 1032 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1033 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, |
| 1034 | AAQueryInfo &AAQI) { |
| 1035 | return AAR ? AAR->getModRefInfo(Call, Loc, AAQI) |
| 1036 | : CurrentResult.getModRefInfo(Call, Loc, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1037 | } |
| 1038 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1039 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, |
| 1040 | AAQueryInfo &AAQI) { |
| 1041 | return AAR ? AAR->getModRefInfo(Call1, Call2, AAQI) |
| 1042 | : CurrentResult.getModRefInfo(Call1, Call2, AAQI); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1043 | } |
| 1044 | }; |
| 1045 | |
| 1046 | explicit AAResultBase() = default; |
| 1047 | |
| 1048 | // Provide all the copy and move constructors so that derived types aren't |
| 1049 | // constrained. |
| 1050 | AAResultBase(const AAResultBase &Arg) {} |
| 1051 | AAResultBase(AAResultBase &&Arg) {} |
| 1052 | |
| 1053 | /// Get a proxy for the best AA result set to query at this time. |
| 1054 | /// |
| 1055 | /// When this result is part of a larger aggregation, this will proxy to that |
| 1056 | /// aggregation. When this result is used in isolation, it will just delegate |
| 1057 | /// back to the derived class's implementation. |
| 1058 | /// |
| 1059 | /// Note that callers of this need to take considerable care to not cause |
| 1060 | /// performance problems when they use this routine, in the case of a large |
| 1061 | /// number of alias analyses being aggregated, it can be expensive to walk |
| 1062 | /// back across the chain. |
| 1063 | AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); } |
| 1064 | |
| 1065 | public: |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1066 | AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, |
| 1067 | AAQueryInfo &AAQI) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1068 | return MayAlias; |
| 1069 | } |
| 1070 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1071 | bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, |
| 1072 | bool OrLocal) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1073 | return false; |
| 1074 | } |
| 1075 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1076 | ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1077 | return ModRefInfo::ModRef; |
| 1078 | } |
| 1079 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1080 | FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1081 | return FMRB_UnknownModRefBehavior; |
| 1082 | } |
| 1083 | |
| 1084 | FunctionModRefBehavior getModRefBehavior(const Function *F) { |
| 1085 | return FMRB_UnknownModRefBehavior; |
| 1086 | } |
| 1087 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1088 | ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, |
| 1089 | AAQueryInfo &AAQI) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1090 | return ModRefInfo::ModRef; |
| 1091 | } |
| 1092 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1093 | ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, |
| 1094 | AAQueryInfo &AAQI) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1095 | return ModRefInfo::ModRef; |
| 1096 | } |
| 1097 | }; |
| 1098 | |
| 1099 | /// Return true if this pointer is returned by a noalias function. |
| 1100 | bool isNoAliasCall(const Value *V); |
| 1101 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1102 | /// Return true if this pointer refers to a distinct and identifiable object. |
| 1103 | /// This returns true for: |
| 1104 | /// Global Variables and Functions (but not Global Aliases) |
| 1105 | /// Allocas |
| 1106 | /// ByVal and NoAlias Arguments |
| 1107 | /// NoAlias returns (e.g. calls to malloc) |
| 1108 | /// |
| 1109 | bool isIdentifiedObject(const Value *V); |
| 1110 | |
| 1111 | /// Return true if V is umabigously identified at the function-level. |
| 1112 | /// Different IdentifiedFunctionLocals can't alias. |
| 1113 | /// Further, an IdentifiedFunctionLocal can not alias with any function |
| 1114 | /// arguments other than itself, which is not necessarily true for |
| 1115 | /// IdentifiedObjects. |
| 1116 | bool isIdentifiedFunctionLocal(const Value *V); |
| 1117 | |
| 1118 | /// A manager for alias analyses. |
| 1119 | /// |
| 1120 | /// This class can have analyses registered with it and when run, it will run |
| 1121 | /// all of them and aggregate their results into single AA results interface |
| 1122 | /// that dispatches across all of the alias analysis results available. |
| 1123 | /// |
| 1124 | /// Note that the order in which analyses are registered is very significant. |
| 1125 | /// That is the order in which the results will be aggregated and queried. |
| 1126 | /// |
| 1127 | /// This manager effectively wraps the AnalysisManager for registering alias |
| 1128 | /// analyses. When you register your alias analysis with this manager, it will |
| 1129 | /// ensure the analysis itself is registered with its AnalysisManager. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1130 | /// |
| 1131 | /// The result of this analysis is only invalidated if one of the particular |
| 1132 | /// aggregated AA results end up being invalidated. This removes the need to |
| 1133 | /// explicitly preserve the results of `AAManager`. Note that analyses should no |
| 1134 | /// longer be registered once the `AAManager` is run. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1135 | class AAManager : public AnalysisInfoMixin<AAManager> { |
| 1136 | public: |
| 1137 | using Result = AAResults; |
| 1138 | |
| 1139 | /// Register a specific AA result. |
| 1140 | template <typename AnalysisT> void registerFunctionAnalysis() { |
| 1141 | ResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>); |
| 1142 | } |
| 1143 | |
| 1144 | /// Register a specific AA result. |
| 1145 | template <typename AnalysisT> void registerModuleAnalysis() { |
| 1146 | ResultGetters.push_back(&getModuleAAResultImpl<AnalysisT>); |
| 1147 | } |
| 1148 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 1149 | Result run(Function &F, FunctionAnalysisManager &AM); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1150 | |
| 1151 | private: |
| 1152 | friend AnalysisInfoMixin<AAManager>; |
| 1153 | |
| 1154 | static AnalysisKey Key; |
| 1155 | |
| 1156 | SmallVector<void (*)(Function &F, FunctionAnalysisManager &AM, |
| 1157 | AAResults &AAResults), |
| 1158 | 4> ResultGetters; |
| 1159 | |
| 1160 | template <typename AnalysisT> |
| 1161 | static void getFunctionAAResultImpl(Function &F, |
| 1162 | FunctionAnalysisManager &AM, |
| 1163 | AAResults &AAResults) { |
| 1164 | AAResults.addAAResult(AM.template getResult<AnalysisT>(F)); |
| 1165 | AAResults.addAADependencyID(AnalysisT::ID()); |
| 1166 | } |
| 1167 | |
| 1168 | template <typename AnalysisT> |
| 1169 | static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM, |
| 1170 | AAResults &AAResults) { |
| 1171 | auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 1172 | if (auto *R = |
| 1173 | MAMProxy.template getCachedResult<AnalysisT>(*F.getParent())) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1174 | AAResults.addAAResult(*R); |
| 1175 | MAMProxy |
| 1176 | .template registerOuterAnalysisInvalidation<AnalysisT, AAManager>(); |
| 1177 | } |
| 1178 | } |
| 1179 | }; |
| 1180 | |
| 1181 | /// A wrapper pass to provide the legacy pass manager access to a suitably |
| 1182 | /// prepared AAResults object. |
| 1183 | class AAResultsWrapperPass : public FunctionPass { |
| 1184 | std::unique_ptr<AAResults> AAR; |
| 1185 | |
| 1186 | public: |
| 1187 | static char ID; |
| 1188 | |
| 1189 | AAResultsWrapperPass(); |
| 1190 | |
| 1191 | AAResults &getAAResults() { return *AAR; } |
| 1192 | const AAResults &getAAResults() const { return *AAR; } |
| 1193 | |
| 1194 | bool runOnFunction(Function &F) override; |
| 1195 | |
| 1196 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
| 1197 | }; |
| 1198 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1199 | /// A wrapper pass for external alias analyses. This just squirrels away the |
| 1200 | /// callback used to run any analyses and register their results. |
| 1201 | struct ExternalAAWrapperPass : ImmutablePass { |
| 1202 | using CallbackT = std::function<void(Pass &, Function &, AAResults &)>; |
| 1203 | |
| 1204 | CallbackT CB; |
| 1205 | |
| 1206 | static char ID; |
| 1207 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 1208 | ExternalAAWrapperPass(); |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1209 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 1210 | explicit ExternalAAWrapperPass(CallbackT CB); |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 1211 | |
| 1212 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
| 1213 | AU.setPreservesAll(); |
| 1214 | } |
| 1215 | }; |
| 1216 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1217 | FunctionPass *createAAResultsWrapperPass(); |
| 1218 | |
| 1219 | /// A wrapper pass around a callback which can be used to populate the |
| 1220 | /// AAResults in the AAResultsWrapperPass from an external AA. |
| 1221 | /// |
| 1222 | /// The callback provided here will be used each time we prepare an AAResults |
| 1223 | /// object, and will receive a reference to the function wrapper pass, the |
| 1224 | /// function, and the AAResults object to populate. This should be used when |
| 1225 | /// setting up a custom pass pipeline to inject a hook into the AA results. |
| 1226 | ImmutablePass *createExternalAAWrapperPass( |
| 1227 | std::function<void(Pass &, Function &, AAResults &)> Callback); |
| 1228 | |
| 1229 | /// A helper for the legacy pass manager to create a \c AAResults |
| 1230 | /// object populated to the best of our ability for a particular function when |
| 1231 | /// inside of a \c ModulePass or a \c CallGraphSCCPass. |
| 1232 | /// |
| 1233 | /// If a \c ModulePass or a \c CallGraphSCCPass calls \p |
| 1234 | /// createLegacyPMAAResults, it also needs to call \p addUsedAAAnalyses in \p |
| 1235 | /// getAnalysisUsage. |
| 1236 | AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR); |
| 1237 | |
| 1238 | /// A helper for the legacy pass manager to populate \p AU to add uses to make |
| 1239 | /// sure the analyses required by \p createLegacyPMAAResults are available. |
| 1240 | void getAAResultsAnalysisUsage(AnalysisUsage &AU); |
| 1241 | |
| 1242 | } // end namespace llvm |
| 1243 | |
| 1244 | #endif // LLVM_ANALYSIS_ALIASANALYSIS_H |