From 4f8d33ffb551af99d3526feeea90caacbf63880a Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Thu, 27 Oct 2022 13:57:18 -0700 Subject: [PATCH] SILOptimizer: Break circular dependency with SIL library by moving extendStoreBorrow(). --- include/swift/SIL/ScopedAddressUtils.h | 5 -- .../SILOptimizer/Utils/OwnershipOptUtils.h | 6 ++ lib/SIL/Utils/ScopedAddressUtils.cpp | 67 ------------------ lib/SILOptimizer/Utils/OwnershipOptUtils.cpp | 68 +++++++++++++++++++ .../Utils/PartialApplyCombiner.cpp | 1 + 5 files changed, 75 insertions(+), 72 deletions(-) diff --git a/include/swift/SIL/ScopedAddressUtils.h b/include/swift/SIL/ScopedAddressUtils.h index 873ac71c26cfc..cf446484f889d 100644 --- a/include/swift/SIL/ScopedAddressUtils.h +++ b/include/swift/SIL/ScopedAddressUtils.h @@ -137,11 +137,6 @@ bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi, SSAPrunedLiveness *liveness, DeadEndBlocks *deadEndBlocks); -/// Extend the store_borrow \p sbi's scope such that it encloses \p newUsers. -bool extendStoreBorrow(StoreBorrowInst *sbi, - SmallVectorImpl &newUses, - DeadEndBlocks *deadEndBlocks, - InstModCallbacks callbacks = InstModCallbacks()); } // namespace swift #endif diff --git a/include/swift/SILOptimizer/Utils/OwnershipOptUtils.h b/include/swift/SILOptimizer/Utils/OwnershipOptUtils.h index e649f0761da31..bceddf29711bf 100644 --- a/include/swift/SILOptimizer/Utils/OwnershipOptUtils.h +++ b/include/swift/SILOptimizer/Utils/OwnershipOptUtils.h @@ -404,6 +404,12 @@ struct LoadOperation { } }; +/// Extend the store_borrow \p sbi's scope such that it encloses \p newUsers. +bool extendStoreBorrow(StoreBorrowInst *sbi, + SmallVectorImpl &newUses, + DeadEndBlocks *deadEndBlocks, + InstModCallbacks callbacks = InstModCallbacks()); + } // namespace swift #endif diff --git a/lib/SIL/Utils/ScopedAddressUtils.cpp b/lib/SIL/Utils/ScopedAddressUtils.cpp index 05cf06f160908..b56d0a96893ab 100644 --- a/lib/SIL/Utils/ScopedAddressUtils.cpp +++ b/lib/SIL/Utils/ScopedAddressUtils.cpp @@ -182,73 +182,6 @@ bool swift::hasOtherStoreBorrowsInLifetime(StoreBorrowInst *storeBorrow, return false; } -bool swift::extendStoreBorrow(StoreBorrowInst *sbi, - SmallVectorImpl &newUses, - DeadEndBlocks *deadEndBlocks, - InstModCallbacks callbacks) { - ScopedAddressValue scopedAddress(sbi); - - SmallVector discoveredBlocks; - SSAPrunedLiveness storeBorrowLiveness(&discoveredBlocks); - - // FIXME: if OSSA lifetimes are complete, then we don't need transitive - // liveness here. - AddressUseKind useKind = - scopedAddress.computeTransitiveLiveness(storeBorrowLiveness); - - // If all new uses are within store_borrow boundary, no need for extension. - if (storeBorrowLiveness.areUsesWithinBoundary(newUses, deadEndBlocks)) { - return true; - } - - if (useKind != AddressUseKind::NonEscaping) { - return false; - } - - // store_borrow extension is possible only when there are no other - // store_borrows to the same destination within the store_borrow's lifetime - // built from newUsers. - if (hasOtherStoreBorrowsInLifetime(sbi, &storeBorrowLiveness, - deadEndBlocks)) { - return false; - } - - InstModCallbacks tempCallbacks = callbacks; - InstructionDeleter deleter(std::move(tempCallbacks)); - GuaranteedOwnershipExtension borrowExtension(deleter, *deadEndBlocks, - sbi->getFunction()); - auto status = borrowExtension.checkBorrowExtension( - BorrowedValue(sbi->getSrc()), newUses); - if (status == GuaranteedOwnershipExtension::Invalid) { - return false; - } - - borrowExtension.transform(status); - - SmallVector endBorrowUses; - // Collect old scope-ending instructions. - scopedAddress.visitScopeEndingUses([&](Operand *op) { - endBorrowUses.push_back(op); - return true; - }); - - for (auto *use : newUses) { - // Update newUsers as non-lifetime ending. - storeBorrowLiveness.updateForUse(use->getUser(), - /* lifetimeEnding */ false); - } - - // Add new scope-ending instructions. - scopedAddress.endScopeAtLivenessBoundary(&storeBorrowLiveness); - - // Remove old scope-ending instructions. - for (auto *endBorrowUse : endBorrowUses) { - callbacks.deleteInst(endBorrowUse->getUser()); - } - - return true; -} - void ScopedAddressValue::print(llvm::raw_ostream &os) const { os << "ScopedAddressIntroducingValue:\n" "Kind: " diff --git a/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp b/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp index c9f3e997c04ac..1cb1200828462 100644 --- a/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp +++ b/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp @@ -25,6 +25,7 @@ #include "swift/SIL/MemAccessUtils.h" #include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/Projection.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILInstruction.h" @@ -1848,3 +1849,70 @@ bool swift::createBorrowScopeForPhiOperands(SILPhiArgument *newPhi) { } return GuaranteedPhiBorrowFixup().createExtendedNestedBorrowScope(newPhi); } + +bool swift::extendStoreBorrow(StoreBorrowInst *sbi, + SmallVectorImpl &newUses, + DeadEndBlocks *deadEndBlocks, + InstModCallbacks callbacks) { + ScopedAddressValue scopedAddress(sbi); + + SmallVector discoveredBlocks; + SSAPrunedLiveness storeBorrowLiveness(&discoveredBlocks); + + // FIXME: if OSSA lifetimes are complete, then we don't need transitive + // liveness here. + AddressUseKind useKind = + scopedAddress.computeTransitiveLiveness(storeBorrowLiveness); + + // If all new uses are within store_borrow boundary, no need for extension. + if (storeBorrowLiveness.areUsesWithinBoundary(newUses, deadEndBlocks)) { + return true; + } + + if (useKind != AddressUseKind::NonEscaping) { + return false; + } + + // store_borrow extension is possible only when there are no other + // store_borrows to the same destination within the store_borrow's lifetime + // built from newUsers. + if (hasOtherStoreBorrowsInLifetime(sbi, &storeBorrowLiveness, + deadEndBlocks)) { + return false; + } + + InstModCallbacks tempCallbacks = callbacks; + InstructionDeleter deleter(std::move(tempCallbacks)); + GuaranteedOwnershipExtension borrowExtension(deleter, *deadEndBlocks, + sbi->getFunction()); + auto status = borrowExtension.checkBorrowExtension( + BorrowedValue(sbi->getSrc()), newUses); + if (status == GuaranteedOwnershipExtension::Invalid) { + return false; + } + + borrowExtension.transform(status); + + SmallVector endBorrowUses; + // Collect old scope-ending instructions. + scopedAddress.visitScopeEndingUses([&](Operand *op) { + endBorrowUses.push_back(op); + return true; + }); + + for (auto *use : newUses) { + // Update newUsers as non-lifetime ending. + storeBorrowLiveness.updateForUse(use->getUser(), + /* lifetimeEnding */ false); + } + + // Add new scope-ending instructions. + scopedAddress.endScopeAtLivenessBoundary(&storeBorrowLiveness); + + // Remove old scope-ending instructions. + for (auto *endBorrowUse : endBorrowUses) { + callbacks.deleteInst(endBorrowUse->getUser()); + } + + return true; +} diff --git a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp index e73fa14325e75..78918a0f3edc1 100644 --- a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp +++ b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp @@ -13,6 +13,7 @@ #include "swift/SIL/SILValue.h" #include "swift/SIL/ScopedAddressUtils.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h" #include "swift/SILOptimizer/Utils/ValueLifetime.h" using namespace swift;