33#define DEBUG_TYPE "capture-tracking"
35STATISTIC(NumCaptured,
"Number of pointers maybe captured");
36STATISTIC(NumNotCaptured,
"Number of pointers not captured");
37STATISTIC(NumCapturedBefore,
"Number of pointers maybe captured before");
38STATISTIC(NumNotCapturedBefore,
"Number of pointers not captured before");
48 cl::desc(
"Maximal number of uses to explore."),
70 bool CanBeNull, CanBeFreed;
71 return O->getPointerDereferenceableBytes(
DL, CanBeNull, CanBeFreed);
76 explicit SimpleCaptureTracker(
bool ReturnCaptures)
77 : ReturnCaptures(ReturnCaptures) {}
79 void tooManyUses()
override {
84 bool captured(
const Use *U)
override {
85 if (isa<ReturnInst>(
U->getUser()) && !ReturnCaptures)
96 bool Captured =
false;
105 CapturesBefore(
bool ReturnCaptures,
const Instruction *
I,
107 : BeforeHere(
I), DT(DT), ReturnCaptures(ReturnCaptures),
108 IncludeI(IncludeI), LI(LI) {}
110 void tooManyUses()
override { Captured =
true; }
118 if (!DT->isReachableFromEntry(
I->getParent()))
125 bool captured(
const Use *U)
override {
127 if (isa<ReturnInst>(
I) && !ReturnCaptures)
133 if (isSafeToPrune(
I))
146 bool Captured =
false;
162 : DT(DT), ReturnCaptures(ReturnCaptures),
F(
F) {}
164 void tooManyUses()
override {
166 EarliestCapture = &*
F.getEntryBlock().begin();
169 bool captured(
const Use *U)
override {
171 if (isa<ReturnInst>(
I) && !ReturnCaptures)
174 if (!EarliestCapture)
177 EarliestCapture = DT.findNearestCommonDominator(EarliestCapture,
I);
191 bool Captured =
false;
205 bool StoreCaptures,
unsigned MaxUsesToExplore) {
206 assert(!isa<GlobalValue>(V) &&
207 "It doesn't make sense to ask whether a global is captured.");
217 SimpleCaptureTracker SCT(ReturnCaptures);
240 unsigned MaxUsesToExplore,
242 assert(!isa<GlobalValue>(V) &&
243 "It doesn't make sense to ask whether a global is captured.");
252 CapturesBefore CB(ReturnCaptures,
I, DT, IncludeI, LI);
257 ++NumNotCapturedBefore;
262 bool ReturnCaptures,
bool StoreCaptures,
264 unsigned MaxUsesToExplore) {
265 assert(!isa<GlobalValue>(V) &&
266 "It doesn't make sense to ask whether a global is captured.");
268 EarliestCaptures CB(ReturnCaptures,
F, DT);
273 ++NumNotCapturedBefore;
274 return CB.EarliestCapture;
286 switch (
I->getOpcode()) {
287 case Instruction::Call:
288 case Instruction::Invoke: {
289 auto *Call = cast<CallBase>(
I);
293 if (Call->onlyReadsMemory() && Call->doesNotThrow() &&
294 Call->getType()->isVoidTy())
307 if (
auto *
MI = dyn_cast<MemIntrinsic>(Call))
308 if (
MI->isVolatile())
317 if (Call->isCallee(&U))
321 if (Call->isDataOperand(&U) &&
322 !Call->doesNotCapture(Call->getDataOperandNo(&U))) {
328 case Instruction::Load:
330 if (cast<LoadInst>(
I)->isVolatile())
333 case Instruction::VAArg:
336 case Instruction::Store:
339 if (U.getOperandNo() == 0 || cast<StoreInst>(
I)->isVolatile())
342 case Instruction::AtomicRMW: {
348 auto *ARMWI = cast<AtomicRMWInst>(
I);
349 if (U.getOperandNo() == 1 || ARMWI->isVolatile())
353 case Instruction::AtomicCmpXchg: {
359 auto *ACXI = cast<AtomicCmpXchgInst>(
I);
360 if (U.getOperandNo() == 1 || U.getOperandNo() == 2 || ACXI->isVolatile())
364 case Instruction::GetElementPtr:
367 if (
I->getType()->isVectorTy())
370 case Instruction::BitCast:
371 case Instruction::PHI:
372 case Instruction::Select:
373 case Instruction::AddrSpaceCast:
376 case Instruction::ICmp: {
377 unsigned Idx = U.getOperandNo();
378 unsigned OtherIdx = 1 -
Idx;
379 if (
auto *CPN = dyn_cast<ConstantPointerNull>(
I->getOperand(OtherIdx))) {
383 if (CPN->getType()->getAddressSpace() == 0)
386 if (!
I->getFunction()->nullPointerIsDefined()) {
387 auto *O =
I->getOperand(
Idx)->stripPointerCastsSameRepresentation();
392 if (IsDereferenceableOrNull && IsDereferenceableOrNull(O,
DL))
408 unsigned MaxUsesToExplore) {
409 assert(V->getType()->isPointerTy() &&
"Capture is for pointers only!");
410 if (MaxUsesToExplore == 0)
417 auto AddUses = [&](
const Value *V) {
418 for (
const Use &U : V->uses()) {
421 if (Visited.
size() >= MaxUsesToExplore) {
425 if (!Visited.
insert(&U).second)
439 while (!Worklist.
empty()) {
449 if (!AddUses(U->getUser()))
461 if (IsCapturedCache) {
463 std::tie(CacheIt, Inserted) = IsCapturedCache->
insert({V,
false});
466 return CacheIt->second;
478 CacheIt->second = Ret;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< unsigned > DefaultMaxUsesToExplore("capture-tracking-max-uses-to-explore", cl::Hidden, cl::desc("Maximal number of uses to explore."), cl::init(100))
The default value for MaxUsesToExplore argument.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
UseCaptureKind DetermineUseCaptureKind(const Use &U, llvm::function_ref< bool(Value *, const DataLayout &)> IsDereferenceableOrNull)
Determine what kind of capture behaviour U may exhibit.
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI=false, unsigned MaxUsesToExplore=0, const LoopInfo *LI=nullptr)
PointerMayBeCapturedBefore - Return true if this pointer value may be captured by the enclosing funct...
bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
bool isNonEscapingLocalObject(const Value *V, SmallDenseMap< const Value *, bool, 8 > *IsCapturedCache=nullptr)
Returns true if the pointer is to a function-local object that never escapes from the function.
unsigned getDefaultMaxUsesToExploreForCaptureTracking()
getDefaultMaxUsesToExploreForCaptureTracking - Return default value of the maximal number of uses to ...
bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveNullness)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Instruction * FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures, bool StoreCaptures, const DominatorTree &DT, unsigned MaxUsesToExplore=0)
bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
UseCaptureKind
Types of use capture kinds, see DetermineUseCaptureKind.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
This callback is used in conjunction with PointerMayBeCaptured.
virtual bool shouldExplore(const Use *U)
shouldExplore - This is the use of a value derived from the pointer.
virtual bool isDereferenceableOrNull(Value *O, const DataLayout &DL)
isDereferenceableOrNull - Overload to allow clients with additional knowledge about pointer dereferen...
virtual void tooManyUses()=0
tooManyUses - The depth of traversal has breached a limit.
virtual ~CaptureTracker()
virtual bool captured(const Use *U)=0
captured - Information about the pointer was captured by the user of use U.