Skip to content

Commit b1b89ca

Browse files
authored
Merge pull request #63435 from nate-chandler/cherrypick/508708919ae6bd49d85a6fe3da2ed53ed2cb3a1c
ClosureLifetimeFixup: Fix corner case of unconnected basic blocks
2 parents b86cc30 + 8dfa4f3 commit b1b89ca

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/SIL/BasicBlockDatastructures.h"
2222
#include "swift/SILOptimizer/PassManager/Passes.h"
2323
#include "swift/SILOptimizer/PassManager/Transforms.h"
24+
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
2425
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
2526
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2627
#include "swift/SILOptimizer/Utils/SILSSAUpdater.h"
@@ -477,6 +478,7 @@ static SILValue tryRewriteToPartialApplyStack(
477478
ConvertEscapeToNoEscapeInst *cvt, SILInstruction *closureUser,
478479
DominanceAnalysis *dominanceAnalysis, InstructionDeleter &deleter,
479480
llvm::DenseMap<SILInstruction *, SILInstruction *> &memoized,
481+
llvm::DenseSet<SILBasicBlock *> &unreachableBlocks,
480482
const bool &modifiedCFG) {
481483

482484
auto *origPA = dyn_cast<PartialApplyInst>(skipConvert(cvt->getOperand()));
@@ -583,6 +585,13 @@ static SILValue tryRewriteToPartialApplyStack(
583585
dominanceAnalysis->invalidate(closureUser->getFunction(),
584586
analysisInvalidationKind(modifiedCFG));
585587
// Insert dealloc_stacks of any in_guaranteed captures.
588+
589+
// Don't run insertDeallocOfCapturedArguments if newPA is in an unreachable
590+
// block insertDeallocOfCapturedArguments will run code that computes the DF
591+
// for newPA that will loop infinetly.
592+
if (unreachableBlocks.count(newPA->getParent()))
593+
return closure;
594+
586595
insertDeallocOfCapturedArguments(
587596
newPA, dominanceAnalysis->get(closureUser->getFunction()));
588597
return closure;
@@ -591,6 +600,7 @@ static SILValue tryRewriteToPartialApplyStack(
591600
static bool tryExtendLifetimeToLastUse(
592601
ConvertEscapeToNoEscapeInst *cvt, DominanceAnalysis *dominanceAnalysis,
593602
llvm::DenseMap<SILInstruction *, SILInstruction *> &memoized,
603+
llvm::DenseSet<SILBasicBlock *> &unreachableBlocks,
594604
InstructionDeleter &deleter, const bool &modifiedCFG) {
595605
// If there is a single user that is an apply this is simple: extend the
596606
// lifetime of the operand until after the apply.
@@ -614,7 +624,7 @@ static bool tryExtendLifetimeToLastUse(
614624

615625
if (SILValue closure = tryRewriteToPartialApplyStack(
616626
cvt, singleUser, dominanceAnalysis, deleter, memoized,
617-
/*const*/ modifiedCFG)) {
627+
unreachableBlocks, /*const*/ modifiedCFG)) {
618628
if (auto *cfi = dyn_cast<ConvertFunctionInst>(closure))
619629
closure = cfi->getOperand();
620630
if (endAsyncLet && isa<MarkDependenceInst>(closure)) {
@@ -1009,6 +1019,22 @@ static bool fixupCopyBlockWithoutEscaping(CopyBlockWithoutEscapingInst *cb,
10091019
return true;
10101020
}
10111021

1022+
static void computeUnreachableBlocks(
1023+
llvm::DenseSet<SILBasicBlock*> &unreachableBlocks,
1024+
SILFunction &fn) {
1025+
1026+
ReachableBlocks isReachable(&fn);
1027+
llvm::DenseSet<SILBasicBlock *> reachable;
1028+
isReachable.visit([&] (SILBasicBlock *block) -> bool {
1029+
reachable.insert(block);
1030+
return true;
1031+
});
1032+
for (auto &block : fn) {
1033+
if (!reachable.count(&block))
1034+
unreachableBlocks.insert(&block);
1035+
}
1036+
}
1037+
10121038
static bool fixupClosureLifetimes(SILFunction &fn,
10131039
DominanceAnalysis *dominanceAnalysis,
10141040
bool &checkStackNesting, bool &modifiedCFG) {
@@ -1018,6 +1044,9 @@ static bool fixupClosureLifetimes(SILFunction &fn,
10181044
// queries.
10191045
llvm::DenseMap<SILInstruction *, SILInstruction *> memoizedQueries;
10201046

1047+
llvm::DenseSet<SILBasicBlock *> unreachableBlocks;
1048+
computeUnreachableBlocks(unreachableBlocks, fn);
1049+
10211050
for (auto &block : fn) {
10221051
SILSSAUpdater updater;
10231052

@@ -1045,7 +1074,7 @@ static bool fixupClosureLifetimes(SILFunction &fn,
10451074
}
10461075

10471076
if (tryExtendLifetimeToLastUse(cvt, dominanceAnalysis, memoizedQueries,
1048-
updater.getDeleter(),
1077+
unreachableBlocks, updater.getDeleter(),
10491078
/*const*/ modifiedCFG)) {
10501079
changed = true;
10511080
checkStackNesting = true;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -closure-lifetime-fixup %s | %FileCheck %s
2+
3+
sil_stage raw
4+
5+
6+
import Builtin
7+
import Swift
8+
9+
sil @cl : $@convention(thin) (@in_guaranteed Builtin.Int64) -> ()
10+
sil @f : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
11+
12+
// This test case used to loop infinitely because it processed the dead block as
13+
// part of a dominance based algorithm.
14+
15+
// CHECK: partial_apply
16+
17+
sil [ossa] @repo : $@convention(thin) (Builtin.Int1, Builtin.Int1, @in_guaranteed Builtin.Int64) -> () {
18+
bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1, %2: $*Builtin.Int64):
19+
cond_br %0, bb2, bb1
20+
21+
bb1:
22+
br bb7
23+
24+
bb2:
25+
br bb3
26+
27+
bb3:
28+
cond_br %1, bb4, bb5
29+
30+
bb4:
31+
br bb8
32+
33+
bb5:
34+
br bb8
35+
36+
bb6:
37+
%41 = alloc_stack $Builtin.Int64
38+
copy_addr %2 to [init] %41 : $*Builtin.Int64
39+
%40 = function_ref @cl : $@convention(thin) (@in_guaranteed Builtin.Int64) -> ()
40+
%43 = partial_apply [callee_guaranteed] %40(%41) : $@convention(thin) (@in_guaranteed Builtin.Int64) -> ()
41+
%44 = convert_escape_to_noescape [not_guaranteed] %43 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
42+
%55 = function_ref @f : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
43+
%56 = apply %55(%44) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
44+
destroy_value %43 : $@callee_guaranteed () -> ()
45+
dealloc_stack %41 : $*Builtin.Int64
46+
br bb8
47+
48+
bb7:
49+
br bb8
50+
51+
bb8:
52+
%r = tuple()
53+
return %r : $()
54+
}

0 commit comments

Comments
 (0)