Skip to content

Commit 8575146

Browse files
committed
Improve copy elimination of noncopyable captures in ClosureLifetimeFixup
For a mark_dependence user of the stack, look through the mark_dependence chain to match the partial_apply
1 parent 960619b commit 8575146

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ collectStackClosureLifetimeEnds(SmallVectorImpl<SILInstruction *> &lifetimeEnds,
554554
}
555555
}
556556

557+
static bool lookThroughMarkDependenceChainForValue(MarkDependenceInst *mark,
558+
PartialApplyInst *pai) {
559+
if (mark->getValue() == pai) {
560+
return true;
561+
}
562+
auto *markChain = dyn_cast<MarkDependenceInst>(mark->getValue());
563+
if (!markChain) {
564+
return false;
565+
}
566+
return lookThroughMarkDependenceChainForValue(markChain, pai);
567+
}
568+
557569
/// Rewrite a partial_apply convert_escape_to_noescape sequence with a single
558570
/// apply/try_apply user to a partial_apply [stack] terminated with a
559571
/// dealloc_stack placed after the apply.
@@ -736,6 +748,7 @@ static SILValue tryRewriteToPartialApplyStack(
736748
newPA->getOrigCalleeType()->getNumParameters() - newPA->getNumArguments();
737749

738750
MarkDependenceInst *markDepChain = nullptr;
751+
739752
for (unsigned i : indices(newPA->getArgumentOperands())) {
740753
auto &arg = newPA->getArgumentOperands()[i];
741754
SILValue copy = arg.get();
@@ -798,14 +811,14 @@ static SILValue tryRewriteToPartialApplyStack(
798811
continue;
799812
}
800813

801-
// If we're marking dependence of the current partial_apply on this
802-
// stack slot, that's fine.
803-
if (mark->getValue() != newPA
804-
|| mark->getBase() != stack) {
814+
// If we're marking dependence on this stack slot for the current
815+
// partial_apply or it's chain of mark_dependences, that's fine.
816+
if (!lookThroughMarkDependenceChainForValue(mark, newPA) ||
817+
mark->getBase() != stack) {
805818
LLVM_DEBUG(llvm::dbgs() << "-- had unexpected mark_dependence use\n";
806819
use->getUser()->print(llvm::dbgs());
807820
llvm::dbgs() << "\n");
808-
821+
initialization = nullptr;
809822
break;
810823
}
811824
markDep = mark;

test/SILOptimizer/moveonly_closure_lifetime_fixup_address_only_borrowed_captures.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,27 @@ struct E<T>: ~Copyable {
88
var t: T
99
}
1010

11+
struct C<T> {
12+
var t: T
13+
}
14+
1115
var escaper: () -> () = {}
1216

1317
func nonescaping(_ x: () -> ()) { }
1418
func escaping(_ x: @escaping () -> ()) { escaper = x }
1519

1620
func borrow<T>(_: borrowing E<T>) {}
21+
func borrow<T>(_: borrowing C<T>) {}
22+
23+
func testMultiCapture<T>(_ e: borrowing E<T>, _ c: C<T>) {
24+
// CHECK: [[C_STK:%.*]] = alloc_stack $C<T>
25+
// CHECK: copy_addr %1 to [init] [[C_STK]] : $*C<T>
26+
// CHECK: partial_apply {{.*}}[on_stack] {{.*}}([[C_STK]], %0) :
27+
nonescaping {
28+
borrow(c)
29+
borrow(e)
30+
}
31+
}
1732

1833
// CHECK-LABEL: sil {{.*}}16testNeverEscaped
1934
func testNeverEscaped<T>(_ e: borrowing E<T>) {

0 commit comments

Comments
 (0)