1414
1515#include " swift/Basic/Assertions.h"
1616#include " swift/Basic/Defer.h"
17+ #include " swift/SIL/BasicBlockDatastructures.h"
1718#include " swift/SIL/DebugUtils.h"
1819#include " swift/SIL/InstructionUtils.h"
1920#include " swift/SIL/PrunedLiveness.h"
2021#include " swift/SIL/SILArgument.h"
2122#include " swift/SIL/SILBuilder.h"
2223#include " swift/SIL/SILInstruction.h"
2324#include " swift/SIL/SILValue.h"
24- #include " swift/SIL/BasicBlockDatastructures.h"
2525#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
26+ #include " swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
2627#include " swift/SILOptimizer/PassManager/Passes.h"
2728#include " swift/SILOptimizer/PassManager/Transforms.h"
2829#include " swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
2930#include " swift/SILOptimizer/Utils/CFGOptUtils.h"
30- #include " swift/SILOptimizer/Utils/OwnershipOptUtils.h"
3131#include " swift/SILOptimizer/Utils/InstOptUtils.h"
32+ #include " swift/SILOptimizer/Utils/OwnershipOptUtils.h"
3233#include " swift/SILOptimizer/Utils/SILSSAUpdater.h"
3334#include " swift/SILOptimizer/Utils/StackNesting.h"
3435
@@ -445,14 +446,6 @@ static BuiltinInst *getEndAsyncLet(BuiltinInst *startAsyncLet) {
445446// / a closure is used by \p closureUser.
446447static void insertAfterClosureUser (SILInstruction *closureUser,
447448 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-
456449 {
457450 SILInstruction *userForBorrow = closureUser;
458451 if (auto *m = dyn_cast<MoveOnlyWrapperToCopyableValueInst>(userForBorrow))
@@ -468,7 +461,7 @@ static void insertAfterClosureUser(SILInstruction *closureUser,
468461
469462 for (auto eb : endBorrows) {
470463 SILBuilderWithScope builder (std::next (eb->getIterator ()));
471- insertAtNonUnreachable (builder);
464+ insertFn (builder);
472465 }
473466 return ;
474467 }
@@ -479,12 +472,12 @@ static void insertAfterClosureUser(SILInstruction *closureUser,
479472 if (!endAsyncLet)
480473 return ;
481474 SILBuilderWithScope builder (std::next (endAsyncLet->getIterator ()));
482- insertAtNonUnreachable (builder);
475+ insertFn (builder);
483476 return ;
484477 }
485478 FullApplySite fas = FullApplySite::isa (closureUser);
486479 assert (fas);
487- fas.insertAfterApplication (insertAtNonUnreachable );
480+ fas.insertAfterApplication (insertFn );
488481}
489482
490483static SILValue skipConvert (SILValue v) {
@@ -1000,6 +993,7 @@ static SILValue tryRewriteToPartialApplyStack(
1000993
1001994static bool tryExtendLifetimeToLastUse (
1002995 ConvertEscapeToNoEscapeInst *cvt, DominanceAnalysis *dominanceAnalysis,
996+ DeadEndBlocksAnalysis *deadEndBlocksAnalysis,
1003997 llvm::DenseMap<SILInstruction *, SILInstruction *> &memoized,
1004998 llvm::DenseSet<SILBasicBlock *> &unreachableBlocks,
1005999 InstructionDeleter &deleter, const bool &modifiedCFG) {
@@ -1048,10 +1042,22 @@ static bool tryExtendLifetimeToLastUse(
10481042 cvt->setLifetimeGuaranteed ();
10491043 cvt->setOperand (closureCopy);
10501044
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+ });
10551061 /*
10561062 llvm::errs() << "after lifetime extension of\n";
10571063 escapingClosure->dump();
@@ -1440,6 +1446,7 @@ static void computeUnreachableBlocks(
14401446
14411447static bool fixupClosureLifetimes (SILFunction &fn,
14421448 DominanceAnalysis *dominanceAnalysis,
1449+ DeadEndBlocksAnalysis *deadEndBlocksAnalysis,
14431450 bool &checkStackNesting, bool &modifiedCFG) {
14441451 bool changed = false ;
14451452
@@ -1476,7 +1483,8 @@ static bool fixupClosureLifetimes(SILFunction &fn,
14761483 }
14771484 }
14781485
1479- if (tryExtendLifetimeToLastUse (cvt, dominanceAnalysis, memoizedQueries,
1486+ if (tryExtendLifetimeToLastUse (cvt, dominanceAnalysis,
1487+ deadEndBlocksAnalysis, memoizedQueries,
14801488 unreachableBlocks, updater.getDeleter (),
14811489 /* const*/ modifiedCFG)) {
14821490 changed = true ;
@@ -1516,9 +1524,11 @@ class ClosureLifetimeFixup : public SILFunctionTransform {
15161524 bool modifiedCFG = false ;
15171525
15181526 auto *dominanceAnalysis = PM->getAnalysis <DominanceAnalysis>();
1527+ auto *deadEndBlocksAnalysis = getAnalysis<DeadEndBlocksAnalysis>();
15191528
15201529 if (fixupClosureLifetimes (*getFunction (), dominanceAnalysis,
1521- checkStackNesting, modifiedCFG)) {
1530+ deadEndBlocksAnalysis, checkStackNesting,
1531+ modifiedCFG)) {
15221532 updateBorrowedFrom (getPassManager (), getFunction ());
15231533 if (checkStackNesting){
15241534 modifiedCFG |=
0 commit comments