Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/CaptureTracking.cpp
35233 views
//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains routines that help determine which pointers are captured.9// A pointer value is captured if the function makes a copy of any part of the10// pointer that outlives the call. Not being captured means, more or less, that11// the pointer is only dereferenced and not stored in a global. Returning part12// of the pointer as the function return value may or may not count as capturing13// the pointer, depending on the context.14//15//===----------------------------------------------------------------------===//1617#include "llvm/Analysis/CaptureTracking.h"18#include "llvm/ADT/SmallSet.h"19#include "llvm/ADT/SmallVector.h"20#include "llvm/ADT/Statistic.h"21#include "llvm/Analysis/AliasAnalysis.h"22#include "llvm/Analysis/CFG.h"23#include "llvm/Analysis/ValueTracking.h"24#include "llvm/IR/Constants.h"25#include "llvm/IR/Dominators.h"26#include "llvm/IR/Instructions.h"27#include "llvm/IR/IntrinsicInst.h"28#include "llvm/Support/CommandLine.h"2930using namespace llvm;3132#define DEBUG_TYPE "capture-tracking"3334STATISTIC(NumCaptured, "Number of pointers maybe captured");35STATISTIC(NumNotCaptured, "Number of pointers not captured");36STATISTIC(NumCapturedBefore, "Number of pointers maybe captured before");37STATISTIC(NumNotCapturedBefore, "Number of pointers not captured before");3839/// The default value for MaxUsesToExplore argument. It's relatively small to40/// keep the cost of analysis reasonable for clients like BasicAliasAnalysis,41/// where the results can't be cached.42/// TODO: we should probably introduce a caching CaptureTracking analysis and43/// use it where possible. The caching version can use much higher limit or44/// don't have this cap at all.45static cl::opt<unsigned>46DefaultMaxUsesToExplore("capture-tracking-max-uses-to-explore", cl::Hidden,47cl::desc("Maximal number of uses to explore."),48cl::init(100));4950unsigned llvm::getDefaultMaxUsesToExploreForCaptureTracking() {51return DefaultMaxUsesToExplore;52}5354CaptureTracker::~CaptureTracker() = default;5556bool CaptureTracker::shouldExplore(const Use *U) { return true; }5758bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {59// We want comparisons to null pointers to not be considered capturing,60// but need to guard against cases like gep(p, -ptrtoint(p2)) == null,61// which are equivalent to p == p2 and would capture the pointer.62//63// A dereferenceable pointer is a case where this is known to be safe,64// because the pointer resulting from such a construction would not be65// dereferenceable.66//67// It is not sufficient to check for inbounds GEP here, because GEP with68// zero offset is always inbounds.69bool CanBeNull, CanBeFreed;70return O->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);71}7273namespace {74struct SimpleCaptureTracker : public CaptureTracker {75explicit SimpleCaptureTracker(bool ReturnCaptures)76: ReturnCaptures(ReturnCaptures) {}7778void tooManyUses() override {79LLVM_DEBUG(dbgs() << "Captured due to too many uses\n");80Captured = true;81}8283bool captured(const Use *U) override {84if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)85return false;8687LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n");8889Captured = true;90return true;91}9293bool ReturnCaptures;9495bool Captured = false;96};9798/// Only find pointer captures which happen before the given instruction. Uses99/// the dominator tree to determine whether one instruction is before another.100/// Only support the case where the Value is defined in the same basic block101/// as the given instruction and the use.102struct CapturesBefore : public CaptureTracker {103104CapturesBefore(bool ReturnCaptures, const Instruction *I,105const DominatorTree *DT, bool IncludeI, const LoopInfo *LI)106: BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures),107IncludeI(IncludeI), LI(LI) {}108109void tooManyUses() override { Captured = true; }110111bool isSafeToPrune(Instruction *I) {112if (BeforeHere == I)113return !IncludeI;114115// We explore this usage only if the usage can reach "BeforeHere".116// If use is not reachable from entry, there is no need to explore.117if (!DT->isReachableFromEntry(I->getParent()))118return true;119120// Check whether there is a path from I to BeforeHere.121return !isPotentiallyReachable(I, BeforeHere, nullptr, DT, LI);122}123124bool captured(const Use *U) override {125Instruction *I = cast<Instruction>(U->getUser());126if (isa<ReturnInst>(I) && !ReturnCaptures)127return false;128129// Check isSafeToPrune() here rather than in shouldExplore() to avoid130// an expensive reachability query for every instruction we look at.131// Instead we only do one for actual capturing candidates.132if (isSafeToPrune(I))133return false;134135Captured = true;136return true;137}138139const Instruction *BeforeHere;140const DominatorTree *DT;141142bool ReturnCaptures;143bool IncludeI;144145bool Captured = false;146147const LoopInfo *LI;148};149150/// Find the 'earliest' instruction before which the pointer is known not to151/// be captured. Here an instruction A is considered earlier than instruction152/// B, if A dominates B. If 2 escapes do not dominate each other, the153/// terminator of the common dominator is chosen. If not all uses cannot be154/// analyzed, the earliest escape is set to the first instruction in the155/// function entry block.156// NOTE: Users have to make sure instructions compared against the earliest157// escape are not in a cycle.158struct EarliestCaptures : public CaptureTracker {159160EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT)161: DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}162163void tooManyUses() override {164Captured = true;165EarliestCapture = &*F.getEntryBlock().begin();166}167168bool captured(const Use *U) override {169Instruction *I = cast<Instruction>(U->getUser());170if (isa<ReturnInst>(I) && !ReturnCaptures)171return false;172173if (!EarliestCapture)174EarliestCapture = I;175else176EarliestCapture = DT.findNearestCommonDominator(EarliestCapture, I);177Captured = true;178179// Return false to continue analysis; we need to see all potential180// captures.181return false;182}183184Instruction *EarliestCapture = nullptr;185186const DominatorTree &DT;187188bool ReturnCaptures;189190bool Captured = false;191192Function &F;193};194} // namespace195196/// PointerMayBeCaptured - Return true if this pointer value may be captured197/// by the enclosing function (which is required to exist). This routine can198/// be expensive, so consider caching the results. The boolean ReturnCaptures199/// specifies whether returning the value (or part of it) from the function200/// counts as capturing it or not. The boolean StoreCaptures specified whether201/// storing the value (or part of it) into memory anywhere automatically202/// counts as capturing it or not.203bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,204bool StoreCaptures, unsigned MaxUsesToExplore) {205assert(!isa<GlobalValue>(V) &&206"It doesn't make sense to ask whether a global is captured.");207208// TODO: If StoreCaptures is not true, we could do Fancy analysis209// to determine whether this store is not actually an escape point.210// In that case, BasicAliasAnalysis should be updated as well to211// take advantage of this.212(void)StoreCaptures;213214LLVM_DEBUG(dbgs() << "Captured?: " << *V << " = ");215216SimpleCaptureTracker SCT(ReturnCaptures);217PointerMayBeCaptured(V, &SCT, MaxUsesToExplore);218if (SCT.Captured)219++NumCaptured;220else {221++NumNotCaptured;222LLVM_DEBUG(dbgs() << "not captured\n");223}224return SCT.Captured;225}226227/// PointerMayBeCapturedBefore - Return true if this pointer value may be228/// captured by the enclosing function (which is required to exist). If a229/// DominatorTree is provided, only captures which happen before the given230/// instruction are considered. This routine can be expensive, so consider231/// caching the results. The boolean ReturnCaptures specifies whether232/// returning the value (or part of it) from the function counts as capturing233/// it or not. The boolean StoreCaptures specified whether storing the value234/// (or part of it) into memory anywhere automatically counts as capturing it235/// or not.236bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,237bool StoreCaptures, const Instruction *I,238const DominatorTree *DT, bool IncludeI,239unsigned MaxUsesToExplore,240const LoopInfo *LI) {241assert(!isa<GlobalValue>(V) &&242"It doesn't make sense to ask whether a global is captured.");243244if (!DT)245return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures,246MaxUsesToExplore);247248// TODO: See comment in PointerMayBeCaptured regarding what could be done249// with StoreCaptures.250251CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, LI);252PointerMayBeCaptured(V, &CB, MaxUsesToExplore);253if (CB.Captured)254++NumCapturedBefore;255else256++NumNotCapturedBefore;257return CB.Captured;258}259260Instruction *llvm::FindEarliestCapture(const Value *V, Function &F,261bool ReturnCaptures, bool StoreCaptures,262const DominatorTree &DT,263unsigned MaxUsesToExplore) {264assert(!isa<GlobalValue>(V) &&265"It doesn't make sense to ask whether a global is captured.");266267EarliestCaptures CB(ReturnCaptures, F, DT);268PointerMayBeCaptured(V, &CB, MaxUsesToExplore);269if (CB.Captured)270++NumCapturedBefore;271else272++NumNotCapturedBefore;273return CB.EarliestCapture;274}275276UseCaptureKind llvm::DetermineUseCaptureKind(277const Use &U,278function_ref<bool(Value *, const DataLayout &)> IsDereferenceableOrNull) {279Instruction *I = dyn_cast<Instruction>(U.getUser());280281// TODO: Investigate non-instruction uses.282if (!I)283return UseCaptureKind::MAY_CAPTURE;284285switch (I->getOpcode()) {286case Instruction::Call:287case Instruction::Invoke: {288auto *Call = cast<CallBase>(I);289// Not captured if the callee is readonly, doesn't return a copy through290// its return value and doesn't unwind (a readonly function can leak bits291// by throwing an exception or not depending on the input value).292if (Call->onlyReadsMemory() && Call->doesNotThrow() &&293Call->getType()->isVoidTy())294return UseCaptureKind::NO_CAPTURE;295296// The pointer is not captured if returned pointer is not captured.297// NOTE: CaptureTracking users should not assume that only functions298// marked with nocapture do not capture. This means that places like299// getUnderlyingObject in ValueTracking or DecomposeGEPExpression300// in BasicAA also need to know about this property.301if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(Call, true))302return UseCaptureKind::PASSTHROUGH;303304// Volatile operations effectively capture the memory location that they305// load and store to.306if (auto *MI = dyn_cast<MemIntrinsic>(Call))307if (MI->isVolatile())308return UseCaptureKind::MAY_CAPTURE;309310// Calling a function pointer does not in itself cause the pointer to311// be captured. This is a subtle point considering that (for example)312// the callee might return its own address. It is analogous to saying313// that loading a value from a pointer does not cause the pointer to be314// captured, even though the loaded value might be the pointer itself315// (think of self-referential objects).316if (Call->isCallee(&U))317return UseCaptureKind::NO_CAPTURE;318319// Not captured if only passed via 'nocapture' arguments.320if (Call->isDataOperand(&U) &&321!Call->doesNotCapture(Call->getDataOperandNo(&U))) {322// The parameter is not marked 'nocapture' - captured.323return UseCaptureKind::MAY_CAPTURE;324}325return UseCaptureKind::NO_CAPTURE;326}327case Instruction::Load:328// Volatile loads make the address observable.329if (cast<LoadInst>(I)->isVolatile())330return UseCaptureKind::MAY_CAPTURE;331return UseCaptureKind::NO_CAPTURE;332case Instruction::VAArg:333// "va-arg" from a pointer does not cause it to be captured.334return UseCaptureKind::NO_CAPTURE;335case Instruction::Store:336// Stored the pointer - conservatively assume it may be captured.337// Volatile stores make the address observable.338if (U.getOperandNo() == 0 || cast<StoreInst>(I)->isVolatile())339return UseCaptureKind::MAY_CAPTURE;340return UseCaptureKind::NO_CAPTURE;341case Instruction::AtomicRMW: {342// atomicrmw conceptually includes both a load and store from343// the same location.344// As with a store, the location being accessed is not captured,345// but the value being stored is.346// Volatile stores make the address observable.347auto *ARMWI = cast<AtomicRMWInst>(I);348if (U.getOperandNo() == 1 || ARMWI->isVolatile())349return UseCaptureKind::MAY_CAPTURE;350return UseCaptureKind::NO_CAPTURE;351}352case Instruction::AtomicCmpXchg: {353// cmpxchg conceptually includes both a load and store from354// the same location.355// As with a store, the location being accessed is not captured,356// but the value being stored is.357// Volatile stores make the address observable.358auto *ACXI = cast<AtomicCmpXchgInst>(I);359if (U.getOperandNo() == 1 || U.getOperandNo() == 2 || ACXI->isVolatile())360return UseCaptureKind::MAY_CAPTURE;361return UseCaptureKind::NO_CAPTURE;362}363case Instruction::GetElementPtr:364// AA does not support pointers of vectors, so GEP vector splats need to365// be considered as captures.366if (I->getType()->isVectorTy())367return UseCaptureKind::MAY_CAPTURE;368return UseCaptureKind::PASSTHROUGH;369case Instruction::BitCast:370case Instruction::PHI:371case Instruction::Select:372case Instruction::AddrSpaceCast:373// The original value is not captured via this if the new value isn't.374return UseCaptureKind::PASSTHROUGH;375case Instruction::ICmp: {376unsigned Idx = U.getOperandNo();377unsigned OtherIdx = 1 - Idx;378if (auto *CPN = dyn_cast<ConstantPointerNull>(I->getOperand(OtherIdx))) {379// Don't count comparisons of a no-alias return value against null as380// captures. This allows us to ignore comparisons of malloc results381// with null, for example.382if (CPN->getType()->getAddressSpace() == 0)383if (isNoAliasCall(U.get()->stripPointerCasts()))384return UseCaptureKind::NO_CAPTURE;385if (!I->getFunction()->nullPointerIsDefined()) {386auto *O = I->getOperand(Idx)->stripPointerCastsSameRepresentation();387// Comparing a dereferenceable_or_null pointer against null cannot388// lead to pointer escapes, because if it is not null it must be a389// valid (in-bounds) pointer.390const DataLayout &DL = I->getDataLayout();391if (IsDereferenceableOrNull && IsDereferenceableOrNull(O, DL))392return UseCaptureKind::NO_CAPTURE;393}394}395396// Otherwise, be conservative. There are crazy ways to capture pointers397// using comparisons.398return UseCaptureKind::MAY_CAPTURE;399}400default:401// Something else - be conservative and say it is captured.402return UseCaptureKind::MAY_CAPTURE;403}404}405406void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,407unsigned MaxUsesToExplore) {408assert(V->getType()->isPointerTy() && "Capture is for pointers only!");409if (MaxUsesToExplore == 0)410MaxUsesToExplore = DefaultMaxUsesToExplore;411412SmallVector<const Use *, 20> Worklist;413Worklist.reserve(getDefaultMaxUsesToExploreForCaptureTracking());414SmallSet<const Use *, 20> Visited;415416auto AddUses = [&](const Value *V) {417for (const Use &U : V->uses()) {418// If there are lots of uses, conservatively say that the value419// is captured to avoid taking too much compile time.420if (Visited.size() >= MaxUsesToExplore) {421Tracker->tooManyUses();422return false;423}424if (!Visited.insert(&U).second)425continue;426if (!Tracker->shouldExplore(&U))427continue;428Worklist.push_back(&U);429}430return true;431};432if (!AddUses(V))433return;434435auto IsDereferenceableOrNull = [Tracker](Value *V, const DataLayout &DL) {436return Tracker->isDereferenceableOrNull(V, DL);437};438while (!Worklist.empty()) {439const Use *U = Worklist.pop_back_val();440switch (DetermineUseCaptureKind(*U, IsDereferenceableOrNull)) {441case UseCaptureKind::NO_CAPTURE:442continue;443case UseCaptureKind::MAY_CAPTURE:444if (Tracker->captured(U))445return;446continue;447case UseCaptureKind::PASSTHROUGH:448if (!AddUses(U->getUser()))449return;450continue;451}452}453454// All uses examined.455}456457bool llvm::isNonEscapingLocalObject(458const Value *V, SmallDenseMap<const Value *, bool, 8> *IsCapturedCache) {459SmallDenseMap<const Value *, bool, 8>::iterator CacheIt;460if (IsCapturedCache) {461bool Inserted;462std::tie(CacheIt, Inserted) = IsCapturedCache->insert({V, false});463if (!Inserted)464// Found cached result, return it!465return CacheIt->second;466}467468// If this is an identified function-local object, check to see if it escapes.469if (isIdentifiedFunctionLocal(V)) {470// Set StoreCaptures to True so that we can assume in our callers that the471// pointer is not the result of a load instruction. Currently472// PointerMayBeCaptured doesn't have any special analysis for the473// StoreCaptures=false case; if it did, our callers could be refined to be474// more precise.475auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);476if (IsCapturedCache)477CacheIt->second = Ret;478return Ret;479}480481return false;482}483484485