[CopyPropagation] Add ShrinkBorrowScope.

During copy propagation (for which -enable-copy-propagation must still
be passed), also try to shrink borrow scopes by hoisting end_borrows
using the newly added ShrinkBorrowScope utility.

Allow end_borrow instructions to be hoisted over instructions that are
not deinit barriers for the value which is borrowed.  Deinit barriers
include uses of the value, loads of memory, loads of weak references
that may be zeroed during deinit, and "synchronization points".

rdar://79149830
This commit is contained in:
Nate Chandler
2021-11-15 08:14:59 -08:00
parent c8f0dd2733
commit cde250a3e3
11 changed files with 934 additions and 11 deletions

View File

@@ -75,6 +75,9 @@ struct CanonicalDefWorklist {
CanonicalDefWorklist(bool canonicalizeBorrows)
: canonicalizeBorrows(canonicalizeBorrows) {}
// Update the worklist for the def corresponding to \p bbi, a BeginBorrow.
void updateForBorrow(BeginBorrowInst *bbi) { borrowedValues.insert(bbi); }
// Update the worklist for the def corresponding to \p copy, which is usually
// a CopyValue, but may be any owned value such as the operand of a
// DestroyValue (to force lifetime shortening).
@@ -414,11 +417,15 @@ void CopyPropagation::run() {
InstructionDeleter deleter(std::move(callbacks));
bool changed = false;
// Driver: Find all copied defs.
GraphNodeWorklist<BeginBorrowInst *, 16> beginBorrowsToShrink;
// Driver: Find all copied or borrowed defs.
for (auto &bb : *f) {
for (auto &i : bb) {
if (auto *copy = dyn_cast<CopyValueInst>(&i)) {
defWorklist.updateForCopy(copy);
} else if (auto *borrow = dyn_cast<BeginBorrowInst>(&i)) {
beginBorrowsToShrink.insert(borrow);
} else if (canonicalizeAll) {
if (auto *destroy = dyn_cast<DestroyValueInst>(&i)) {
defWorklist.updateForCopy(destroy->getOperand());
@@ -426,6 +433,14 @@ void CopyPropagation::run() {
}
}
}
// NOTE: We assume that the function is in reverse post order so visiting the
// blocks and pushing begin_borrows as we see them and then popping them
// off the end will result in shrinking inner borrow scopes first.
while (auto *bbi = beginBorrowsToShrink.pop()) {
shrinkBorrowScope(bbi, deleter);
}
// canonicalizer performs all modifications through deleter's callbacks, so we
// don't need to explicitly check for changes.
CanonicalizeOSSALifetime canonicalizer(pruneDebug, poisonRefs,