14
14
15
15
#include " swift/Basic/Assertions.h"
16
16
#include " swift/Basic/Defer.h"
17
+ #include " swift/SIL/BasicBlockDatastructures.h"
17
18
#include " swift/SIL/DebugUtils.h"
18
19
#include " swift/SIL/InstructionUtils.h"
19
20
#include " swift/SIL/PrunedLiveness.h"
20
21
#include " swift/SIL/SILArgument.h"
21
22
#include " swift/SIL/SILBuilder.h"
22
23
#include " swift/SIL/SILInstruction.h"
23
24
#include " swift/SIL/SILValue.h"
24
- #include " swift/SIL/BasicBlockDatastructures.h"
25
25
#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
26
+ #include " swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
26
27
#include " swift/SILOptimizer/PassManager/Passes.h"
27
28
#include " swift/SILOptimizer/PassManager/Transforms.h"
28
29
#include " swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
29
30
#include " swift/SILOptimizer/Utils/CFGOptUtils.h"
30
- #include " swift/SILOptimizer/Utils/OwnershipOptUtils.h"
31
31
#include " swift/SILOptimizer/Utils/InstOptUtils.h"
32
+ #include " swift/SILOptimizer/Utils/OwnershipOptUtils.h"
32
33
#include " swift/SILOptimizer/Utils/SILSSAUpdater.h"
33
34
#include " swift/SILOptimizer/Utils/StackNesting.h"
34
35
@@ -445,14 +446,6 @@ static BuiltinInst *getEndAsyncLet(BuiltinInst *startAsyncLet) {
445
446
// / a closure is used by \p closureUser.
446
447
static void insertAfterClosureUser (SILInstruction *closureUser,
447
448
function_ref<void (SILBuilder &)> insertFn) {
448
- // Don't insert any destroy or deallocation right before an unreachable.
449
- // It's not needed an will only add up to code size.
450
- auto insertAtNonUnreachable = [&](SILBuilder &builder) {
451
- if (isa<UnreachableInst>(builder.getInsertionPoint ()))
452
- return ;
453
- insertFn (builder);
454
- };
455
-
456
449
{
457
450
SILInstruction *userForBorrow = closureUser;
458
451
if (auto *m = dyn_cast<MoveOnlyWrapperToCopyableValueInst>(userForBorrow))
@@ -468,7 +461,7 @@ static void insertAfterClosureUser(SILInstruction *closureUser,
468
461
469
462
for (auto eb : endBorrows) {
470
463
SILBuilderWithScope builder (std::next (eb->getIterator ()));
471
- insertAtNonUnreachable (builder);
464
+ insertFn (builder);
472
465
}
473
466
return ;
474
467
}
@@ -479,12 +472,12 @@ static void insertAfterClosureUser(SILInstruction *closureUser,
479
472
if (!endAsyncLet)
480
473
return ;
481
474
SILBuilderWithScope builder (std::next (endAsyncLet->getIterator ()));
482
- insertAtNonUnreachable (builder);
475
+ insertFn (builder);
483
476
return ;
484
477
}
485
478
FullApplySite fas = FullApplySite::isa (closureUser);
486
479
assert (fas);
487
- fas.insertAfterApplication (insertAtNonUnreachable );
480
+ fas.insertAfterApplication (insertFn );
488
481
}
489
482
490
483
static SILValue skipConvert (SILValue v) {
@@ -1000,6 +993,7 @@ static SILValue tryRewriteToPartialApplyStack(
1000
993
1001
994
static bool tryExtendLifetimeToLastUse (
1002
995
ConvertEscapeToNoEscapeInst *cvt, DominanceAnalysis *dominanceAnalysis,
996
+ DeadEndBlocksAnalysis *deadEndBlocksAnalysis,
1003
997
llvm::DenseMap<SILInstruction *, SILInstruction *> &memoized,
1004
998
llvm::DenseSet<SILBasicBlock *> &unreachableBlocks,
1005
999
InstructionDeleter &deleter, const bool &modifiedCFG) {
@@ -1048,10 +1042,22 @@ static bool tryExtendLifetimeToLastUse(
1048
1042
cvt->setLifetimeGuaranteed ();
1049
1043
cvt->setOperand (closureCopy);
1050
1044
1051
- insertAfterClosureUser (singleUser, [closureCopy](SILBuilder &builder) {
1052
- auto loc = RegularLocation (builder.getInsertionPointLoc ());
1053
- builder.createDestroyValue (loc, closureCopy);
1054
- });
1045
+ auto *function = cvt->getFunction ();
1046
+ // The CFG may have been modified during this run, which would have made
1047
+ // dead-end blocks analysis invalid. Mark it invalid it now if that
1048
+ // happened. If the CFG hasn't been modified, this is a noop thanks to
1049
+ // DeadEndBlocksAnalysis::shouldInvalidate.
1050
+ deadEndBlocksAnalysis->invalidate (function,
1051
+ analysisInvalidationKind (modifiedCFG));
1052
+ auto *deadEndBlocks = deadEndBlocksAnalysis->get (function);
1053
+
1054
+ insertAfterClosureUser (
1055
+ singleUser, [closureCopy, deadEndBlocks](SILBuilder &builder) {
1056
+ auto loc = RegularLocation (builder.getInsertionPointLoc ());
1057
+ auto isDeadEnd = IsDeadEnd_t (
1058
+ deadEndBlocks->isDeadEnd (builder.getInsertionPoint ()->getParent ()));
1059
+ builder.createDestroyValue (loc, closureCopy, DontPoisonRefs, isDeadEnd);
1060
+ });
1055
1061
/*
1056
1062
llvm::errs() << "after lifetime extension of\n";
1057
1063
escapingClosure->dump();
@@ -1440,6 +1446,7 @@ static void computeUnreachableBlocks(
1440
1446
1441
1447
static bool fixupClosureLifetimes (SILFunction &fn,
1442
1448
DominanceAnalysis *dominanceAnalysis,
1449
+ DeadEndBlocksAnalysis *deadEndBlocksAnalysis,
1443
1450
bool &checkStackNesting, bool &modifiedCFG) {
1444
1451
bool changed = false ;
1445
1452
@@ -1476,7 +1483,8 @@ static bool fixupClosureLifetimes(SILFunction &fn,
1476
1483
}
1477
1484
}
1478
1485
1479
- if (tryExtendLifetimeToLastUse (cvt, dominanceAnalysis, memoizedQueries,
1486
+ if (tryExtendLifetimeToLastUse (cvt, dominanceAnalysis,
1487
+ deadEndBlocksAnalysis, memoizedQueries,
1480
1488
unreachableBlocks, updater.getDeleter (),
1481
1489
/* const*/ modifiedCFG)) {
1482
1490
changed = true ;
@@ -1516,9 +1524,11 @@ class ClosureLifetimeFixup : public SILFunctionTransform {
1516
1524
bool modifiedCFG = false ;
1517
1525
1518
1526
auto *dominanceAnalysis = PM->getAnalysis <DominanceAnalysis>();
1527
+ auto *deadEndBlocksAnalysis = getAnalysis<DeadEndBlocksAnalysis>();
1519
1528
1520
1529
if (fixupClosureLifetimes (*getFunction (), dominanceAnalysis,
1521
- checkStackNesting, modifiedCFG)) {
1530
+ deadEndBlocksAnalysis, checkStackNesting,
1531
+ modifiedCFG)) {
1522
1532
updateBorrowedFrom (getPassManager (), getFunction ());
1523
1533
if (checkStackNesting){
1524
1534
modifiedCFG |=
0 commit comments