|
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