diff options
author | Florian Hahn <flo@fhahn.com> | 2021-09-24 15:41:47 +0100 |
---|---|---|
committer | Florian Hahn <flo@fhahn.com> | 2021-09-24 17:13:27 +0100 |
commit | 6f28fb708149e9db8d077e65fcc9f87d566e824a (patch) | |
tree | 4c5d5697069ba9458f03a169727fa173cc6fec28 /llvm/lib/Analysis/CaptureTracking.cpp | |
parent | e2546525902de18bb66a0c46ad3517d9f389fa47 (diff) | |
download | llvm-6f28fb708149e9db8d077e65fcc9f87d566e824a.zip llvm-6f28fb708149e9db8d077e65fcc9f87d566e824a.tar.gz llvm-6f28fb708149e9db8d077e65fcc9f87d566e824a.tar.bz2 |
Recommit "[DSE] Track earliest escape, use for loads in isReadClobber."
This reverts the revert commit df56fc6ebbee6c458b0473185277b7860f7e3408.
This version of the patch adjusts the location where the EarliestEscapes
cache is cleared when an instruction gets removed. The earliest escaping
instruction does not have to be a memory instruction.
It could be a ptrtoint instruction like in the added test
@earliest_escape_ptrtoint, which subsequently gets removed. We need to
invalidate the EarliestEscape entry referring to the ptrtoint when
deleting it.
This fixes the crash mentioned in
https://bugs.chromium.org/p/chromium/issues/detail?id=1252762#c6
Diffstat (limited to 'llvm/lib/Analysis/CaptureTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/CaptureTracking.cpp | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp index 49fc65f6..8955658 100644 --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -143,6 +143,66 @@ namespace { const LoopInfo *LI; }; + + /// 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 { + + EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT) + : DT(DT), ReturnCaptures(ReturnCaptures), Captured(false), F(F) {} + + void tooManyUses() override { + Captured = true; + EarliestCapture = &*F.getEntryBlock().begin(); + } + + bool captured(const Use *U) override { + Instruction *I = cast<Instruction>(U->getUser()); + if (isa<ReturnInst>(I) && !ReturnCaptures) + return false; + + if (!EarliestCapture) { + EarliestCapture = I; + } else if (EarliestCapture->getParent() == I->getParent()) { + if (I->comesBefore(EarliestCapture)) + EarliestCapture = I; + } else { + BasicBlock *CurrentBB = I->getParent(); + BasicBlock *EarliestBB = EarliestCapture->getParent(); + if (DT.dominates(EarliestBB, CurrentBB)) { + // EarliestCapture already comes before the current use. + } else if (DT.dominates(CurrentBB, EarliestBB)) { + EarliestCapture = I; + } else { + // Otherwise find the nearest common dominator and use its terminator. + auto *NearestCommonDom = + DT.findNearestCommonDominator(CurrentBB, EarliestBB); + EarliestCapture = NearestCommonDom->getTerminator(); + } + } + Captured = true; + + // Return false to continue analysis; we need to see all potential + // captures. + return false; + } + + Instruction *EarliestCapture = nullptr; + + const DominatorTree &DT; + + bool ReturnCaptures; + + bool Captured; + + Function &F; + }; } /// PointerMayBeCaptured - Return true if this pointer value may be captured @@ -206,6 +266,22 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, return CB.Captured; } +Instruction *llvm::FindEarliestCapture(const Value *V, Function &F, + bool ReturnCaptures, bool StoreCaptures, + const DominatorTree &DT, + unsigned MaxUsesToExplore) { + assert(!isa<GlobalValue>(V) && + "It doesn't make sense to ask whether a global is captured."); + + EarliestCaptures CB(ReturnCaptures, F, DT); + PointerMayBeCaptured(V, &CB, MaxUsesToExplore); + if (CB.Captured) + ++NumCapturedBefore; + else + ++NumNotCapturedBefore; + return CB.EarliestCapture; +} + void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, unsigned MaxUsesToExplore) { assert(V->getType()->isPointerTy() && "Capture is for pointers only!"); |