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