mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85934 from atrick/fix-closure-liveness
Fix InteriorUseWalker: consider partial_apply [on_stack] an escape
This commit is contained in:
@@ -626,9 +626,13 @@ extension InteriorUseWalker: OwnershipUseVisitor {
|
||||
if value.type.isTrivial(in: function) {
|
||||
return .continueWalk
|
||||
}
|
||||
guard value.type.isEscapable(in: function) else {
|
||||
guard value.mayEscape else {
|
||||
// Non-escapable dependent values can be lifetime-extended by copying, which is not handled by
|
||||
// InteriorUseWalker. LifetimeDependenceDefUseWalker does this.
|
||||
// InteriorUseWalker. LifetimeDependenceDefUseWalker does this. Alternatively, we could continue to `walkDownUses`
|
||||
// but later recognize a copy of a `mayEscape` value to be a pointer escape at that point.
|
||||
//
|
||||
// This includes partial_apply [on_stack] which can currently be copied. Although a better solution would be to
|
||||
// make copying an on-stack closure illegal SIL.
|
||||
return pointerEscapingUse(of: operand)
|
||||
}
|
||||
if useVisitor(operand) == .abortWalk {
|
||||
|
||||
@@ -319,8 +319,11 @@ bb0(%0 : @owned $String):
|
||||
return %r
|
||||
}
|
||||
|
||||
// TODO: If InteriorLiveness handles `partial_apply [on_stack]`, then the destroy can be hoisted.
|
||||
//
|
||||
// CHECK-LABEL: sil [ossa] @partial_apply :
|
||||
// CHECK: destroy_value %1
|
||||
// CHECK-NEXT: debug_step
|
||||
// CHECK-NEXT: destroy_value %0
|
||||
// CHECK: } // end sil function 'partial_apply'
|
||||
sil [ossa] @partial_apply : $@convention(thin) (@owned String) -> () {
|
||||
@@ -445,3 +448,31 @@ bb0:
|
||||
%r = tuple ()
|
||||
return %r
|
||||
}
|
||||
|
||||
sil @closure1 : $@convention(thin) (@guaranteed C) -> ()
|
||||
|
||||
// rdar165850554: InteriorUseDefWalker must consider copies of an on-stack partial apply when computing liveness of the
|
||||
// borrowed operand.
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @test_closure_copy :
|
||||
// CHECK: %1 = copy_value %0
|
||||
// CHECK: debug_step
|
||||
// CHECK-NEXT: destroy_value %1
|
||||
// CHECK-LABEL: } // end sil function 'test_closure_copy'
|
||||
sil private [ossa] @test_closure_copy : $@convention(thin) (@owned C) -> () {
|
||||
bb0(%0 : @owned $C):
|
||||
// create a non-lexical value to trigger mandatory destroy hoisting
|
||||
%1 = copy_value %0
|
||||
%2 = function_ref @closure1 : $@convention(thin) (@guaranteed C) -> ()
|
||||
%3 = partial_apply [callee_guaranteed] [on_stack] %2(%1) : $@convention(thin) (@guaranteed C) -> ()
|
||||
%4 = copy_value %3
|
||||
// force a pointer-escape
|
||||
%5 = unchecked_bitwise_cast %4 to $@noescape @callee_guaranteed () -> ()
|
||||
destroy_value %3
|
||||
destroy_value %0
|
||||
destroy_value %4
|
||||
debug_step
|
||||
destroy_value %1
|
||||
%10 = tuple ()
|
||||
return %10
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user