diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index 59137282471..8b7c7a90f7c 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -40,10 +40,11 @@ namespace llvm { /// 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. + /// or not. Captures by the provided instruction are considered if the + /// final parameter is true. bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, - DominatorTree *DT); + DominatorTree *DT, bool IncludeI = false); /// This callback is used in conjunction with PointerMayBeCaptured. In /// addition to the interface here, you'll need to provide your own getters diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 3f1cf6aa3f8..8b8106b950a 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -408,7 +408,8 @@ AliasAnalysis::callCapturesBefore(const Instruction *I, return AliasAnalysis::ModRef; if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true, - /* StoreCaptures */ true, I, DT)) + /* StoreCaptures */ true, I, DT, + /* include Object */ true)) return AliasAnalysis::ModRef; unsigned ArgNo = 0; diff --git a/lib/Analysis/CaptureTracking.cpp b/lib/Analysis/CaptureTracking.cpp index e13c47a9bde..f2f8877af1a 100644 --- a/lib/Analysis/CaptureTracking.cpp +++ b/lib/Analysis/CaptureTracking.cpp @@ -57,14 +57,18 @@ namespace { /// 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 { - CapturesBefore(bool ReturnCaptures, const Instruction *I, DominatorTree *DT) + CapturesBefore(bool ReturnCaptures, const Instruction *I, DominatorTree *DT, + bool IncludeI) : BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures), - Captured(false) {} + IncludeI(IncludeI), Captured(false) {} void tooManyUses() override { Captured = true; } bool shouldExplore(const Use *U) override { Instruction *I = cast(U->getUser()); + if (BeforeHere == I && !IncludeI) + return false; + BasicBlock *BB = I->getParent(); // We explore this usage only if the usage can reach "BeforeHere". // If use is not reachable from entry, there is no need to explore. @@ -84,6 +88,9 @@ namespace { return false; Instruction *I = cast(U->getUser()); + if (BeforeHere == I && !IncludeI) + return false; + BasicBlock *BB = I->getParent(); // Same logic as in shouldExplore. if (BeforeHere != I && !DT->isReachableFromEntry(BB)) @@ -99,6 +106,7 @@ namespace { DominatorTree *DT; bool ReturnCaptures; + bool IncludeI; bool Captured; }; @@ -138,7 +146,7 @@ bool llvm::PointerMayBeCaptured(const Value *V, /// or not. bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, - DominatorTree *DT) { + DominatorTree *DT, bool IncludeI) { assert(!isa(V) && "It doesn't make sense to ask whether a global is captured."); @@ -148,7 +156,7 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, // TODO: See comment in PointerMayBeCaptured regarding what could be done // with StoreCaptures. - CapturesBefore CB(ReturnCaptures, I, DT); + CapturesBefore CB(ReturnCaptures, I, DT, IncludeI); PointerMayBeCaptured(V, &CB); return CB.Captured; }