LLVM 20.0.0git
MemoryLocation.cpp
Go to the documentation of this file.
1//===- MemoryLocation.cpp - Memory location descriptions -------------------==//
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
11#include "llvm/IR/DataLayout.h"
14#include "llvm/IR/IntrinsicsARM.h"
15#include "llvm/IR/Type.h"
16#include <optional>
17using namespace llvm;
18
20 OS << "LocationSize::";
21 if (*this == beforeOrAfterPointer())
22 OS << "beforeOrAfterPointer";
23 else if (*this == afterPointer())
24 OS << "afterPointer";
25 else if (*this == mapEmpty())
26 OS << "mapEmpty";
27 else if (*this == mapTombstone())
28 OS << "mapTombstone";
29 else if (isPrecise())
30 OS << "precise(" << getValue() << ')';
31 else
32 OS << "upperBound(" << getValue() << ')';
33}
34
36 const auto &DL = LI->getDataLayout();
37
38 return MemoryLocation(
40 LocationSize::precise(DL.getTypeStoreSize(LI->getType())),
41 LI->getAAMetadata());
42}
43
45 const auto &DL = SI->getDataLayout();
46
47 return MemoryLocation(SI->getPointerOperand(),
48 LocationSize::precise(DL.getTypeStoreSize(
49 SI->getValueOperand()->getType())),
50 SI->getAAMetadata());
51}
52
54 return MemoryLocation(VI->getPointerOperand(),
55 LocationSize::afterPointer(), VI->getAAMetadata());
56}
57
59 const auto &DL = CXI->getDataLayout();
60
62 LocationSize::precise(DL.getTypeStoreSize(
63 CXI->getCompareOperand()->getType())),
64 CXI->getAAMetadata());
65}
66
68 const auto &DL = RMWI->getDataLayout();
69
70 return MemoryLocation(RMWI->getPointerOperand(),
71 LocationSize::precise(DL.getTypeStoreSize(
72 RMWI->getValOperand()->getType())),
73 RMWI->getAAMetadata());
74}
75
76std::optional<MemoryLocation>
78 switch (Inst->getOpcode()) {
79 case Instruction::Load:
80 return get(cast<LoadInst>(Inst));
81 case Instruction::Store:
82 return get(cast<StoreInst>(Inst));
83 case Instruction::VAArg:
84 return get(cast<VAArgInst>(Inst));
85 case Instruction::AtomicCmpXchg:
86 return get(cast<AtomicCmpXchgInst>(Inst));
87 case Instruction::AtomicRMW:
88 return get(cast<AtomicRMWInst>(Inst));
89 default:
90 return std::nullopt;
91 }
92}
93
95 return getForSource(cast<AnyMemTransferInst>(MTI));
96}
97
99 return getForSource(cast<AnyMemTransferInst>(MTI));
100}
101
103 assert(MTI->getRawSource() == MTI->getArgOperand(1));
104 return getForArgument(MTI, 1, nullptr);
105}
106
108 return getForDest(cast<AnyMemIntrinsic>(MI));
109}
110
112 return getForDest(cast<AnyMemIntrinsic>(MI));
113}
114
116 assert(MI->getRawDest() == MI->getArgOperand(0));
117 return getForArgument(MI, 0, nullptr);
118}
119
120std::optional<MemoryLocation>
122 if (!CB->onlyAccessesArgMemory())
123 return std::nullopt;
124
125 if (CB->hasOperandBundles())
126 // TODO: remove implementation restriction
127 return std::nullopt;
128
129 Value *UsedV = nullptr;
130 std::optional<unsigned> UsedIdx;
131 for (unsigned i = 0; i < CB->arg_size(); i++) {
132 if (!CB->getArgOperand(i)->getType()->isPointerTy())
133 continue;
134 if (CB->onlyReadsMemory(i))
135 continue;
136 if (!UsedV) {
137 // First potentially writing parameter
138 UsedV = CB->getArgOperand(i);
139 UsedIdx = i;
140 continue;
141 }
142 UsedIdx = std::nullopt;
143 if (UsedV != CB->getArgOperand(i))
144 // Can't describe writing to two distinct locations.
145 // TODO: This results in an inprecision when two values derived from the
146 // same object are passed as arguments to the same function.
147 return std::nullopt;
148 }
149 if (!UsedV)
150 // We don't currently have a way to represent a "does not write" result
151 // and thus have to be conservative and return unknown.
152 return std::nullopt;
153
154 if (UsedIdx)
155 return getForArgument(CB, *UsedIdx, &TLI);
157}
158
160 unsigned ArgIdx,
161 const TargetLibraryInfo *TLI) {
162 AAMDNodes AATags = Call->getAAMetadata();
163 const Value *Arg = Call->getArgOperand(ArgIdx);
164
165 // We may be able to produce an exact size for known intrinsics.
166 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call)) {
167 const DataLayout &DL = II->getDataLayout();
168
169 switch (II->getIntrinsicID()) {
170 default:
171 break;
172 case Intrinsic::memset:
173 case Intrinsic::memcpy:
174 case Intrinsic::memcpy_inline:
175 case Intrinsic::memmove:
176 case Intrinsic::memcpy_element_unordered_atomic:
177 case Intrinsic::memmove_element_unordered_atomic:
178 case Intrinsic::memset_element_unordered_atomic:
179 assert((ArgIdx == 0 || ArgIdx == 1) &&
180 "Invalid argument index for memory intrinsic");
181 if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
182 return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
183 AATags);
184 return MemoryLocation::getAfter(Arg, AATags);
185
186 case Intrinsic::lifetime_start:
187 case Intrinsic::lifetime_end:
188 case Intrinsic::invariant_start:
189 assert(ArgIdx == 1 && "Invalid argument index");
190 return MemoryLocation(
191 Arg,
193 cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),
194 AATags);
195
196 case Intrinsic::masked_load:
197 assert(ArgIdx == 0 && "Invalid argument index");
198 return MemoryLocation(
199 Arg,
200 LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),
201 AATags);
202
203 case Intrinsic::masked_store:
204 assert(ArgIdx == 1 && "Invalid argument index");
205 return MemoryLocation(
206 Arg,
208 DL.getTypeStoreSize(II->getArgOperand(0)->getType())),
209 AATags);
210
211 case Intrinsic::invariant_end:
212 // The first argument to an invariant.end is a "descriptor" type (e.g. a
213 // pointer to a empty struct) which is never actually dereferenced.
214 if (ArgIdx == 0)
216 assert(ArgIdx == 2 && "Invalid argument index");
217 return MemoryLocation(
218 Arg,
220 cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()),
221 AATags);
222
223 case Intrinsic::arm_neon_vld1:
224 assert(ArgIdx == 0 && "Invalid argument index");
225 // LLVM's vld1 and vst1 intrinsics currently only support a single
226 // vector register.
227 return MemoryLocation(
228 Arg, LocationSize::precise(DL.getTypeStoreSize(II->getType())),
229 AATags);
230
231 case Intrinsic::arm_neon_vst1:
232 assert(ArgIdx == 0 && "Invalid argument index");
233 return MemoryLocation(Arg,
234 LocationSize::precise(DL.getTypeStoreSize(
235 II->getArgOperand(1)->getType())),
236 AATags);
237 }
238
239 assert(
240 !isa<AnyMemTransferInst>(II) &&
241 "all memory transfer intrinsics should be handled by the switch above");
242 }
243
244 // We can bound the aliasing properties of memset_pattern16 just as we can
245 // for memcpy/memset. This is particularly important because the
246 // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
247 // whenever possible.
248 LibFunc F;
249 if (TLI && TLI->getLibFunc(*Call, F) && TLI->has(F)) {
250 switch (F) {
251 case LibFunc_strcpy:
252 case LibFunc_strcat:
253 case LibFunc_strncat:
254 assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for str function");
255 return MemoryLocation::getAfter(Arg, AATags);
256
257 case LibFunc_memset_chk:
258 assert(ArgIdx == 0 && "Invalid argument index for memset_chk");
259 [[fallthrough]];
260 case LibFunc_memcpy_chk: {
261 assert((ArgIdx == 0 || ArgIdx == 1) &&
262 "Invalid argument index for memcpy_chk");
264 if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
265 // memset_chk writes at most Len bytes, memcpy_chk reads/writes at most
266 // Len bytes. They may read/write less, if Len exceeds the specified max
267 // size and aborts.
268 Size = LocationSize::upperBound(Len->getZExtValue());
269 }
270 return MemoryLocation(Arg, Size, AATags);
271 }
272 case LibFunc_strncpy: {
273 assert((ArgIdx == 0 || ArgIdx == 1) &&
274 "Invalid argument index for strncpy");
276 if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
277 // strncpy is guaranteed to write Len bytes, but only reads up to Len
278 // bytes.
279 Size = ArgIdx == 0 ? LocationSize::precise(Len->getZExtValue())
280 : LocationSize::upperBound(Len->getZExtValue());
281 }
282 return MemoryLocation(Arg, Size, AATags);
283 }
284 case LibFunc_memset_pattern16:
285 case LibFunc_memset_pattern4:
286 case LibFunc_memset_pattern8:
287 assert((ArgIdx == 0 || ArgIdx == 1) &&
288 "Invalid argument index for memset_pattern16");
289 if (ArgIdx == 1) {
290 unsigned Size = 16;
291 if (F == LibFunc_memset_pattern4)
292 Size = 4;
293 else if (F == LibFunc_memset_pattern8)
294 Size = 8;
296 }
297 if (const ConstantInt *LenCI =
298 dyn_cast<ConstantInt>(Call->getArgOperand(2)))
299 return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
300 AATags);
301 return MemoryLocation::getAfter(Arg, AATags);
302 case LibFunc_bcmp:
303 case LibFunc_memcmp:
304 assert((ArgIdx == 0 || ArgIdx == 1) &&
305 "Invalid argument index for memcmp/bcmp");
306 if (const ConstantInt *LenCI =
307 dyn_cast<ConstantInt>(Call->getArgOperand(2)))
308 return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
309 AATags);
310 return MemoryLocation::getAfter(Arg, AATags);
311 case LibFunc_memchr:
312 assert((ArgIdx == 0) && "Invalid argument index for memchr");
313 if (const ConstantInt *LenCI =
314 dyn_cast<ConstantInt>(Call->getArgOperand(2)))
315 return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
316 AATags);
317 return MemoryLocation::getAfter(Arg, AATags);
318 case LibFunc_memccpy:
319 assert((ArgIdx == 0 || ArgIdx == 1) &&
320 "Invalid argument index for memccpy");
321 // We only know an upper bound on the number of bytes read/written.
322 if (const ConstantInt *LenCI =
323 dyn_cast<ConstantInt>(Call->getArgOperand(3)))
324 return MemoryLocation(
325 Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);
326 return MemoryLocation::getAfter(Arg, AATags);
327 default:
328 break;
329 };
330 }
331
332 return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);
333}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
This file provides utility analysis objects describing memory locations.
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:501
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:704
Value * getPointerOperand()
Definition: Instructions.h:870
Value * getValOperand()
Definition: Instructions.h:874
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1120
bool onlyReadsMemory(unsigned OpNo) const
Definition: InstrTypes.h:1724
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1294
bool onlyAccessesArgMemory() const
Determine if the call can access memmory only using pointers based on its arguments.
unsigned arg_size() const
Definition: InstrTypes.h:1292
bool hasOperandBundles() const
Return true if this User has any operand bundles.
Definition: InstrTypes.h:1969
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
Definition: Metadata.cpp:1750
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:274
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Definition: Instruction.cpp:74
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:48
An instruction for reading from memory.
Definition: Instructions.h:176
Value * getPointerOperand()
Definition: Instructions.h:255
static LocationSize precise(uint64_t Value)
static constexpr LocationSize mapEmpty()
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
TypeSize getValue() const
void print(raw_ostream &OS) const
bool isPrecise() const
static constexpr LocationSize afterPointer()
Any location after the base pointer (but still within the underlying object).
static LocationSize upperBound(uint64_t Value)
static constexpr LocationSize mapTombstone()
This is the common base class for memset/memcpy/memmove.
Value * getRawSource() const
Return the arguments to the instruction.
This class wraps the llvm.memcpy/memmove intrinsics.
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
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...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
static MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static 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.
Definition: Instructions.h:292
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:264
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Definition: Metadata.h:760