|
12 | 12 |
|
13 | 13 | #define DEBUG_TYPE "sil-dce" |
14 | 14 | #include "swift/Basic/Assertions.h" |
| 15 | +#include "swift/SIL/BasicBlockBits.h" |
15 | 16 | #include "swift/SIL/DebugUtils.h" |
| 17 | +#include "swift/SIL/MemAccessUtils.h" |
| 18 | +#include "swift/SIL/NodeBits.h" |
16 | 19 | #include "swift/SIL/OwnershipUtils.h" |
17 | 20 | #include "swift/SIL/SILArgument.h" |
18 | 21 | #include "swift/SIL/SILBasicBlock.h" |
19 | | -#include "swift/SIL/BasicBlockBits.h" |
20 | | -#include "swift/SIL/NodeBits.h" |
21 | 22 | #include "swift/SIL/SILBuilder.h" |
22 | 23 | #include "swift/SIL/SILFunction.h" |
23 | 24 | #include "swift/SIL/SILUndef.h" |
@@ -158,6 +159,8 @@ class DCE { |
158 | 159 | bool CallsChanged = false; |
159 | 160 |
|
160 | 161 | bool precomputeControlInfo(); |
| 162 | + /// Populates borrow dependencies and disables DCE if needed. |
| 163 | + void processBorrow(BorrowedValue borrow); |
161 | 164 | void markLive(); |
162 | 165 | /// Record a reverse dependency from \p from to \p to meaning \p to is live |
163 | 166 | /// if \p from is also live. |
@@ -252,6 +255,49 @@ static BuiltinInst *getProducer(CondFailInst *CFI) { |
252 | 255 | return nullptr; |
253 | 256 | } |
254 | 257 |
|
| 258 | +void DCE::processBorrow(BorrowedValue borrow) { |
| 259 | + // Populate guaranteedPhiDependencies for this borrow |
| 260 | + findGuaranteedPhiDependencies(borrow); |
| 261 | + if (!borrow.hasReborrow()) { |
| 262 | + return; |
| 263 | + } |
| 264 | + |
| 265 | + // If the borrow was not computed from another |
| 266 | + // borrow, return. |
| 267 | + SILValue baseValue; |
| 268 | + if (auto *beginBorrow = dyn_cast<BeginBorrowInst>(*borrow)) { |
| 269 | + auto borrowOp = beginBorrow->getOperand(); |
| 270 | + if (borrowOp->getOwnershipKind() != OwnershipKind::Guaranteed) { |
| 271 | + return; |
| 272 | + } |
| 273 | + baseValue = borrowOp; |
| 274 | + } else { |
| 275 | + auto *loadBorrow = cast<LoadBorrowInst>(*borrow); |
| 276 | + auto accessBase = AccessBase::compute(loadBorrow->getOperand()); |
| 277 | + if (!accessBase.isReference()) { |
| 278 | + return; |
| 279 | + } |
| 280 | + baseValue = accessBase.getReference(); |
| 281 | + } |
| 282 | + // If the borrow was computed from another |
| 283 | + // borrow, disable DCE of the outer borrow. |
| 284 | + // This is because, when a reborrow is dead, DCE has to insert |
| 285 | + // end_borrows in predecessor blocks and it cannot yet handle borrow |
| 286 | + // nesting. |
| 287 | + // TODO: Instead of disabling DCE of outer borrow, consider inserting |
| 288 | + // end_borrows inside-out. |
| 289 | + SmallVector<SILValue, 4> roots; |
| 290 | + findGuaranteedReferenceRoots(baseValue, |
| 291 | + /*lookThroughNestedBorrows=*/false, roots); |
| 292 | + // Visit the end_borrows of all the borrow scopes that this |
| 293 | + // begin_borrow could be borrowing, and mark them live. |
| 294 | + for (auto root : roots) { |
| 295 | + visitTransitiveEndBorrows(root, [&](EndBorrowInst *endBorrow) { |
| 296 | + markInstructionLive(endBorrow); |
| 297 | + }); |
| 298 | + } |
| 299 | +} |
| 300 | + |
255 | 301 | // Determine which instructions from this function we need to keep. |
256 | 302 | void DCE::markLive() { |
257 | 303 | // Find the initial set of instructions in this function that appear |
@@ -327,32 +373,12 @@ void DCE::markLive() { |
327 | 373 | } |
328 | 374 | case SILInstructionKind::BeginBorrowInst: { |
329 | 375 | auto *borrowInst = cast<BeginBorrowInst>(&I); |
330 | | - // Populate guaranteedPhiDependencies for this borrowInst |
331 | | - findGuaranteedPhiDependencies(BorrowedValue(borrowInst)); |
332 | | - auto disableBorrowDCE = [&](SILValue borrow) { |
333 | | - visitTransitiveEndBorrows(borrow, [&](EndBorrowInst *endBorrow) { |
334 | | - markInstructionLive(endBorrow); |
335 | | - }); |
336 | | - }; |
337 | | - // If we have a begin_borrow of a @guaranteed operand, disable DCE'ing |
338 | | - // of parent borrow scopes. Dead reborrows needs complex handling, which |
339 | | - // is why it is disabled for now. |
340 | | - if (borrowInst->getOperand()->getOwnershipKind() == |
341 | | - OwnershipKind::Guaranteed) { |
342 | | - SmallVector<SILValue, 4> roots; |
343 | | - findGuaranteedReferenceRoots(borrowInst->getOperand(), |
344 | | - /*lookThroughNestedBorrows=*/false, |
345 | | - roots); |
346 | | - // Visit the end_borrows of all the borrow scopes that this |
347 | | - // begin_borrow could be borrowing, and mark them live. |
348 | | - for (auto root : roots) { |
349 | | - disableBorrowDCE(root); |
350 | | - } |
351 | | - } |
| 376 | + processBorrow(BorrowedValue(borrowInst)); |
352 | 377 | break; |
353 | 378 | } |
354 | 379 | case SILInstructionKind::LoadBorrowInst: { |
355 | | - findGuaranteedPhiDependencies(BorrowedValue(cast<LoadBorrowInst>(&I))); |
| 380 | + auto *loadBorrowInst = cast<LoadBorrowInst>(&I); |
| 381 | + processBorrow(BorrowedValue(loadBorrowInst)); |
356 | 382 | break; |
357 | 383 | } |
358 | 384 | default: |
|
0 commit comments