Skip to content

Commit e71cd4b

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. Since this is a superset of the `markDepChain` logic, remove that. So that we don't have 2 ways to check for the same.
1 parent 960619b commit e71cd4b

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 17 additions & 18 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.
@@ -735,7 +747,6 @@ static SILValue tryRewriteToPartialApplyStack(
735747
unsigned appliedArgStartIdx =
736748
newPA->getOrigCalleeType()->getNumParameters() - newPA->getNumArguments();
737749

738-
MarkDependenceInst *markDepChain = nullptr;
739750
for (unsigned i : indices(newPA->getArgumentOperands())) {
740751
auto &arg = newPA->getArgumentOperands()[i];
741752
SILValue copy = arg.get();
@@ -789,31 +800,19 @@ static SILValue tryRewriteToPartialApplyStack(
789800
// %md = mark_dependence %pai on %0
790801
// %md2 = mark_dependence %md on %1
791802
// to tie all of those operands together on the same partial_apply.
792-
//
793-
// FIXME: Should we not be chaining like this and just emit independent
794-
// mark_dependence?
795-
if (markDepChain && mark->getValue() == markDepChain) {
796-
markDep = mark;
797-
markDepChain = mark;
798-
continue;
799-
}
800803

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) {
804+
// Check if we're marking dependence on this stack slot for the current
805+
// partial_apply or it's chain of mark_dependences.
806+
if (!lookThroughMarkDependenceChainForValue(mark, newPA) ||
807+
mark->getBase() != stack) {
805808
LLVM_DEBUG(llvm::dbgs() << "-- had unexpected mark_dependence use\n";
806809
use->getUser()->print(llvm::dbgs());
807810
llvm::dbgs() << "\n");
808-
811+
initialization = nullptr;
809812
break;
810813
}
811814
markDep = mark;
812815

813-
if (!markDepChain) {
814-
markDepChain = mark;
815-
}
816-
817816
continue;
818817
}
819818

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)