llvm-project
334 строки · 12.1 Кб
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
9#include "llvm/Analysis/MemoryLocation.h"10#include "llvm/Analysis/TargetLibraryInfo.h"11#include "llvm/IR/DataLayout.h"12#include "llvm/IR/Instructions.h"13#include "llvm/IR/IntrinsicInst.h"14#include "llvm/IR/IntrinsicsARM.h"15#include "llvm/IR/Module.h"16#include "llvm/IR/Type.h"17#include <optional>18using namespace llvm;19
20void LocationSize::print(raw_ostream &OS) const {21OS << "LocationSize::";22if (*this == beforeOrAfterPointer())23OS << "beforeOrAfterPointer";24else if (*this == afterPointer())25OS << "afterPointer";26else if (*this == mapEmpty())27OS << "mapEmpty";28else if (*this == mapTombstone())29OS << "mapTombstone";30else if (isPrecise())31OS << "precise(" << getValue() << ')';32else33OS << "upperBound(" << getValue() << ')';34}
35
36MemoryLocation MemoryLocation::get(const LoadInst *LI) {37const auto &DL = LI->getDataLayout();38
39return MemoryLocation(40LI->getPointerOperand(),41LocationSize::precise(DL.getTypeStoreSize(LI->getType())),42LI->getAAMetadata());43}
44
45MemoryLocation MemoryLocation::get(const StoreInst *SI) {46const auto &DL = SI->getDataLayout();47
48return MemoryLocation(SI->getPointerOperand(),49LocationSize::precise(DL.getTypeStoreSize(50SI->getValueOperand()->getType())),51SI->getAAMetadata());52}
53
54MemoryLocation MemoryLocation::get(const VAArgInst *VI) {55return MemoryLocation(VI->getPointerOperand(),56LocationSize::afterPointer(), VI->getAAMetadata());57}
58
59MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) {60const auto &DL = CXI->getDataLayout();61
62return MemoryLocation(CXI->getPointerOperand(),63LocationSize::precise(DL.getTypeStoreSize(64CXI->getCompareOperand()->getType())),65CXI->getAAMetadata());66}
67
68MemoryLocation MemoryLocation::get(const AtomicRMWInst *RMWI) {69const auto &DL = RMWI->getDataLayout();70
71return MemoryLocation(RMWI->getPointerOperand(),72LocationSize::precise(DL.getTypeStoreSize(73RMWI->getValOperand()->getType())),74RMWI->getAAMetadata());75}
76
77std::optional<MemoryLocation>78MemoryLocation::getOrNone(const Instruction *Inst) {79switch (Inst->getOpcode()) {80case Instruction::Load:81return get(cast<LoadInst>(Inst));82case Instruction::Store:83return get(cast<StoreInst>(Inst));84case Instruction::VAArg:85return get(cast<VAArgInst>(Inst));86case Instruction::AtomicCmpXchg:87return get(cast<AtomicCmpXchgInst>(Inst));88case Instruction::AtomicRMW:89return get(cast<AtomicRMWInst>(Inst));90default:91return std::nullopt;92}93}
94
95MemoryLocation MemoryLocation::getForSource(const MemTransferInst *MTI) {96return getForSource(cast<AnyMemTransferInst>(MTI));97}
98
99MemoryLocation MemoryLocation::getForSource(const AtomicMemTransferInst *MTI) {100return getForSource(cast<AnyMemTransferInst>(MTI));101}
102
103MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) {104assert(MTI->getRawSource() == MTI->getArgOperand(1));105return getForArgument(MTI, 1, nullptr);106}
107
108MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MI) {109return getForDest(cast<AnyMemIntrinsic>(MI));110}
111
112MemoryLocation MemoryLocation::getForDest(const AtomicMemIntrinsic *MI) {113return getForDest(cast<AnyMemIntrinsic>(MI));114}
115
116MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) {117assert(MI->getRawDest() == MI->getArgOperand(0));118return getForArgument(MI, 0, nullptr);119}
120
121std::optional<MemoryLocation>122MemoryLocation::getForDest(const CallBase *CB, const TargetLibraryInfo &TLI) {123if (!CB->onlyAccessesArgMemory())124return std::nullopt;125
126if (CB->hasOperandBundles())127// TODO: remove implementation restriction128return std::nullopt;129
130Value *UsedV = nullptr;131std::optional<unsigned> UsedIdx;132for (unsigned i = 0; i < CB->arg_size(); i++) {133if (!CB->getArgOperand(i)->getType()->isPointerTy())134continue;135if (CB->onlyReadsMemory(i))136continue;137if (!UsedV) {138// First potentially writing parameter139UsedV = CB->getArgOperand(i);140UsedIdx = i;141continue;142}143UsedIdx = std::nullopt;144if (UsedV != CB->getArgOperand(i))145// Can't describe writing to two distinct locations.146// TODO: This results in an inprecision when two values derived from the147// same object are passed as arguments to the same function.148return std::nullopt;149}150if (!UsedV)151// We don't currently have a way to represent a "does not write" result152// and thus have to be conservative and return unknown.153return std::nullopt;154
155if (UsedIdx)156return getForArgument(CB, *UsedIdx, &TLI);157return MemoryLocation::getBeforeOrAfter(UsedV, CB->getAAMetadata());158}
159
160MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,161unsigned ArgIdx,162const TargetLibraryInfo *TLI) {163AAMDNodes AATags = Call->getAAMetadata();164const Value *Arg = Call->getArgOperand(ArgIdx);165
166// We may be able to produce an exact size for known intrinsics.167if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call)) {168const DataLayout &DL = II->getDataLayout();169
170switch (II->getIntrinsicID()) {171default:172break;173case Intrinsic::memset:174case Intrinsic::memcpy:175case Intrinsic::memcpy_inline:176case Intrinsic::memmove:177case Intrinsic::memcpy_element_unordered_atomic:178case Intrinsic::memmove_element_unordered_atomic:179case Intrinsic::memset_element_unordered_atomic:180assert((ArgIdx == 0 || ArgIdx == 1) &&181"Invalid argument index for memory intrinsic");182if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))183return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),184AATags);185return MemoryLocation::getAfter(Arg, AATags);186
187case Intrinsic::lifetime_start:188case Intrinsic::lifetime_end:189case Intrinsic::invariant_start:190assert(ArgIdx == 1 && "Invalid argument index");191return MemoryLocation(192Arg,193LocationSize::precise(194cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),195AATags);196
197case Intrinsic::masked_load:198assert(ArgIdx == 0 && "Invalid argument index");199return MemoryLocation(200Arg,201LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),202AATags);203
204case Intrinsic::masked_store:205assert(ArgIdx == 1 && "Invalid argument index");206return MemoryLocation(207Arg,208LocationSize::upperBound(209DL.getTypeStoreSize(II->getArgOperand(0)->getType())),210AATags);211
212case Intrinsic::invariant_end:213// The first argument to an invariant.end is a "descriptor" type (e.g. a214// pointer to a empty struct) which is never actually dereferenced.215if (ArgIdx == 0)216return MemoryLocation(Arg, LocationSize::precise(0), AATags);217assert(ArgIdx == 2 && "Invalid argument index");218return MemoryLocation(219Arg,220LocationSize::precise(221cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()),222AATags);223
224case Intrinsic::arm_neon_vld1:225assert(ArgIdx == 0 && "Invalid argument index");226// LLVM's vld1 and vst1 intrinsics currently only support a single227// vector register.228return MemoryLocation(229Arg, LocationSize::precise(DL.getTypeStoreSize(II->getType())),230AATags);231
232case Intrinsic::arm_neon_vst1:233assert(ArgIdx == 0 && "Invalid argument index");234return MemoryLocation(Arg,235LocationSize::precise(DL.getTypeStoreSize(236II->getArgOperand(1)->getType())),237AATags);238}239
240assert(241!isa<AnyMemTransferInst>(II) &&242"all memory transfer intrinsics should be handled by the switch above");243}244
245// We can bound the aliasing properties of memset_pattern16 just as we can246// for memcpy/memset. This is particularly important because the247// LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16248// whenever possible.249LibFunc F;250if (TLI && TLI->getLibFunc(*Call, F) && TLI->has(F)) {251switch (F) {252case LibFunc_strcpy:253case LibFunc_strcat:254case LibFunc_strncat:255assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for str function");256return MemoryLocation::getAfter(Arg, AATags);257
258case LibFunc_memset_chk:259assert(ArgIdx == 0 && "Invalid argument index for memset_chk");260[[fallthrough]];261case LibFunc_memcpy_chk: {262assert((ArgIdx == 0 || ArgIdx == 1) &&263"Invalid argument index for memcpy_chk");264LocationSize Size = LocationSize::afterPointer();265if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {266// memset_chk writes at most Len bytes, memcpy_chk reads/writes at most267// Len bytes. They may read/write less, if Len exceeds the specified max268// size and aborts.269Size = LocationSize::upperBound(Len->getZExtValue());270}271return MemoryLocation(Arg, Size, AATags);272}273case LibFunc_strncpy: {274assert((ArgIdx == 0 || ArgIdx == 1) &&275"Invalid argument index for strncpy");276LocationSize Size = LocationSize::afterPointer();277if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {278// strncpy is guaranteed to write Len bytes, but only reads up to Len279// bytes.280Size = ArgIdx == 0 ? LocationSize::precise(Len->getZExtValue())281: LocationSize::upperBound(Len->getZExtValue());282}283return MemoryLocation(Arg, Size, AATags);284}285case LibFunc_memset_pattern16:286case LibFunc_memset_pattern4:287case LibFunc_memset_pattern8:288assert((ArgIdx == 0 || ArgIdx == 1) &&289"Invalid argument index for memset_pattern16");290if (ArgIdx == 1) {291unsigned Size = 16;292if (F == LibFunc_memset_pattern4)293Size = 4;294else if (F == LibFunc_memset_pattern8)295Size = 8;296return MemoryLocation(Arg, LocationSize::precise(Size), AATags);297}298if (const ConstantInt *LenCI =299dyn_cast<ConstantInt>(Call->getArgOperand(2)))300return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),301AATags);302return MemoryLocation::getAfter(Arg, AATags);303case LibFunc_bcmp:304case LibFunc_memcmp:305assert((ArgIdx == 0 || ArgIdx == 1) &&306"Invalid argument index for memcmp/bcmp");307if (const ConstantInt *LenCI =308dyn_cast<ConstantInt>(Call->getArgOperand(2)))309return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),310AATags);311return MemoryLocation::getAfter(Arg, AATags);312case LibFunc_memchr:313assert((ArgIdx == 0) && "Invalid argument index for memchr");314if (const ConstantInt *LenCI =315dyn_cast<ConstantInt>(Call->getArgOperand(2)))316return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),317AATags);318return MemoryLocation::getAfter(Arg, AATags);319case LibFunc_memccpy:320assert((ArgIdx == 0 || ArgIdx == 1) &&321"Invalid argument index for memccpy");322// We only know an upper bound on the number of bytes read/written.323if (const ConstantInt *LenCI =324dyn_cast<ConstantInt>(Call->getArgOperand(3)))325return MemoryLocation(326Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);327return MemoryLocation::getAfter(Arg, AATags);328default:329break;330};331}332
333return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);334}
335