170c61c1aSChandler Carruth //===- MemoryLocation.cpp - Memory location descriptions -------------------==//
270c61c1aSChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
670c61c1aSChandler Carruth //
770c61c1aSChandler Carruth //===----------------------------------------------------------------------===//
870c61c1aSChandler Carruth
970c61c1aSChandler Carruth #include "llvm/Analysis/MemoryLocation.h"
10c41404a0SChandler Carruth #include "llvm/Analysis/TargetLibraryInfo.h"
1170c61c1aSChandler Carruth #include "llvm/IR/DataLayout.h"
1270c61c1aSChandler Carruth #include "llvm/IR/Instructions.h"
1370c61c1aSChandler Carruth #include "llvm/IR/IntrinsicInst.h"
145d986953SReid Kleckner #include "llvm/IR/IntrinsicsARM.h"
1570c61c1aSChandler Carruth #include "llvm/IR/Module.h"
1670c61c1aSChandler Carruth #include "llvm/IR/Type.h"
1770c61c1aSChandler Carruth using namespace llvm;
1870c61c1aSChandler Carruth
print(raw_ostream & OS) const19d98d505cSGeorge Burgess IV void LocationSize::print(raw_ostream &OS) const {
20d98d505cSGeorge Burgess IV OS << "LocationSize::";
214df8efceSNikita Popov if (*this == beforeOrAfterPointer())
224df8efceSNikita Popov OS << "beforeOrAfterPointer";
236fa12305SNikita Popov else if (*this == afterPointer())
244df8efceSNikita Popov OS << "afterPointer";
25d98d505cSGeorge Burgess IV else if (*this == mapEmpty())
26d98d505cSGeorge Burgess IV OS << "mapEmpty";
27d98d505cSGeorge Burgess IV else if (*this == mapTombstone())
28d98d505cSGeorge Burgess IV OS << "mapTombstone";
2940dc63e1SGeorge Burgess IV else if (isPrecise())
30d98d505cSGeorge Burgess IV OS << "precise(" << getValue() << ')';
3140dc63e1SGeorge Burgess IV else
3240dc63e1SGeorge Burgess IV OS << "upperBound(" << getValue() << ')';
33d98d505cSGeorge Burgess IV }
34d98d505cSGeorge Burgess IV
get(const LoadInst * LI)3570c61c1aSChandler Carruth MemoryLocation MemoryLocation::get(const LoadInst *LI) {
3670c61c1aSChandler Carruth const auto &DL = LI->getModule()->getDataLayout();
3770c61c1aSChandler Carruth
3869952979SGeorge Burgess IV return MemoryLocation(
3969952979SGeorge Burgess IV LI->getPointerOperand(),
400fc624f0SNikita Popov LocationSize::precise(DL.getTypeStoreSize(LI->getType())),
410fc624f0SNikita Popov LI->getAAMetadata());
4270c61c1aSChandler Carruth }
4370c61c1aSChandler Carruth
get(const StoreInst * SI)4470c61c1aSChandler Carruth MemoryLocation MemoryLocation::get(const StoreInst *SI) {
4570c61c1aSChandler Carruth const auto &DL = SI->getModule()->getDataLayout();
4670c61c1aSChandler Carruth
4770c61c1aSChandler Carruth return MemoryLocation(SI->getPointerOperand(),
4869952979SGeorge Burgess IV LocationSize::precise(DL.getTypeStoreSize(
4969952979SGeorge Burgess IV SI->getValueOperand()->getType())),
500fc624f0SNikita Popov SI->getAAMetadata());
5170c61c1aSChandler Carruth }
5270c61c1aSChandler Carruth
get(const VAArgInst * VI)5370c61c1aSChandler Carruth MemoryLocation MemoryLocation::get(const VAArgInst *VI) {
544df8efceSNikita Popov return MemoryLocation(VI->getPointerOperand(),
550fc624f0SNikita Popov LocationSize::afterPointer(), VI->getAAMetadata());
5670c61c1aSChandler Carruth }
5770c61c1aSChandler Carruth
get(const AtomicCmpXchgInst * CXI)5870c61c1aSChandler Carruth MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) {
5970c61c1aSChandler Carruth const auto &DL = CXI->getModule()->getDataLayout();
6070c61c1aSChandler Carruth
6169952979SGeorge Burgess IV return MemoryLocation(CXI->getPointerOperand(),
6269952979SGeorge Burgess IV LocationSize::precise(DL.getTypeStoreSize(
6369952979SGeorge Burgess IV CXI->getCompareOperand()->getType())),
640fc624f0SNikita Popov CXI->getAAMetadata());
6570c61c1aSChandler Carruth }
6670c61c1aSChandler Carruth
get(const AtomicRMWInst * RMWI)6770c61c1aSChandler Carruth MemoryLocation MemoryLocation::get(const AtomicRMWInst *RMWI) {
6870c61c1aSChandler Carruth const auto &DL = RMWI->getModule()->getDataLayout();
6970c61c1aSChandler Carruth
7070c61c1aSChandler Carruth return MemoryLocation(RMWI->getPointerOperand(),
7169952979SGeorge Burgess IV LocationSize::precise(DL.getTypeStoreSize(
7269952979SGeorge Burgess IV RMWI->getValOperand()->getType())),
730fc624f0SNikita Popov RMWI->getAAMetadata());
7470c61c1aSChandler Carruth }
7570c61c1aSChandler Carruth
getOrNone(const Instruction * Inst)765bd97eb2SSanne Wouda Optional<MemoryLocation> MemoryLocation::getOrNone(const Instruction *Inst) {
775bd97eb2SSanne Wouda switch (Inst->getOpcode()) {
785bd97eb2SSanne Wouda case Instruction::Load:
795bd97eb2SSanne Wouda return get(cast<LoadInst>(Inst));
805bd97eb2SSanne Wouda case Instruction::Store:
815bd97eb2SSanne Wouda return get(cast<StoreInst>(Inst));
825bd97eb2SSanne Wouda case Instruction::VAArg:
835bd97eb2SSanne Wouda return get(cast<VAArgInst>(Inst));
845bd97eb2SSanne Wouda case Instruction::AtomicCmpXchg:
855bd97eb2SSanne Wouda return get(cast<AtomicCmpXchgInst>(Inst));
865bd97eb2SSanne Wouda case Instruction::AtomicRMW:
875bd97eb2SSanne Wouda return get(cast<AtomicRMWInst>(Inst));
885bd97eb2SSanne Wouda default:
895bd97eb2SSanne Wouda return None;
905bd97eb2SSanne Wouda }
915bd97eb2SSanne Wouda }
925bd97eb2SSanne Wouda
getForSource(const MemTransferInst * MTI)9370c61c1aSChandler Carruth MemoryLocation MemoryLocation::getForSource(const MemTransferInst *MTI) {
94cc45e923SDaniel Neilson return getForSource(cast<AnyMemTransferInst>(MTI));
95cc45e923SDaniel Neilson }
96cc45e923SDaniel Neilson
getForSource(const AtomicMemTransferInst * MTI)97cc45e923SDaniel Neilson MemoryLocation MemoryLocation::getForSource(const AtomicMemTransferInst *MTI) {
98cc45e923SDaniel Neilson return getForSource(cast<AnyMemTransferInst>(MTI));
99cc45e923SDaniel Neilson }
100cc45e923SDaniel Neilson
getForSource(const AnyMemTransferInst * MTI)101cc45e923SDaniel Neilson MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) {
102203f29b4SFlorian Hahn assert(MTI->getRawSource() == MTI->getArgOperand(1));
103203f29b4SFlorian Hahn return getForArgument(MTI, 1, nullptr);
10470c61c1aSChandler Carruth }
10570c61c1aSChandler Carruth
getForDest(const MemIntrinsic * MI)106cc45e923SDaniel Neilson MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MI) {
107cc45e923SDaniel Neilson return getForDest(cast<AnyMemIntrinsic>(MI));
108cc45e923SDaniel Neilson }
109cc45e923SDaniel Neilson
getForDest(const AtomicMemIntrinsic * MI)110cc45e923SDaniel Neilson MemoryLocation MemoryLocation::getForDest(const AtomicMemIntrinsic *MI) {
111cc45e923SDaniel Neilson return getForDest(cast<AnyMemIntrinsic>(MI));
112cc45e923SDaniel Neilson }
113cc45e923SDaniel Neilson
getForDest(const AnyMemIntrinsic * MI)114cc45e923SDaniel Neilson MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) {
115203f29b4SFlorian Hahn assert(MI->getRawDest() == MI->getArgOperand(0));
116203f29b4SFlorian Hahn return getForArgument(MI, 0, nullptr);
11770c61c1aSChandler Carruth }
118c41404a0SChandler Carruth
119f078536fSFlorian Hahn Optional<MemoryLocation>
getForDest(const CallBase * CB,const TargetLibraryInfo & TLI)120f078536fSFlorian Hahn MemoryLocation::getForDest(const CallBase *CB, const TargetLibraryInfo &TLI) {
121*44d23d53SPhilip Reames if (!CB->onlyAccessesArgMemory())
122af86aa79SFlorian Hahn return None;
123*44d23d53SPhilip Reames
124*44d23d53SPhilip Reames if (CB->hasOperandBundles())
125*44d23d53SPhilip Reames // TODO: remove implementation restriction
126*44d23d53SPhilip Reames return None;
127*44d23d53SPhilip Reames
128*44d23d53SPhilip Reames Value *UsedV = nullptr;
129*44d23d53SPhilip Reames Optional<unsigned> UsedIdx;
130*44d23d53SPhilip Reames for (unsigned i = 0; i < CB->arg_size(); i++) {
131*44d23d53SPhilip Reames if (!CB->getArgOperand(i)->getType()->isPointerTy())
132*44d23d53SPhilip Reames continue;
133*44d23d53SPhilip Reames if (CB->onlyReadsMemory(i))
134*44d23d53SPhilip Reames continue;
135*44d23d53SPhilip Reames if (!UsedV) {
136*44d23d53SPhilip Reames // First potentially writing parameter
137*44d23d53SPhilip Reames UsedV = CB->getArgOperand(i);
138*44d23d53SPhilip Reames UsedIdx = i;
139*44d23d53SPhilip Reames continue;
140*44d23d53SPhilip Reames }
141*44d23d53SPhilip Reames UsedIdx = None;
142*44d23d53SPhilip Reames if (UsedV != CB->getArgOperand(i))
143*44d23d53SPhilip Reames // Can't describe writing to two distinct locations.
144*44d23d53SPhilip Reames // TODO: This results in an inprecision when two values derived from the
145*44d23d53SPhilip Reames // same object are passed as arguments to the same function.
146*44d23d53SPhilip Reames return None;
147*44d23d53SPhilip Reames }
148*44d23d53SPhilip Reames if (!UsedV)
149*44d23d53SPhilip Reames // We don't currently have a way to represent a "does not write" result
150*44d23d53SPhilip Reames // and thus have to be conservative and return unknown.
151*44d23d53SPhilip Reames return None;
152*44d23d53SPhilip Reames
153*44d23d53SPhilip Reames if (UsedIdx)
154*44d23d53SPhilip Reames return getForArgument(CB, *UsedIdx, &TLI);
155*44d23d53SPhilip Reames return MemoryLocation::getBeforeOrAfter(UsedV, CB->getAAMetadata());
156f078536fSFlorian Hahn }
157f078536fSFlorian Hahn
getForArgument(const CallBase * Call,unsigned ArgIdx,const TargetLibraryInfo * TLI)158363ac683SChandler Carruth MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
159c41404a0SChandler Carruth unsigned ArgIdx,
160cb8b3278SPhilip Reames const TargetLibraryInfo *TLI) {
1610fc624f0SNikita Popov AAMDNodes AATags = Call->getAAMetadata();
162363ac683SChandler Carruth const Value *Arg = Call->getArgOperand(ArgIdx);
163c41404a0SChandler Carruth
164c41404a0SChandler Carruth // We may be able to produce an exact size for known intrinsics.
165363ac683SChandler Carruth if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call)) {
166c41404a0SChandler Carruth const DataLayout &DL = II->getModule()->getDataLayout();
167c41404a0SChandler Carruth
168c41404a0SChandler Carruth switch (II->getIntrinsicID()) {
169c41404a0SChandler Carruth default:
170c41404a0SChandler Carruth break;
171c41404a0SChandler Carruth case Intrinsic::memset:
172c41404a0SChandler Carruth case Intrinsic::memcpy:
1732990518bSDávid Bolvanský case Intrinsic::memcpy_inline:
174c41404a0SChandler Carruth case Intrinsic::memmove:
175a9125792SFlorian Hahn case Intrinsic::memcpy_element_unordered_atomic:
176a9125792SFlorian Hahn case Intrinsic::memmove_element_unordered_atomic:
177a9125792SFlorian Hahn case Intrinsic::memset_element_unordered_atomic:
178c41404a0SChandler Carruth assert((ArgIdx == 0 || ArgIdx == 1) &&
179c41404a0SChandler Carruth "Invalid argument index for memory intrinsic");
180c41404a0SChandler Carruth if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
18169952979SGeorge Burgess IV return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
18269952979SGeorge Burgess IV AATags);
1834df8efceSNikita Popov return MemoryLocation::getAfter(Arg, AATags);
184c41404a0SChandler Carruth
185c41404a0SChandler Carruth case Intrinsic::lifetime_start:
186c41404a0SChandler Carruth case Intrinsic::lifetime_end:
187c41404a0SChandler Carruth case Intrinsic::invariant_start:
188c41404a0SChandler Carruth assert(ArgIdx == 1 && "Invalid argument index");
189c41404a0SChandler Carruth return MemoryLocation(
19069952979SGeorge Burgess IV Arg,
19169952979SGeorge Burgess IV LocationSize::precise(
19269952979SGeorge Burgess IV cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),
19369952979SGeorge Burgess IV AATags);
194c41404a0SChandler Carruth
195055d2095SKrzysztof Parzyszek case Intrinsic::masked_load:
196055d2095SKrzysztof Parzyszek assert(ArgIdx == 0 && "Invalid argument index");
197055d2095SKrzysztof Parzyszek return MemoryLocation(
198055d2095SKrzysztof Parzyszek Arg,
199055d2095SKrzysztof Parzyszek LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),
200055d2095SKrzysztof Parzyszek AATags);
201055d2095SKrzysztof Parzyszek
202055d2095SKrzysztof Parzyszek case Intrinsic::masked_store:
203055d2095SKrzysztof Parzyszek assert(ArgIdx == 1 && "Invalid argument index");
204055d2095SKrzysztof Parzyszek return MemoryLocation(
205055d2095SKrzysztof Parzyszek Arg,
206055d2095SKrzysztof Parzyszek LocationSize::upperBound(
207055d2095SKrzysztof Parzyszek DL.getTypeStoreSize(II->getArgOperand(0)->getType())),
208055d2095SKrzysztof Parzyszek AATags);
209055d2095SKrzysztof Parzyszek
210c41404a0SChandler Carruth case Intrinsic::invariant_end:
211684fa57eSPhilip Reames // The first argument to an invariant.end is a "descriptor" type (e.g. a
212684fa57eSPhilip Reames // pointer to a empty struct) which is never actually dereferenced.
213684fa57eSPhilip Reames if (ArgIdx == 0)
21469952979SGeorge Burgess IV return MemoryLocation(Arg, LocationSize::precise(0), AATags);
215c41404a0SChandler Carruth assert(ArgIdx == 2 && "Invalid argument index");
216c41404a0SChandler Carruth return MemoryLocation(
21769952979SGeorge Burgess IV Arg,
21869952979SGeorge Burgess IV LocationSize::precise(
21969952979SGeorge Burgess IV cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()),
22069952979SGeorge Burgess IV AATags);
221c41404a0SChandler Carruth
222c41404a0SChandler Carruth case Intrinsic::arm_neon_vld1:
223c41404a0SChandler Carruth assert(ArgIdx == 0 && "Invalid argument index");
224c41404a0SChandler Carruth // LLVM's vld1 and vst1 intrinsics currently only support a single
225c41404a0SChandler Carruth // vector register.
22669952979SGeorge Burgess IV return MemoryLocation(
22769952979SGeorge Burgess IV Arg, LocationSize::precise(DL.getTypeStoreSize(II->getType())),
22869952979SGeorge Burgess IV AATags);
229c41404a0SChandler Carruth
230c41404a0SChandler Carruth case Intrinsic::arm_neon_vst1:
231c41404a0SChandler Carruth assert(ArgIdx == 0 && "Invalid argument index");
23269952979SGeorge Burgess IV return MemoryLocation(Arg,
23369952979SGeorge Burgess IV LocationSize::precise(DL.getTypeStoreSize(
23469952979SGeorge Burgess IV II->getArgOperand(1)->getType())),
23569952979SGeorge Burgess IV AATags);
236c41404a0SChandler Carruth }
237a9125792SFlorian Hahn
238a9125792SFlorian Hahn assert(
239a9125792SFlorian Hahn !isa<AnyMemTransferInst>(II) &&
240a9125792SFlorian Hahn "all memory transfer intrinsics should be handled by the switch above");
241c41404a0SChandler Carruth }
242c41404a0SChandler Carruth
243c41404a0SChandler Carruth // We can bound the aliasing properties of memset_pattern16 just as we can
244c41404a0SChandler Carruth // for memcpy/memset. This is particularly important because the
245c41404a0SChandler Carruth // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
246c41404a0SChandler Carruth // whenever possible.
247d21529faSDavid L. Jones LibFunc F;
248fd6ebea5SFlorian Hahn if (TLI && TLI->getLibFunc(*Call, F) && TLI->has(F)) {
249fd6ebea5SFlorian Hahn switch (F) {
250829b29b6SFlorian Hahn case LibFunc_strcpy:
251829b29b6SFlorian Hahn case LibFunc_strcat:
252829b29b6SFlorian Hahn case LibFunc_strncat:
253829b29b6SFlorian Hahn assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for str function");
254829b29b6SFlorian Hahn return MemoryLocation::getAfter(Arg, AATags);
255829b29b6SFlorian Hahn
2569f9e8ba1SFlorian Hahn case LibFunc_memset_chk: {
2579f9e8ba1SFlorian Hahn assert(ArgIdx == 0 && "Invalid argument index for memset_chk");
2589f9e8ba1SFlorian Hahn LocationSize Size = LocationSize::afterPointer();
2599f9e8ba1SFlorian Hahn if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
2609f9e8ba1SFlorian Hahn // memset_chk writes at most Len bytes. It may write less, if Len
2619f9e8ba1SFlorian Hahn // exceeds the specified max size and aborts.
2629f9e8ba1SFlorian Hahn Size = LocationSize::upperBound(Len->getZExtValue());
2639f9e8ba1SFlorian Hahn }
2649f9e8ba1SFlorian Hahn return MemoryLocation(Arg, Size, AATags);
2659f9e8ba1SFlorian Hahn }
266639a78a4SFlorian Hahn case LibFunc_strncpy: {
267639a78a4SFlorian Hahn assert((ArgIdx == 0 || ArgIdx == 1) &&
268639a78a4SFlorian Hahn "Invalid argument index for strncpy");
269639a78a4SFlorian Hahn LocationSize Size = LocationSize::afterPointer();
270639a78a4SFlorian Hahn if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
271639a78a4SFlorian Hahn // strncpy is guaranteed to write Len bytes, but only reads up to Len
272639a78a4SFlorian Hahn // bytes.
273639a78a4SFlorian Hahn Size = ArgIdx == 0 ? LocationSize::precise(Len->getZExtValue())
274639a78a4SFlorian Hahn : LocationSize::upperBound(Len->getZExtValue());
275639a78a4SFlorian Hahn }
276639a78a4SFlorian Hahn return MemoryLocation(Arg, Size, AATags);
277639a78a4SFlorian Hahn }
278fd6ebea5SFlorian Hahn case LibFunc_memset_pattern16:
2793c55acc4SFlorian Hahn case LibFunc_memset_pattern4:
2803c55acc4SFlorian Hahn case LibFunc_memset_pattern8:
281c41404a0SChandler Carruth assert((ArgIdx == 0 || ArgIdx == 1) &&
282c41404a0SChandler Carruth "Invalid argument index for memset_pattern16");
2833c55acc4SFlorian Hahn if (ArgIdx == 1) {
2843c55acc4SFlorian Hahn unsigned Size = 16;
2853c55acc4SFlorian Hahn if (F == LibFunc_memset_pattern4)
2863c55acc4SFlorian Hahn Size = 4;
2873c55acc4SFlorian Hahn else if (F == LibFunc_memset_pattern8)
2883c55acc4SFlorian Hahn Size = 8;
2893c55acc4SFlorian Hahn return MemoryLocation(Arg, LocationSize::precise(Size), AATags);
2903c55acc4SFlorian Hahn }
291363ac683SChandler Carruth if (const ConstantInt *LenCI =
292363ac683SChandler Carruth dyn_cast<ConstantInt>(Call->getArgOperand(2)))
29369952979SGeorge Burgess IV return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
29469952979SGeorge Burgess IV AATags);
2954df8efceSNikita Popov return MemoryLocation::getAfter(Arg, AATags);
296d716f160SDávid Bolvanský case LibFunc_bcmp:
297fd6ebea5SFlorian Hahn case LibFunc_memcmp:
298fd6ebea5SFlorian Hahn assert((ArgIdx == 0 || ArgIdx == 1) &&
299d716f160SDávid Bolvanský "Invalid argument index for memcmp/bcmp");
300fd6ebea5SFlorian Hahn if (const ConstantInt *LenCI =
301fd6ebea5SFlorian Hahn dyn_cast<ConstantInt>(Call->getArgOperand(2)))
302fd6ebea5SFlorian Hahn return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
303fd6ebea5SFlorian Hahn AATags);
3044df8efceSNikita Popov return MemoryLocation::getAfter(Arg, AATags);
30528691cddSDávid Bolvanský case LibFunc_memchr:
30628691cddSDávid Bolvanský assert((ArgIdx == 0) && "Invalid argument index for memchr");
30728691cddSDávid Bolvanský if (const ConstantInt *LenCI =
30828691cddSDávid Bolvanský dyn_cast<ConstantInt>(Call->getArgOperand(2)))
30928691cddSDávid Bolvanský return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
31028691cddSDávid Bolvanský AATags);
3114df8efceSNikita Popov return MemoryLocation::getAfter(Arg, AATags);
31228691cddSDávid Bolvanský case LibFunc_memccpy:
31328691cddSDávid Bolvanský assert((ArgIdx == 0 || ArgIdx == 1) &&
31428691cddSDávid Bolvanský "Invalid argument index for memccpy");
31549cddb90SDávid Bolvanský // We only know an upper bound on the number of bytes read/written.
31628691cddSDávid Bolvanský if (const ConstantInt *LenCI =
31728691cddSDávid Bolvanský dyn_cast<ConstantInt>(Call->getArgOperand(3)))
31849cddb90SDávid Bolvanský return MemoryLocation(
31949cddb90SDávid Bolvanský Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);
3204df8efceSNikita Popov return MemoryLocation::getAfter(Arg, AATags);
321fd6ebea5SFlorian Hahn default:
322fd6ebea5SFlorian Hahn break;
323fd6ebea5SFlorian Hahn };
324c41404a0SChandler Carruth }
325c41404a0SChandler Carruth
3264df8efceSNikita Popov return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);
327c41404a0SChandler Carruth }
328