xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/MemoryLocation.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MemoryLocation.cpp - Memory location descriptions -------------------==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
100b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
110b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
120b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
130b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
14480093f4SDimitry Andric #include "llvm/IR/IntrinsicsARM.h"
150b57cec5SDimitry Andric #include "llvm/IR/Module.h"
160b57cec5SDimitry Andric #include "llvm/IR/Type.h"
17bdd1243dSDimitry Andric #include <optional>
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric void LocationSize::print(raw_ostream &OS) const {
210b57cec5SDimitry Andric   OS << "LocationSize::";
22e8d8bef9SDimitry Andric   if (*this == beforeOrAfterPointer())
23e8d8bef9SDimitry Andric     OS << "beforeOrAfterPointer";
24e8d8bef9SDimitry Andric   else if (*this == afterPointer())
25e8d8bef9SDimitry Andric     OS << "afterPointer";
260b57cec5SDimitry Andric   else if (*this == mapEmpty())
270b57cec5SDimitry Andric     OS << "mapEmpty";
280b57cec5SDimitry Andric   else if (*this == mapTombstone())
290b57cec5SDimitry Andric     OS << "mapTombstone";
300b57cec5SDimitry Andric   else if (isPrecise())
310b57cec5SDimitry Andric     OS << "precise(" << getValue() << ')';
320b57cec5SDimitry Andric   else
330b57cec5SDimitry Andric     OS << "upperBound(" << getValue() << ')';
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric MemoryLocation MemoryLocation::get(const LoadInst *LI) {
37*0fca6ea1SDimitry Andric   const auto &DL = LI->getDataLayout();
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   return MemoryLocation(
400b57cec5SDimitry Andric       LI->getPointerOperand(),
41349cc55cSDimitry Andric       LocationSize::precise(DL.getTypeStoreSize(LI->getType())),
42349cc55cSDimitry Andric       LI->getAAMetadata());
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric MemoryLocation MemoryLocation::get(const StoreInst *SI) {
46*0fca6ea1SDimitry Andric   const auto &DL = SI->getDataLayout();
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   return MemoryLocation(SI->getPointerOperand(),
490b57cec5SDimitry Andric                         LocationSize::precise(DL.getTypeStoreSize(
500b57cec5SDimitry Andric                             SI->getValueOperand()->getType())),
51349cc55cSDimitry Andric                         SI->getAAMetadata());
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric MemoryLocation MemoryLocation::get(const VAArgInst *VI) {
55e8d8bef9SDimitry Andric   return MemoryLocation(VI->getPointerOperand(),
56349cc55cSDimitry Andric                         LocationSize::afterPointer(), VI->getAAMetadata());
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) {
60*0fca6ea1SDimitry Andric   const auto &DL = CXI->getDataLayout();
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   return MemoryLocation(CXI->getPointerOperand(),
630b57cec5SDimitry Andric                         LocationSize::precise(DL.getTypeStoreSize(
640b57cec5SDimitry Andric                             CXI->getCompareOperand()->getType())),
65349cc55cSDimitry Andric                         CXI->getAAMetadata());
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric MemoryLocation MemoryLocation::get(const AtomicRMWInst *RMWI) {
69*0fca6ea1SDimitry Andric   const auto &DL = RMWI->getDataLayout();
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   return MemoryLocation(RMWI->getPointerOperand(),
720b57cec5SDimitry Andric                         LocationSize::precise(DL.getTypeStoreSize(
730b57cec5SDimitry Andric                             RMWI->getValOperand()->getType())),
74349cc55cSDimitry Andric                         RMWI->getAAMetadata());
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
77bdd1243dSDimitry Andric std::optional<MemoryLocation>
78bdd1243dSDimitry Andric MemoryLocation::getOrNone(const Instruction *Inst) {
795ffd83dbSDimitry Andric   switch (Inst->getOpcode()) {
805ffd83dbSDimitry Andric   case Instruction::Load:
815ffd83dbSDimitry Andric     return get(cast<LoadInst>(Inst));
825ffd83dbSDimitry Andric   case Instruction::Store:
835ffd83dbSDimitry Andric     return get(cast<StoreInst>(Inst));
845ffd83dbSDimitry Andric   case Instruction::VAArg:
855ffd83dbSDimitry Andric     return get(cast<VAArgInst>(Inst));
865ffd83dbSDimitry Andric   case Instruction::AtomicCmpXchg:
875ffd83dbSDimitry Andric     return get(cast<AtomicCmpXchgInst>(Inst));
885ffd83dbSDimitry Andric   case Instruction::AtomicRMW:
895ffd83dbSDimitry Andric     return get(cast<AtomicRMWInst>(Inst));
905ffd83dbSDimitry Andric   default:
91bdd1243dSDimitry Andric     return std::nullopt;
925ffd83dbSDimitry Andric   }
935ffd83dbSDimitry Andric }
945ffd83dbSDimitry Andric 
950b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForSource(const MemTransferInst *MTI) {
960b57cec5SDimitry Andric   return getForSource(cast<AnyMemTransferInst>(MTI));
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForSource(const AtomicMemTransferInst *MTI) {
1000b57cec5SDimitry Andric   return getForSource(cast<AnyMemTransferInst>(MTI));
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) {
1040eae32dcSDimitry Andric   assert(MTI->getRawSource() == MTI->getArgOperand(1));
1050eae32dcSDimitry Andric   return getForArgument(MTI, 1, nullptr);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MI) {
1090b57cec5SDimitry Andric   return getForDest(cast<AnyMemIntrinsic>(MI));
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForDest(const AtomicMemIntrinsic *MI) {
1130b57cec5SDimitry Andric   return getForDest(cast<AnyMemIntrinsic>(MI));
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) {
1170eae32dcSDimitry Andric   assert(MI->getRawDest() == MI->getArgOperand(0));
1180eae32dcSDimitry Andric   return getForArgument(MI, 0, nullptr);
1190eae32dcSDimitry Andric }
1200b57cec5SDimitry Andric 
121bdd1243dSDimitry Andric std::optional<MemoryLocation>
1220eae32dcSDimitry Andric MemoryLocation::getForDest(const CallBase *CB, const TargetLibraryInfo &TLI) {
1230eae32dcSDimitry Andric   if (!CB->onlyAccessesArgMemory())
124bdd1243dSDimitry Andric     return std::nullopt;
1250eae32dcSDimitry Andric 
1260eae32dcSDimitry Andric   if (CB->hasOperandBundles())
1270eae32dcSDimitry Andric     // TODO: remove implementation restriction
128bdd1243dSDimitry Andric     return std::nullopt;
1290eae32dcSDimitry Andric 
1300eae32dcSDimitry Andric   Value *UsedV = nullptr;
131bdd1243dSDimitry Andric   std::optional<unsigned> UsedIdx;
1320eae32dcSDimitry Andric   for (unsigned i = 0; i < CB->arg_size(); i++) {
1330eae32dcSDimitry Andric     if (!CB->getArgOperand(i)->getType()->isPointerTy())
1340eae32dcSDimitry Andric       continue;
1350eae32dcSDimitry Andric     if (CB->onlyReadsMemory(i))
1360eae32dcSDimitry Andric       continue;
1370eae32dcSDimitry Andric     if (!UsedV) {
1380eae32dcSDimitry Andric       // First potentially writing parameter
1390eae32dcSDimitry Andric       UsedV = CB->getArgOperand(i);
1400eae32dcSDimitry Andric       UsedIdx = i;
1410eae32dcSDimitry Andric       continue;
1420eae32dcSDimitry Andric     }
143bdd1243dSDimitry Andric     UsedIdx = std::nullopt;
1440eae32dcSDimitry Andric     if (UsedV != CB->getArgOperand(i))
1450eae32dcSDimitry Andric       // Can't describe writing to two distinct locations.
1460eae32dcSDimitry Andric       // TODO: This results in an inprecision when two values derived from the
1470eae32dcSDimitry Andric       // same object are passed as arguments to the same function.
148bdd1243dSDimitry Andric       return std::nullopt;
1490eae32dcSDimitry Andric   }
1500eae32dcSDimitry Andric   if (!UsedV)
1510eae32dcSDimitry Andric     // We don't currently have a way to represent a "does not write" result
1520eae32dcSDimitry Andric     // and thus have to be conservative and return unknown.
153bdd1243dSDimitry Andric     return std::nullopt;
1540eae32dcSDimitry Andric 
1550eae32dcSDimitry Andric   if (UsedIdx)
1560eae32dcSDimitry Andric     return getForArgument(CB, *UsedIdx, &TLI);
1570eae32dcSDimitry Andric   return MemoryLocation::getBeforeOrAfter(UsedV, CB->getAAMetadata());
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
1610b57cec5SDimitry Andric                                               unsigned ArgIdx,
1620b57cec5SDimitry Andric                                               const TargetLibraryInfo *TLI) {
163349cc55cSDimitry Andric   AAMDNodes AATags = Call->getAAMetadata();
1640b57cec5SDimitry Andric   const Value *Arg = Call->getArgOperand(ArgIdx);
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   // We may be able to produce an exact size for known intrinsics.
1670b57cec5SDimitry Andric   if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call)) {
168*0fca6ea1SDimitry Andric     const DataLayout &DL = II->getDataLayout();
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     switch (II->getIntrinsicID()) {
1710b57cec5SDimitry Andric     default:
1720b57cec5SDimitry Andric       break;
1730b57cec5SDimitry Andric     case Intrinsic::memset:
1740b57cec5SDimitry Andric     case Intrinsic::memcpy:
175e8d8bef9SDimitry Andric     case Intrinsic::memcpy_inline:
1760b57cec5SDimitry Andric     case Intrinsic::memmove:
1770eae32dcSDimitry Andric     case Intrinsic::memcpy_element_unordered_atomic:
1780eae32dcSDimitry Andric     case Intrinsic::memmove_element_unordered_atomic:
1790eae32dcSDimitry Andric     case Intrinsic::memset_element_unordered_atomic:
1800b57cec5SDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
1810b57cec5SDimitry Andric              "Invalid argument index for memory intrinsic");
1820b57cec5SDimitry Andric       if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
1830b57cec5SDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
1840b57cec5SDimitry Andric                               AATags);
185e8d8bef9SDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     case Intrinsic::lifetime_start:
1880b57cec5SDimitry Andric     case Intrinsic::lifetime_end:
1890b57cec5SDimitry Andric     case Intrinsic::invariant_start:
1900b57cec5SDimitry Andric       assert(ArgIdx == 1 && "Invalid argument index");
1910b57cec5SDimitry Andric       return MemoryLocation(
1920b57cec5SDimitry Andric           Arg,
1930b57cec5SDimitry Andric           LocationSize::precise(
1940b57cec5SDimitry Andric               cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),
1950b57cec5SDimitry Andric           AATags);
1960b57cec5SDimitry Andric 
197e8d8bef9SDimitry Andric     case Intrinsic::masked_load:
198e8d8bef9SDimitry Andric       assert(ArgIdx == 0 && "Invalid argument index");
199e8d8bef9SDimitry Andric       return MemoryLocation(
200e8d8bef9SDimitry Andric           Arg,
201e8d8bef9SDimitry Andric           LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),
202e8d8bef9SDimitry Andric           AATags);
203e8d8bef9SDimitry Andric 
204e8d8bef9SDimitry Andric     case Intrinsic::masked_store:
205e8d8bef9SDimitry Andric       assert(ArgIdx == 1 && "Invalid argument index");
206e8d8bef9SDimitry Andric       return MemoryLocation(
207e8d8bef9SDimitry Andric           Arg,
208e8d8bef9SDimitry Andric           LocationSize::upperBound(
209e8d8bef9SDimitry Andric               DL.getTypeStoreSize(II->getArgOperand(0)->getType())),
210e8d8bef9SDimitry Andric           AATags);
211e8d8bef9SDimitry Andric 
2120b57cec5SDimitry Andric     case Intrinsic::invariant_end:
2130b57cec5SDimitry Andric       // The first argument to an invariant.end is a "descriptor" type (e.g. a
2140b57cec5SDimitry Andric       // pointer to a empty struct) which is never actually dereferenced.
2150b57cec5SDimitry Andric       if (ArgIdx == 0)
2160b57cec5SDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(0), AATags);
2170b57cec5SDimitry Andric       assert(ArgIdx == 2 && "Invalid argument index");
2180b57cec5SDimitry Andric       return MemoryLocation(
2190b57cec5SDimitry Andric           Arg,
2200b57cec5SDimitry Andric           LocationSize::precise(
2210b57cec5SDimitry Andric               cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()),
2220b57cec5SDimitry Andric           AATags);
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric     case Intrinsic::arm_neon_vld1:
2250b57cec5SDimitry Andric       assert(ArgIdx == 0 && "Invalid argument index");
2260b57cec5SDimitry Andric       // LLVM's vld1 and vst1 intrinsics currently only support a single
2270b57cec5SDimitry Andric       // vector register.
2280b57cec5SDimitry Andric       return MemoryLocation(
2290b57cec5SDimitry Andric           Arg, LocationSize::precise(DL.getTypeStoreSize(II->getType())),
2300b57cec5SDimitry Andric           AATags);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     case Intrinsic::arm_neon_vst1:
2330b57cec5SDimitry Andric       assert(ArgIdx == 0 && "Invalid argument index");
2340b57cec5SDimitry Andric       return MemoryLocation(Arg,
2350b57cec5SDimitry Andric                             LocationSize::precise(DL.getTypeStoreSize(
2360b57cec5SDimitry Andric                                 II->getArgOperand(1)->getType())),
2370b57cec5SDimitry Andric                             AATags);
2380b57cec5SDimitry Andric     }
2390eae32dcSDimitry Andric 
2400eae32dcSDimitry Andric     assert(
2410eae32dcSDimitry Andric         !isa<AnyMemTransferInst>(II) &&
2420eae32dcSDimitry Andric         "all memory transfer intrinsics should be handled by the switch above");
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   // We can bound the aliasing properties of memset_pattern16 just as we can
2460b57cec5SDimitry Andric   // for memcpy/memset.  This is particularly important because the
2470b57cec5SDimitry Andric   // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
2480b57cec5SDimitry Andric   // whenever possible.
2490b57cec5SDimitry Andric   LibFunc F;
250e8d8bef9SDimitry Andric   if (TLI && TLI->getLibFunc(*Call, F) && TLI->has(F)) {
251e8d8bef9SDimitry Andric     switch (F) {
2520eae32dcSDimitry Andric     case LibFunc_strcpy:
2530eae32dcSDimitry Andric     case LibFunc_strcat:
2540eae32dcSDimitry Andric     case LibFunc_strncat:
2550eae32dcSDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for str function");
2560eae32dcSDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
2570eae32dcSDimitry Andric 
258bdd1243dSDimitry Andric     case LibFunc_memset_chk:
2594824e7fdSDimitry Andric       assert(ArgIdx == 0 && "Invalid argument index for memset_chk");
26006c3fb27SDimitry Andric       [[fallthrough]];
261bdd1243dSDimitry Andric     case LibFunc_memcpy_chk: {
262bdd1243dSDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
263bdd1243dSDimitry Andric              "Invalid argument index for memcpy_chk");
2644824e7fdSDimitry Andric       LocationSize Size = LocationSize::afterPointer();
2654824e7fdSDimitry Andric       if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
266bdd1243dSDimitry Andric         // memset_chk writes at most Len bytes, memcpy_chk reads/writes at most
267bdd1243dSDimitry Andric         // Len bytes. They may read/write less, if Len exceeds the specified max
268bdd1243dSDimitry Andric         // size and aborts.
2694824e7fdSDimitry Andric         Size = LocationSize::upperBound(Len->getZExtValue());
2704824e7fdSDimitry Andric       }
2714824e7fdSDimitry Andric       return MemoryLocation(Arg, Size, AATags);
2724824e7fdSDimitry Andric     }
2734824e7fdSDimitry Andric     case LibFunc_strncpy: {
2744824e7fdSDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
2754824e7fdSDimitry Andric              "Invalid argument index for strncpy");
2764824e7fdSDimitry Andric       LocationSize Size = LocationSize::afterPointer();
2774824e7fdSDimitry Andric       if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
2784824e7fdSDimitry Andric         // strncpy is guaranteed to write Len bytes, but only reads up to Len
2794824e7fdSDimitry Andric         // bytes.
2804824e7fdSDimitry Andric         Size = ArgIdx == 0 ? LocationSize::precise(Len->getZExtValue())
2814824e7fdSDimitry Andric                            : LocationSize::upperBound(Len->getZExtValue());
2824824e7fdSDimitry Andric       }
2834824e7fdSDimitry Andric       return MemoryLocation(Arg, Size, AATags);
2844824e7fdSDimitry Andric     }
285e8d8bef9SDimitry Andric     case LibFunc_memset_pattern16:
2860eae32dcSDimitry Andric     case LibFunc_memset_pattern4:
2870eae32dcSDimitry Andric     case LibFunc_memset_pattern8:
2880b57cec5SDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
2890b57cec5SDimitry Andric              "Invalid argument index for memset_pattern16");
2900eae32dcSDimitry Andric       if (ArgIdx == 1) {
2910eae32dcSDimitry Andric         unsigned Size = 16;
2920eae32dcSDimitry Andric         if (F == LibFunc_memset_pattern4)
2930eae32dcSDimitry Andric           Size = 4;
2940eae32dcSDimitry Andric         else if (F == LibFunc_memset_pattern8)
2950eae32dcSDimitry Andric           Size = 8;
2960eae32dcSDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(Size), AATags);
2970eae32dcSDimitry Andric       }
2980b57cec5SDimitry Andric       if (const ConstantInt *LenCI =
2990b57cec5SDimitry Andric               dyn_cast<ConstantInt>(Call->getArgOperand(2)))
3000b57cec5SDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
3010b57cec5SDimitry Andric                               AATags);
302e8d8bef9SDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
303e8d8bef9SDimitry Andric     case LibFunc_bcmp:
304e8d8bef9SDimitry Andric     case LibFunc_memcmp:
305e8d8bef9SDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
306e8d8bef9SDimitry Andric              "Invalid argument index for memcmp/bcmp");
307e8d8bef9SDimitry Andric       if (const ConstantInt *LenCI =
308e8d8bef9SDimitry Andric               dyn_cast<ConstantInt>(Call->getArgOperand(2)))
309e8d8bef9SDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
310e8d8bef9SDimitry Andric                               AATags);
311e8d8bef9SDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
312e8d8bef9SDimitry Andric     case LibFunc_memchr:
313e8d8bef9SDimitry Andric       assert((ArgIdx == 0) && "Invalid argument index for memchr");
314e8d8bef9SDimitry Andric       if (const ConstantInt *LenCI =
315e8d8bef9SDimitry Andric               dyn_cast<ConstantInt>(Call->getArgOperand(2)))
316e8d8bef9SDimitry Andric         return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
317e8d8bef9SDimitry Andric                               AATags);
318e8d8bef9SDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
319e8d8bef9SDimitry Andric     case LibFunc_memccpy:
320e8d8bef9SDimitry Andric       assert((ArgIdx == 0 || ArgIdx == 1) &&
321e8d8bef9SDimitry Andric              "Invalid argument index for memccpy");
322e8d8bef9SDimitry Andric       // We only know an upper bound on the number of bytes read/written.
323e8d8bef9SDimitry Andric       if (const ConstantInt *LenCI =
324e8d8bef9SDimitry Andric               dyn_cast<ConstantInt>(Call->getArgOperand(3)))
325e8d8bef9SDimitry Andric         return MemoryLocation(
326e8d8bef9SDimitry Andric             Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);
327e8d8bef9SDimitry Andric       return MemoryLocation::getAfter(Arg, AATags);
328e8d8bef9SDimitry Andric     default:
329e8d8bef9SDimitry Andric       break;
330e8d8bef9SDimitry Andric     };
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
333e8d8bef9SDimitry Andric   return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);
3340b57cec5SDimitry Andric }
335