Skip to content

Commit 46c5e9e

Browse files
authored
Merge pull request swiftlang#81341 from eeckstein/closure-optimizations
SILCombine: handle `mark_dependence` in some closure optimizations
2 parents 921d6d8 + 2c27963 commit 46c5e9e

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,8 +1520,14 @@ SILInstruction *SILCombiner::legacyVisitApplyInst(ApplyInst *AI) {
15201520
return nullptr;
15211521

15221522
SILValue callee = AI->getCallee();
1523-
if (auto *cee = dyn_cast<ConvertEscapeToNoEscapeInst>(callee)) {
1524-
callee = cee->getOperand();
1523+
for (;;) {
1524+
if (auto *cee = dyn_cast<ConvertEscapeToNoEscapeInst>(callee)) {
1525+
callee = cee->getOperand();
1526+
} else if (auto *mdi = dyn_cast<MarkDependenceInst>(callee)) {
1527+
callee = mdi->getValue();
1528+
} else {
1529+
break;
1530+
}
15251531
}
15261532
if (auto *CFI = dyn_cast<ConvertFunctionInst>(callee))
15271533
return optimizeApplyOfConvertFunctionInst(AI, CFI);

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,9 @@ static bool useHasTransitiveOwnership(const SILInstruction *inst) {
963963
if (isa<ConvertEscapeToNoEscapeInst>(inst))
964964
return true;
965965

966+
if (isa<MarkDependenceInst>(inst))
967+
return true;
968+
966969
// Look through copy_value, begin_borrow, move_value. They are inert for our
967970
// purposes, but we need to look through it.
968971
return isa<CopyValueInst>(inst) || isa<BeginBorrowInst>(inst) ||
@@ -1095,13 +1098,16 @@ void swift::getConsumedPartialApplyArgs(PartialApplyInst *pai,
10951098
}
10961099
}
10971100

1098-
bool swift::collectDestroys(SingleValueInstruction *inst,
1099-
SmallVectorImpl<Operand *> &destroys) {
1101+
static bool collectDestroysRecursively(SingleValueInstruction *inst,
1102+
SmallVectorImpl<Operand *> &destroys,
1103+
InstructionSet &visited) {
11001104
bool isDead = true;
11011105
for (Operand *use : inst->getUses()) {
11021106
SILInstruction *user = use->getUser();
1107+
if (!visited.insert(user))
1108+
continue;
11031109
if (useHasTransitiveOwnership(user)) {
1104-
if (!collectDestroys(cast<SingleValueInstruction>(user), destroys))
1110+
if (!collectDestroysRecursively(cast<SingleValueInstruction>(user), destroys, visited))
11051111
isDead = false;
11061112
destroys.push_back(use);
11071113
} else if (useDoesNotKeepValueAlive(user)) {
@@ -1113,6 +1119,12 @@ bool swift::collectDestroys(SingleValueInstruction *inst,
11131119
return isDead;
11141120
}
11151121

1122+
bool swift::collectDestroys(SingleValueInstruction *inst,
1123+
SmallVectorImpl<Operand *> &destroys) {
1124+
InstructionSet visited(inst->getFunction());
1125+
return collectDestroysRecursively(inst, destroys, visited);
1126+
}
1127+
11161128
/// Move the original arguments of the partial_apply into newly created
11171129
/// temporaries to extend the lifetime of the arguments until the partial_apply
11181130
/// is finally destroyed.

test/SILOptimizer/sil_combine1.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@ public func test_compose_closure() -> Int32 {
3636
return gs
3737
}
3838

39+
// CHECK-LABEL: sil @$s12sil_combine122remove_partial_applies_3key5valueySDySSSiGSgz_SSSitF :
40+
// CHECK-NOT: partial_apply
41+
// CHECK: } // end sil function '$s12sil_combine122remove_partial_applies_3key5valueySDySSSiGSgz_SSSitF'
42+
public func remove_partial_applies(_ dict: inout [String: Int]?, key: String, value: Int) {
43+
dict?[key, default: value] = value
44+
}

test/SILOptimizer/sil_combine_apply_ossa.sil

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,37 @@ bb0(%0 : $Int):
11721172
return %r : $()
11731173
}
11741174

1175+
// CHECK-LABEL: sil [ossa] @test_mark_dependence_of_closure :
1176+
// CHECK-NOT: partial_apply
1177+
// CHECK-LABEL: } // end sil function 'test_mark_dependence_of_closure'
1178+
sil [ossa] @test_mark_dependence_of_closure : $@convention(thin) (Int) -> () {
1179+
bb0(%0 : $Int):
1180+
%3 = function_ref @closure2 : $@convention(thin) (Int) -> ()
1181+
%4 = partial_apply %3(%0) : $@convention(thin) (Int) -> ()
1182+
%5 = convert_function %4 to $@callee_owned () -> ()
1183+
%6 = convert_escape_to_noescape %5 to $@noescape @callee_owned () -> ()
1184+
%7 = mark_dependence %6 on %5
1185+
apply %7() : $@noescape @callee_owned () -> ()
1186+
destroy_value %5
1187+
%r = tuple ()
1188+
return %r : $()
1189+
}
1190+
1191+
// CHECK-LABEL: sil [ossa] @test_dead_closure_with_mark_dependence :
1192+
// CHECK-NOT: partial_apply
1193+
// CHECK-LABEL: } // end sil function 'test_dead_closure_with_mark_dependence'
1194+
sil [ossa] @test_dead_closure_with_mark_dependence : $@convention(thin) (Int) -> () {
1195+
bb0(%0 : $Int):
1196+
%3 = function_ref @closure2 : $@convention(thin) (Int) -> ()
1197+
%4 = partial_apply %3(%0) : $@convention(thin) (Int) -> ()
1198+
%6 = convert_escape_to_noescape %4 to $@noescape @callee_owned () -> ()
1199+
%7 = mark_dependence %6 on %4
1200+
destroy_value %4
1201+
destroy_value %7
1202+
%r = tuple ()
1203+
return %r : $()
1204+
}
1205+
11751206
sil [ossa] @closure2 : $@convention(thin) (Int) -> ()
11761207

11771208
sil [ossa] @yield1 : $@yield_once(Float) -> (@yields Float) {

0 commit comments

Comments
 (0)