/// TODO: Refactor this code so the decision on whether or not to accept an /// instruction. bool swift::getFinalReleasesForValue(SILValue V, ReleaseTracker &Tracker) { llvm::SmallPtrSet<SILBasicBlock *, 16> LiveIn; llvm::SmallPtrSet<SILBasicBlock *, 16> UseBlocks; // First attempt to get the BB where this value resides. auto *DefBB = V->getParentBB(); if (!DefBB) return false; bool seenRelease = false; SILInstruction *OneRelease = nullptr; // We'll treat this like a liveness problem where the value is the def. Each // block that has a use of the value has the value live-in unless it is the // block with the value. for (auto *UI : V->getUses()) { auto *User = UI->getUser(); auto *BB = User->getParent(); if (!Tracker.isUserAcceptable(User)) return false; Tracker.trackUser(User); if (BB != DefBB) LiveIn.insert(BB); // Also keep track of the blocks with uses. UseBlocks.insert(BB); // Try to speed up the trivial case of single release/dealloc. if (isa<StrongReleaseInst>(User) || isa<DeallocBoxInst>(User)) { if (!seenRelease) OneRelease = User; else OneRelease = nullptr; seenRelease = true; } } // Only a single release/dealloc? We're done! if (OneRelease) { Tracker.trackLastRelease(OneRelease); return true; } propagateLiveness(LiveIn, DefBB); // Now examine each block we saw a use in. If it has no successors // that are in LiveIn, then the last use in the block is the final // release/dealloc. for (auto *BB : UseBlocks) if (!successorHasLiveIn(BB, LiveIn)) if (!addLastUse(V, BB, Tracker)) return false; return true; }
// Walk backwards in BB looking for the last use of a given // value, and add it to the set of release points. static bool addLastUse(SILValue V, SILBasicBlock *BB, ReleaseTracker &Tracker) { for (auto I = BB->rbegin(); I != BB->rend(); ++I) { if (Tracker.isUser(&*I)) { Tracker.trackLastRelease(&*I); return true; } } llvm_unreachable("BB is expected to have a use of a closure"); return false; }
// Walk backwards in BB looking for the last use of a given // value, and add it to the set of release points. static bool addLastUse(SILValue V, SILBasicBlock *BB, ReleaseTracker &Tracker) { for (auto I = BB->rbegin(); I != BB->rend(); ++I) { for (auto &Op : I->getAllOperands()) if (Op.get() == V) { Tracker.trackLastRelease(&*I); return true; } } llvm_unreachable("BB is expected to have a use of a closure"); return false; }