aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/CaptureTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/CaptureTracking.cpp')
-rw-r--r--llvm/lib/Analysis/CaptureTracking.cpp80
1 files changed, 14 insertions, 66 deletions
diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp
index b2fc6e603f9e..5fe4f9befc86 100644
--- a/llvm/lib/Analysis/CaptureTracking.cpp
+++ b/llvm/lib/Analysis/CaptureTracking.cpp
@@ -68,8 +68,8 @@ bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {
if (auto *GEP = dyn_cast<GetElementPtrInst>(O))
if (GEP->isInBounds())
return true;
- bool CanBeNull;
- return O->getPointerDereferenceableBytes(DL, CanBeNull);
+ bool CanBeNull, CanBeFreed;
+ return O->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
}
namespace {
@@ -106,67 +106,29 @@ namespace {
void tooManyUses() override { Captured = true; }
bool isSafeToPrune(Instruction *I) {
- BasicBlock *BB = I->getParent();
+ if (BeforeHere == I)
+ return !IncludeI;
+
// We explore this usage only if the usage can reach "BeforeHere".
// If use is not reachable from entry, there is no need to explore.
- if (BeforeHere != I && !DT->isReachableFromEntry(BB))
+ if (!DT->isReachableFromEntry(I->getParent()))
return true;
- // Compute the case where both instructions are inside the same basic
- // block.
- if (BB == BeforeHere->getParent()) {
- // 'I' dominates 'BeforeHere' => not safe to prune.
- //
- // The value defined by an invoke dominates an instruction only
- // if it dominates every instruction in UseBB. A PHI is dominated only
- // if the instruction dominates every possible use in the UseBB. Since
- // UseBB == BB, avoid pruning.
- if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I == BeforeHere)
- return false;
- if (!BeforeHere->comesBefore(I))
- return false;
-
- // 'BeforeHere' comes before 'I', it's safe to prune if we also
- // guarantee that 'I' never reaches 'BeforeHere' through a back-edge or
- // by its successors, i.e, prune if:
- //
- // (1) BB is an entry block or have no successors.
- // (2) There's no path coming back through BB successors.
- if (BB == &BB->getParent()->getEntryBlock() ||
- !BB->getTerminator()->getNumSuccessors())
- return true;
-
- SmallVector<BasicBlock*, 32> Worklist;
- Worklist.append(succ_begin(BB), succ_end(BB));
- return !isPotentiallyReachableFromMany(Worklist, BB, nullptr, DT);
- }
-
- // If the value is defined in the same basic block as use and BeforeHere,
- // there is no need to explore the use if BeforeHere dominates use.
// Check whether there is a path from I to BeforeHere.
- if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
- !isPotentiallyReachable(I, BeforeHere, nullptr, DT))
- return true;
-
- return false;
+ return !isPotentiallyReachable(I, BeforeHere, nullptr, DT);
}
- bool shouldExplore(const Use *U) override {
+ bool captured(const Use *U) override {
Instruction *I = cast<Instruction>(U->getUser());
-
- if (BeforeHere == I && !IncludeI)
+ if (isa<ReturnInst>(I) && !ReturnCaptures)
return false;
+ // Check isSafeToPrune() here rather than in shouldExplore() to avoid
+ // an expensive reachability query for every instruction we look at.
+ // Instead we only do one for actual capturing candidates.
if (isSafeToPrune(I))
return false;
- return true;
- }
-
- bool captured(const Use *U) override {
- if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)
- return false;
-
Captured = true;
return true;
}
@@ -423,8 +385,8 @@ bool llvm::isNonEscapingLocalObject(
return CacheIt->second;
}
- // If this is a local allocation, check to see if it escapes.
- if (isa<AllocaInst>(V) || isNoAliasCall(V)) {
+ // If this is an identified function-local object, check to see if it escapes.
+ if (isIdentifiedFunctionLocal(V)) {
// Set StoreCaptures to True so that we can assume in our callers that the
// pointer is not the result of a load instruction. Currently
// PointerMayBeCaptured doesn't have any special analysis for the
@@ -436,19 +398,5 @@ bool llvm::isNonEscapingLocalObject(
return Ret;
}
- // If this is an argument that corresponds to a byval or noalias argument,
- // then it has not escaped before entering the function. Check if it escapes
- // inside the function.
- if (const Argument *A = dyn_cast<Argument>(V))
- if (A->hasByValAttr() || A->hasNoAliasAttr()) {
- // Note even if the argument is marked nocapture, we still need to check
- // for copies made inside the function. The nocapture attribute only
- // specifies that there are no copies made that outlive the function.
- auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
- if (IsCapturedCache)
- CacheIt->second = Ret;
- return Ret;
- }
-
return false;
}