Skip to content

Commit 53bb72c

Browse files
committed
EscapeUtils: don't follow the result of a partial_apply for not captured address operands.
A partial_apply copies the values from indirect-in arguments, but does not capture the address.
1 parent b98608d commit 53bb72c

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,9 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
546546
// We need to follow the partial_apply value for two reasons:
547547
// 1. the closure (with the captured values) itself can escape
548548
// 2. something can escape in a destructor when the context is destroyed
549-
return walkDownUses(ofValue: pai, path: path.with(knownType: nil))
549+
if followLoads(at: path) || pai.capturesAddress(of: operand) {
550+
return walkDownUses(ofValue: pai, path: path.with(knownType: nil))
551+
}
550552
case is LoadInst, is LoadWeakInst, is LoadUnownedInst, is LoadBorrowInst:
551553
if !followLoads(at: path) {
552554
return .continueWalk
@@ -966,3 +968,23 @@ private extension SmallProjectionPath {
966968
EscapeUtilityTypes.EscapePath(projectionPath: self, followStores: false, addressIsStored: false, knownType: nil)
967969
}
968970
}
971+
972+
private extension PartialApplyInst {
973+
func capturesAddress(of operand: Operand) -> Bool {
974+
assert(operand.value.type.isAddress)
975+
guard let conv = convention(of: operand) else {
976+
fatalError("callee operand of partial_apply cannot have address type")
977+
}
978+
switch conv {
979+
case .indirectIn, .indirectInGuaranteed:
980+
// A partial_apply copies the values from indirect-in arguments, but does not capture the address.
981+
return false
982+
case .indirectInout, .indirectInoutAliasable, .packInout:
983+
return true
984+
case .directOwned, .directUnowned, .directGuaranteed, .packOwned, .packGuaranteed:
985+
fatalError("invalid convention for address operand")
986+
case .indirectOut, .packOut, .indirectInCXX:
987+
fatalError("invalid convention for partial_apply")
988+
}
989+
}
990+
}

test/SILOptimizer/mem-behavior.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,25 @@ bb0(%0 : $*X):
16561656
return %3 : $()
16571657
}
16581658

1659+
// CHECK-LABEL: @test_non_escaping_applied
1660+
// CHECK: PAIR #0.
1661+
// CHECK-NEXT: %2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
1662+
// CHECK-NEXT: %0 = argument of bb0 : $*X
1663+
// CHECK-NEXT: r=1,w=0
1664+
// CHECK: PAIR #1.
1665+
// CHECK-NEXT: %3 = apply %2() : $@noescape @callee_owned () -> ()
1666+
// CHECK-NEXT: %0 = argument of bb0 : $*X
1667+
// CHECK-NEXT: r=0,w=0
1668+
sil [ossa] @test_non_escaping_applied : $@convention(thin) (@in X) -> () {
1669+
bb0(%0 : $*X):
1670+
%1 = function_ref @indirect_X : $@convention(thin) (@in_guaranteed X) -> ()
1671+
%2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
1672+
%3 = apply %2() : $@noescape @callee_owned () -> ()
1673+
destroy_addr %0
1674+
%6 = tuple ()
1675+
return %6 : $()
1676+
}
1677+
16591678
sil @closure : $@convention(thin) (@inout_aliasable Int) -> ()
16601679
sil @closure2 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
16611680

0 commit comments

Comments
 (0)