|
16 | 16 | #include "swift/SIL/SILArgument.h"
|
17 | 17 | #include "swift/SIL/SILBuilder.h"
|
18 | 18 | #include "swift/SIL/SILInstruction.h"
|
| 19 | +#include "swift/SILOptimizer/Utils/InstructionDeleter.h" |
| 20 | +#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h" |
19 | 21 |
|
20 | 22 | using namespace swift;
|
21 | 23 |
|
@@ -85,12 +87,18 @@ bool ScopedAddressValue::visitScopeEndingUses(
|
85 | 87 | }
|
86 | 88 |
|
87 | 89 | bool ScopedAddressValue::computeLiveness(PrunedLiveness &liveness) const {
|
88 |
| - auto addressKind = findTransitiveUsesForAddress(value); |
| 90 | + SmallVector<Operand *, 4> uses; |
| 91 | + // Collect all uses that need to be enclosed by the scope. |
| 92 | + auto addressKind = findTransitiveUsesForAddress(value, &uses); |
89 | 93 | if (addressKind != AddressUseKind::NonEscaping) {
|
90 | 94 | return false;
|
91 | 95 | }
|
92 | 96 |
|
93 | 97 | liveness.initializeDefBlock(value->getParentBlock());
|
| 98 | + for (auto *use : uses) { |
| 99 | + // Update all collected uses as non-lifetime ending. |
| 100 | + liveness.updateForUse(use->getUser(), /* lifetimeEnding */ false); |
| 101 | + } |
94 | 102 | visitScopeEndingUses([&](Operand *endOp) {
|
95 | 103 | liveness.updateForUse(endOp->getUser(), /* isLifetimeEnding */ true);
|
96 | 104 | return true;
|
@@ -156,6 +164,68 @@ bool swift::hasOtherStoreBorrowsInLifetime(StoreBorrowInst *storeBorrow,
|
156 | 164 | return false;
|
157 | 165 | }
|
158 | 166 |
|
| 167 | +bool swift::extendStoreBorrow(StoreBorrowInst *sbi, |
| 168 | + SmallVectorImpl<Operand *> &newUses, |
| 169 | + DeadEndBlocks *deadEndBlocks, |
| 170 | + InstModCallbacks callbacks) { |
| 171 | + ScopedAddressValue scopedAddress(sbi); |
| 172 | + |
| 173 | + SmallVector<SILBasicBlock *, 4> discoveredBlocks; |
| 174 | + PrunedLiveness storeBorrowLiveness(&discoveredBlocks); |
| 175 | + bool success = scopedAddress.computeLiveness(storeBorrowLiveness); |
| 176 | + |
| 177 | + // If all new uses are within store_borrow boundary, no need for extension. |
| 178 | + if (storeBorrowLiveness.areUsesWithinBoundary(newUses, deadEndBlocks)) { |
| 179 | + return true; |
| 180 | + } |
| 181 | + |
| 182 | + if (!success) { |
| 183 | + return false; |
| 184 | + } |
| 185 | + |
| 186 | + // store_borrow extension is possible only when there are no other |
| 187 | + // store_borrows to the same destination within the store_borrow's lifetime |
| 188 | + // built from newUsers. |
| 189 | + if (hasOtherStoreBorrowsInLifetime(sbi, &storeBorrowLiveness, |
| 190 | + deadEndBlocks)) { |
| 191 | + return false; |
| 192 | + } |
| 193 | + |
| 194 | + InstModCallbacks tempCallbacks = callbacks; |
| 195 | + InstructionDeleter deleter(std::move(tempCallbacks)); |
| 196 | + GuaranteedOwnershipExtension borrowExtension(deleter, *deadEndBlocks); |
| 197 | + auto status = borrowExtension.checkBorrowExtension( |
| 198 | + BorrowedValue(sbi->getSrc()), newUses); |
| 199 | + if (status == GuaranteedOwnershipExtension::Invalid) { |
| 200 | + return false; |
| 201 | + } |
| 202 | + |
| 203 | + borrowExtension.transform(status); |
| 204 | + |
| 205 | + SmallVector<Operand *, 4> endBorrowUses; |
| 206 | + // Collect old scope-ending instructions. |
| 207 | + scopedAddress.visitScopeEndingUses([&](Operand *op) { |
| 208 | + endBorrowUses.push_back(op); |
| 209 | + return true; |
| 210 | + }); |
| 211 | + |
| 212 | + for (auto *use : newUses) { |
| 213 | + // Update newUsers as non-lifetime ending. |
| 214 | + storeBorrowLiveness.updateForUse(use->getUser(), |
| 215 | + /* lifetimeEnding */ false); |
| 216 | + } |
| 217 | + |
| 218 | + // Add new scope-ending instructions. |
| 219 | + scopedAddress.endScopeAtLivenessBoundary(&storeBorrowLiveness); |
| 220 | + |
| 221 | + // Remove old scope-ending instructions. |
| 222 | + for (auto *endBorrowUse : endBorrowUses) { |
| 223 | + callbacks.deleteInst(endBorrowUse->getUser()); |
| 224 | + } |
| 225 | + |
| 226 | + return true; |
| 227 | +} |
| 228 | + |
159 | 229 | void ScopedAddressValue::print(llvm::raw_ostream &os) const {
|
160 | 230 | os << "ScopedAddressIntroducingValue:\n"
|
161 | 231 | "Kind: "
|
|
0 commit comments