Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
MemoryLocation.h
Go to the documentation of this file.
1//===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file provides utility analysis objects describing memory locations.
10/// These are used both by the Alias Analysis infrastructure and more
11/// specialized memory analysis layers.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
16#define LLVM_ANALYSIS_MEMORYLOCATION_H
17
19#include "llvm/IR/Metadata.h"
22
23#include <optional>
24
25namespace llvm {
26
27class CallBase;
28class Instruction;
29class LoadInst;
30class StoreInst;
31class MemTransferInst;
32class MemIntrinsic;
34class AtomicRMWInst;
36class AnyMemIntrinsic;
38class VAArgInst;
39
40// Represents the size of a MemoryLocation. Logically, it's an
41// std::optional<uint63_t> that also carries a bit to represent whether the
42// integer it contains, N, is 'precise'. Precise, in this context, means that we
43// know that the area of storage referenced by the given MemoryLocation must be
44// precisely N bytes. An imprecise value is formed as the union of two or more
45// precise values, and can conservatively represent all of the values unioned
46// into it. Importantly, imprecise values are an *upper-bound* on the size of a
47// MemoryLocation.
48//
49// Concretely, a precise MemoryLocation is (%p, 4) in
50// store i32 0, i32* %p
51//
52// Since we know that %p must be at least 4 bytes large at this point.
53// Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4)
54// at the memcpy in
55//
56// %n = select i1 %foo, i64 1, i64 4
57// call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1,
58// i1 false)
59//
60// ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that
61// we'll ever actually do so.
62//
63// If asked to represent a pathologically large value, this will degrade to
64// std::nullopt.
65// Store Scalable information in bit 62 of Value. Scalable information is
66// required to do Alias Analysis on Scalable quantities
67class LocationSize {
68 enum : uint64_t {
69 BeforeOrAfterPointer = ~uint64_t(0),
70 ScalableBit = uint64_t(1) << 62,
71 AfterPointer = (BeforeOrAfterPointer - 1) & ~ScalableBit,
72 MapEmpty = BeforeOrAfterPointer - 2,
73 MapTombstone = BeforeOrAfterPointer - 3,
74 ImpreciseBit = uint64_t(1) << 63,
75
76 // The maximum value we can represent without falling back to 'unknown'.
77 MaxValue = (MapTombstone - 1) & ~(ImpreciseBit | ScalableBit),
78 };
79
80 uint64_t Value;
81
82 constexpr LocationSize(uint64_t Raw) : Value(Raw) {}
83 constexpr LocationSize(uint64_t Raw, bool Scalable)
84 : Value(Raw > MaxValue ? AfterPointer
85 : Raw | (Scalable ? ScalableBit : uint64_t(0))) {}
86
87 static_assert(AfterPointer & ImpreciseBit,
88 "AfterPointer is imprecise by definition.");
89 static_assert(BeforeOrAfterPointer & ImpreciseBit,
90 "BeforeOrAfterPointer is imprecise by definition.");
91 static_assert(~(MaxValue & ScalableBit), "Max value don't have bit 62 set");
92
93public:
94 // Create non-scalable LocationSize
95 static LocationSize precise(uint64_t Value) {
96 return LocationSize(Value, false /*Scalable*/);
97 }
98 static LocationSize precise(TypeSize Value) {
99 return LocationSize(Value.getKnownMinValue(), Value.isScalable());
100 }
101
102 static LocationSize upperBound(uint64_t Value) {
103 // You can't go lower than 0, so give a precise result.
104 if (LLVM_UNLIKELY(Value == 0))
105 return precise(0);
106 if (LLVM_UNLIKELY(Value > MaxValue))
107 return afterPointer();
108 return LocationSize(Value | ImpreciseBit);
109 }
110 static LocationSize upperBound(TypeSize Value) {
111 if (Value.isScalable())
112 return afterPointer();
113 return upperBound(Value.getFixedValue());
114 }
115
116 /// Any location after the base pointer (but still within the underlying
117 /// object).
118 constexpr static LocationSize afterPointer() {
119 return LocationSize(AfterPointer);
120 }
121
122 /// Any location before or after the base pointer (but still within the
123 /// underlying object).
124 constexpr static LocationSize beforeOrAfterPointer() {
125 return LocationSize(BeforeOrAfterPointer);
126 }
127
128 // Sentinel values, generally used for maps.
129 constexpr static LocationSize mapTombstone() {
130 return LocationSize(MapTombstone);
131 }
132 constexpr static LocationSize mapEmpty() {
133 return LocationSize(MapEmpty);
134 }
135
136 // Returns a LocationSize that can correctly represent either `*this` or
137 // `Other`.
138 LocationSize unionWith(LocationSize Other) const {
139 if (Other == *this)
140 return *this;
141
142 if (Value == BeforeOrAfterPointer || Other.Value == BeforeOrAfterPointer)
143 return beforeOrAfterPointer();
144 if (Value == AfterPointer || Other.Value == AfterPointer)
145 return afterPointer();
146 if (isScalable() || Other.isScalable())
147 return afterPointer();
148
149 return upperBound(
150 std::max(getValue().getFixedValue(), Other.getValue().getFixedValue()));
151 }
152
153 bool hasValue() const {
154 return Value != AfterPointer && Value != BeforeOrAfterPointer;
155 }
156 bool isScalable() const { return (Value & ScalableBit); }
157
159 assert(hasValue() && "Getting value from an unknown LocationSize!");
160 assert((Value & ~(ImpreciseBit | ScalableBit)) < MaxValue &&
161 "Scalable bit of value should be masked");
162 return {Value & ~(ImpreciseBit | ScalableBit), isScalable()};
163 }
164
165 // Returns whether or not this value is precise. Note that if a value is
166 // precise, it's guaranteed to not be unknown.
167 bool isPrecise() const { return (Value & ImpreciseBit) == 0; }
168
169 // Convenience method to check if this LocationSize's value is 0.
170 bool isZero() const {
171 return hasValue() && getValue().getKnownMinValue() == 0;
172 }
173
174 /// Whether accesses before the base pointer are possible.
175 bool mayBeBeforePointer() const { return Value == BeforeOrAfterPointer; }
176
177 bool operator==(const LocationSize &Other) const {
178 return Value == Other.Value;
179 }
180 bool operator==(const TypeSize &Other) const {
181 return (*this == LocationSize::precise(Other));
182 }
184 return (*this == LocationSize::precise(Other));
185 }
186
187 bool operator!=(const LocationSize &Other) const { return !(*this == Other); }
188 bool operator!=(const TypeSize &Other) const { return !(*this == Other); }
189 bool operator!=(uint64_t Other) const { return !(*this == Other); }
190
191 // Ordering operators are not provided, since it's unclear if there's only one
192 // reasonable way to compare:
193 // - values that don't exist against values that do, and
194 // - precise values to imprecise values
195
196 LLVM_ABI void print(raw_ostream &OS) const;
197
198 // Returns an opaque value that represents this LocationSize. Cannot be
199 // reliably converted back into a LocationSize.
200 uint64_t toRaw() const { return Value; }
201};
202
204 Size.print(OS);
205 return OS;
206}
207
208/// Representation for a specific memory location.
209///
210/// This abstraction can be used to represent a specific location in memory.
211/// The goal of the location is to represent enough information to describe
212/// abstract aliasing, modification, and reference behaviors of whatever
213/// value(s) are stored in memory at the particular location.
214///
215/// The primary user of this interface is LLVM's Alias Analysis, but other
216/// memory analyses such as MemoryDependence can use it as well.
218public:
219 /// UnknownSize - This is a special value which can be used with the
220 /// size arguments in alias queries to indicate that the caller does not
221 /// know the sizes of the potential memory references.
222 enum : uint64_t { UnknownSize = ~UINT64_C(0) };
223
224 /// The address of the start of the location.
225 const Value *Ptr;
226
227 /// The maximum size of the location, in address-units, or
228 /// UnknownSize if the size is not known.
229 ///
230 /// Note that an unknown size does not mean the pointer aliases the entire
231 /// virtual address space, because there are restrictions on stepping out of
232 /// one object and into another. See
233 /// http://llvm.org/docs/LangRef.html#pointeraliasing
235
236 /// The metadata nodes which describes the aliasing of the location (each
237 /// member is null if that kind of information is unavailable).
239
240 void print(raw_ostream &OS) const { OS << *Ptr << " " << Size << "\n"; }
241
242 /// Return a location with information about the memory reference by the given
243 /// instruction.
244 LLVM_ABI static MemoryLocation get(const LoadInst *LI);
245 LLVM_ABI static MemoryLocation get(const StoreInst *SI);
246 LLVM_ABI static MemoryLocation get(const VAArgInst *VI);
247 LLVM_ABI static MemoryLocation get(const AtomicCmpXchgInst *CXI);
248 LLVM_ABI static MemoryLocation get(const AtomicRMWInst *RMWI);
249 static MemoryLocation get(const Instruction *Inst) {
250 return *MemoryLocation::getOrNone(Inst);
251 }
252 LLVM_ABI static std::optional<MemoryLocation>
253 getOrNone(const Instruction *Inst);
254
255 /// Return a location representing the source of a memory transfer.
258
259 /// Return a location representing the destination of a memory set or
260 /// transfer.
263 LLVM_ABI static std::optional<MemoryLocation>
264 getForDest(const CallBase *CI, const TargetLibraryInfo &TLI);
265
266 /// Return a location representing a particular argument of a call.
268 unsigned ArgIdx,
269 const TargetLibraryInfo *TLI);
270 static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx,
271 const TargetLibraryInfo &TLI) {
272 return getForArgument(Call, ArgIdx, &TLI);
273 }
274
275 /// Return a location that may access any location after Ptr, while remaining
276 /// within the underlying object.
281
282 /// Return a location that may access any location before or after Ptr, while
283 /// remaining within the underlying object.
284 static MemoryLocation
288
289 MemoryLocation() : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()) {}
290
292 const AAMDNodes &AATags = AAMDNodes())
293 : Ptr(Ptr), Size(Size), AATags(AATags) {}
295 const AAMDNodes &AATags = AAMDNodes())
296 : Ptr(Ptr), Size(LocationSize::precise(Size)), AATags(AATags) {}
298 const AAMDNodes &AATags = AAMDNodes())
299 : Ptr(Ptr), Size(LocationSize::precise(Size)), AATags(AATags) {}
300
301 MemoryLocation getWithNewPtr(const Value *NewPtr) const {
302 MemoryLocation Copy(*this);
303 Copy.Ptr = NewPtr;
304 return Copy;
305 }
306
308 MemoryLocation Copy(*this);
309 Copy.Size = NewSize;
310 return Copy;
311 }
313 return getWithNewSize(LocationSize::precise(NewSize));
314 }
316 return getWithNewSize(LocationSize::precise(NewSize));
317 }
318
320 MemoryLocation Copy(*this);
321 Copy.AATags = AAMDNodes();
322 return Copy;
323 }
324
325 bool operator==(const MemoryLocation &Other) const {
326 return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
327 }
328};
329
330// Specialize DenseMapInfo.
331template <> struct DenseMapInfo<LocationSize> {
332 static inline LocationSize getEmptyKey() { return LocationSize::mapEmpty(); }
335 }
336 static unsigned getHashValue(const LocationSize &Val) {
338 }
339 static bool isEqual(const LocationSize &LHS, const LocationSize &RHS) {
340 return LHS == RHS;
341 }
342};
343
362} // namespace llvm
363
364#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
#define LLVM_ABI
Definition Compiler.h:213
This file defines DenseMapInfo traits for DenseMap.
IRTranslator LLVM IR MI
This file contains the declarations for metadata subclasses.
Value * RHS
Value * LHS
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
An instruction for reading from memory.
bool hasValue() const
static LocationSize precise(uint64_t Value)
bool operator!=(uint64_t Other) const
static constexpr LocationSize mapEmpty()
static LocationSize upperBound(TypeSize Value)
bool mayBeBeforePointer() const
Whether accesses before the base pointer are possible.
bool operator==(const TypeSize &Other) const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
bool isScalable() const
TypeSize getValue() const
LLVM_ABI void print(raw_ostream &OS) const
bool operator!=(const TypeSize &Other) const
bool isPrecise() const
bool operator!=(const LocationSize &Other) const
static constexpr LocationSize afterPointer()
Any location after the base pointer (but still within the underlying object).
uint64_t toRaw() const
LocationSize unionWith(LocationSize Other) const
bool operator==(uint64_t Other) const
static LocationSize upperBound(uint64_t Value)
static constexpr LocationSize mapTombstone()
bool operator==(const LocationSize &Other) const
static LocationSize precise(TypeSize Value)
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
Representation for a specific memory location.
MemoryLocation(const Value *Ptr, TypeSize Size, const AAMDNodes &AATags=AAMDNodes())
MemoryLocation getWithNewSize(LocationSize NewSize) const
MemoryLocation getWithoutAATags() const
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo &TLI)
static LLVM_ABI MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
void print(raw_ostream &OS) const
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
static MemoryLocation getAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location after Ptr, while remaining within the underlying objec...
static MemoryLocation get(const Instruction *Inst)
MemoryLocation getWithNewSize(uint64_t NewSize) const
MemoryLocation getWithNewPtr(const Value *NewPtr) const
MemoryLocation getWithNewSize(TypeSize NewSize) const
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
MemoryLocation(const Value *Ptr, LocationSize Size, const AAMDNodes &AATags=AAMDNodes())
static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
bool operator==(const MemoryLocation &Other) const
MemoryLocation(const Value *Ptr, uint64_t Size, const AAMDNodes &AATags=AAMDNodes())
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
An instruction for storing to memory.
Provides information about what library functions are available for the current target.
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
LLVM Value Representation.
Definition Value.h:75
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
@ Other
Any other memory.
Definition ModRef.h:68
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Definition Metadata.h:760
static LocationSize getTombstoneKey()
static bool isEqual(const LocationSize &LHS, const LocationSize &RHS)
static unsigned getHashValue(const LocationSize &Val)
static MemoryLocation getTombstoneKey()
static MemoryLocation getEmptyKey()
static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS)
static unsigned getHashValue(const MemoryLocation &Val)
An information struct used to provide DenseMap with the various necessary components for a given valu...