//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains routines that help determine which pointers are captured. // A pointer value is captured if the function makes a copy of any part of the // pointer that outlives the call. Not being captured means, more or less, that // the pointer is only dereferenced and not stored in a global. Returning part // of the pointer as the function return value may or may not count as capturing // the pointer, depending on the context. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/CaptureTracking.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumCaptured, "Number of pointers maybe captured"); STATISTIC(NumNotCaptured, "Number of pointers not captured"); STATISTIC(NumCapturedBefore, "Number of pointers maybe captured before"); STATISTIC(NumNotCapturedBefore, "Number of pointers not captured before"); /// The default value for MaxUsesToExplore argument. It's relatively small to /// keep the cost of analysis reasonable for clients like BasicAliasAnalysis, /// where the results can't be cached. /// TODO: we should probably introduce a caching CaptureTracking analysis and /// use it where possible. The caching version can use much higher limit or /// don't have this cap at all. static cl::opt<unsigned> DefaultMaxUsesToExplore("capture-tracking-max-uses-to-explore", cl::Hidden, cl::desc("Maximal number of uses to explore."), cl::init(100)); unsigned llvm::getDefaultMaxUsesToExploreForCaptureTracking() { … } CaptureTracker::~CaptureTracker() = default; bool CaptureTracker::shouldExplore(const Use *U) { … } bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) { … } namespace { struct SimpleCaptureTracker : public CaptureTracker { … }; /// Only find pointer captures which happen before the given instruction. Uses /// the dominator tree to determine whether one instruction is before another. /// Only support the case where the Value is defined in the same basic block /// as the given instruction and the use. struct CapturesBefore : public CaptureTracker { … }; /// Find the 'earliest' instruction before which the pointer is known not to /// be captured. Here an instruction A is considered earlier than instruction /// B, if A dominates B. If 2 escapes do not dominate each other, the /// terminator of the common dominator is chosen. If not all uses cannot be /// analyzed, the earliest escape is set to the first instruction in the /// function entry block. // NOTE: Users have to make sure instructions compared against the earliest // escape are not in a cycle. struct EarliestCaptures : public CaptureTracker { … }; } // namespace /// PointerMayBeCaptured - Return true if this pointer value may be captured /// by the enclosing function (which is required to exist). This routine can /// be expensive, so consider caching the results. The boolean ReturnCaptures /// specifies whether returning the value (or part of it) from the function /// counts as capturing it or not. The boolean StoreCaptures specified whether /// storing the value (or part of it) into memory anywhere automatically /// counts as capturing it or not. bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore) { … } /// PointerMayBeCapturedBefore - Return true if this pointer value may be /// captured by the enclosing function (which is required to exist). If a /// DominatorTree is provided, only captures which happen before the given /// instruction are considered. This routine can be expensive, so consider /// caching the results. The boolean ReturnCaptures specifies whether /// returning the value (or part of it) from the function counts as capturing /// it or not. The boolean StoreCaptures specified whether storing the value /// (or part of it) into memory anywhere automatically counts as capturing it /// or not. bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI, unsigned MaxUsesToExplore, const LoopInfo *LI) { … } Instruction *llvm::FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures, bool StoreCaptures, const DominatorTree &DT, unsigned MaxUsesToExplore) { … } UseCaptureKind llvm::DetermineUseCaptureKind( const Use &U, function_ref<bool(Value *, const DataLayout &)> IsDereferenceableOrNull) { … } void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, unsigned MaxUsesToExplore) { … } bool llvm::isNonEscapingLocalObject( const Value *V, SmallDenseMap<const Value *, bool, 8> *IsCapturedCache) { … }