Skip to content

Commit 34dbae1

Browse files
committed
[ClosureSpecializer] Don't release trivial noescape try_apply arg twice.
When a specialization is created, in the original function, releases are added in two different places: (1) `ClosureSpecCloner::populateCloned` (2) `rewriteApplyInst` In the former, releases are added for closures which are guaranteed or trivial noescape (but with owned convention). In the latter, releases are added for closures that are owned. Previously, when emitting releases at (2), whether the closure was trivial noescape wasn't considered. The result was inserting the releases twice, an overrelease. Here, fix (2) to recognize trivial noescape as not +1. rdar://110058964
1 parent 4640f07 commit 34dbae1

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc,
460460
// If we passed in the original closure as @owned, then insert a release
461461
// right after NewAI. This is to balance the +1 from being an @owned
462462
// argument to AI.
463-
if (!CSDesc.isClosureConsumed() || !CSDesc.closureHasRefSemanticContext()) {
463+
if (!CSDesc.isClosureConsumed() || CSDesc.isTrivialNoEscapeParameter() ||
464+
!CSDesc.closureHasRefSemanticContext()) {
464465
break;
465466
}
466467

test/SILOptimizer/closure_specialize.sil

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,71 @@ bb0(%0 : $Int):
702702
return %empty : $()
703703
}
704704

705+
sil @testThrowingClosureConvertHelper : $@convention(thin) (Int) -> (Int, @error any Error)
706+
sil [reabstraction_thunk] @reabstractionThunkThrowing : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
707+
708+
sil @testClosureThunkNoEscapeThrowing : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error) {
709+
entry(%empty : $*(), %closure : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>):
710+
%out = alloc_stack $Int
711+
try_apply %closure(%out) : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>, normal bb1, error bb2
712+
713+
bb1(%ret : $()):
714+
dealloc_stack %out : $*Int
715+
store %ret to %empty : $*()
716+
%retval = tuple ()
717+
return %retval : $()
718+
719+
bb2(%error : $any Error):
720+
dealloc_stack %out : $*Int
721+
throw %error : $any Error
722+
}
723+
724+
// CHECK-LABEL: sil @reabstractionThrowing : $@convention(thin) (Int) -> ((), @error any Error) {
725+
// CHECK: [[HELPER:%[^,]+]] = function_ref @testThrowingClosureConvertHelper
726+
// CHECK: [[SPECIALIZATION:%[^,]+]] = function_ref @$s32testClosureThunkNoEscapeThrowing0afB13ConvertHelperSiTf1nc_n
727+
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[HELPER]]
728+
// CHECK: [[NOESCAPE_CLOSURE:%[^,]+]] = convert_escape_to_noescape [[CLOSURE]]
729+
// CHECK: try_apply [[SPECIALIZATION]]{{.*}}normal [[NORMAL_BLOCK:bb[0-9]+]], error [[ERROR_BLOCK:bb[0-9]+]]
730+
// CHECK: [[NORMAL_BLOCK]]
731+
// CHECK: release_value [[CLOSURE]]
732+
// CHECK-NOT: release_value [[CLOSURE]]
733+
// CHECK: strong_release [[NOESCAPE_CLOSURE]]
734+
// CHECK: [[ERROR_BLOCK]]
735+
// CHECK: release_value [[CLOSURE]]
736+
// CHECK-NOT: release_value [[CLOSURE]]
737+
// CHECK: strong_release [[NOESCAPE_CLOSURE]]
738+
// CHECK-LABEL: } // end sil function 'reabstractionThrowing'
739+
sil @reabstractionThrowing : $(Int) -> ((), @error any Error) {
740+
bb0(%value : $Int):
741+
%testThrowingClosureConvertHelper = function_ref @testThrowingClosureConvertHelper : $@convention(thin) (Int) -> (Int, @error any Error)
742+
%closure = partial_apply [callee_guaranteed] %testThrowingClosureConvertHelper(%value) : $@convention(thin) (Int) -> (Int, @error any Error)
743+
%noescapeClosure = convert_escape_to_noescape %closure : $@callee_guaranteed () -> (Int, @error any Error) to $@noescape @callee_guaranteed () -> (Int, @error any Error)
744+
%thunk = function_ref @reabstractionThunkThrowing : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
745+
%appliedThunk = partial_apply [callee_guaranteed] [on_stack] %thunk(%noescapeClosure) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
746+
747+
%dependency = mark_dependence %appliedThunk : $@noescape @callee_guaranteed () -> (@out Int, @error any Error) on %noescapeClosure : $@noescape @callee_guaranteed () -> (Int, @error any Error)
748+
%generified = convert_function %dependency : $@noescape @callee_guaranteed () -> (@out Int, @error any Error) to $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>
749+
%test = function_ref @testClosureThunkNoEscapeThrowing : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error)
750+
strong_retain %generified : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>
751+
%out = alloc_stack $()
752+
try_apply %test(%out, %generified) : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error), normal bb1, error bb2
753+
754+
bb1(%ret : $()):
755+
dealloc_stack %out : $*()
756+
release_value %closure : $@callee_guaranteed () -> (Int, @error any Error)
757+
strong_release %noescapeClosure : $@noescape @callee_guaranteed () -> (Int, @error any Error)
758+
dealloc_stack %appliedThunk : $@noescape @callee_guaranteed () -> (@out Int, @error any Error)
759+
%empty = tuple ()
760+
return %empty : $()
761+
762+
bb2(%error : $any Error):
763+
dealloc_stack %out : $*()
764+
release_value %closure : $@callee_guaranteed () -> (Int, @error any Error)
765+
strong_release %noescapeClosure : $@noescape @callee_guaranteed () -> (Int, @error any Error)
766+
dealloc_stack %appliedThunk : $@noescape @callee_guaranteed () -> (@out Int, @error any Error)
767+
throw %error : $any Error
768+
}
769+
705770
// Currently not supported cases.
706771

707772
sil @testClosureThunk4 : $@convention(thin) (@owned @callee_guaranteed () -> @out Int) -> @out Int {

0 commit comments

Comments
 (0)