@@ -875,6 +875,7 @@ bb0(%instance : @owned $C):
875875// CHECK-NOT: destroy_value
876876// CHECK-LABEL: } // end sil function 'dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_consuming_block'
877877sil [ossa] @dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_consuming_block : $@convention(thin) () -> () {
878+ bb0:
878879 %instance = apply undef() : $@convention(thin) () -> @owned C
879880 %addr = alloc_stack [lexical] $C, var
880881 %access = begin_access [static] [modify] %addr : $*C
@@ -885,3 +886,52 @@ sil [ossa] @dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_co
885886 %retval = tuple()
886887 return %retval : $()
887888}
889+
890+ sil @closureGetter : $@convention(thin) () -> @owned Optional<@Sendable @callee_guaranteed () -> ()>
891+
892+ // This pattern is produced by SILGen doUncheckedConversion.
893+ // rdar://100527903 (Overrelease of optional closure when using shorthand syntax)
894+ //
895+ // Copy propagation cannot handle a PointerEscape.
896+ //
897+ // CHECK-LABEL: sil hidden [ossa] @testBitwiseClosureEscape : $@convention(thin) () -> () {
898+ // CHECK: [[V:%.*]] = apply %0() : $@convention(thin) () -> @owned Optional<@Sendable @callee_guaranteed () -> ()>
899+ // CHECK: [[CP1:%.*]] = copy_value [[V]] : $Optional<@Sendable @callee_guaranteed () -> ()>
900+ // CHECK: destroy_value [[V]] : $Optional<@Sendable @callee_guaranteed () -> ()>
901+ // CHECK: [[CAST:%.*]] = unchecked_bitwise_cast [[CP1]] : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
902+ // CHECK-NEXT: [[CASTCP:%.*]] = copy_value [[CAST]] : $Optional<@callee_guaranteed () -> ()>
903+ // CHECK: store [[CASTCP]] to [init]
904+ // CHECK: destroy_value [[CP1]] : $Optional<@Sendable @callee_guaranteed () -> ()>
905+ // CHECK-LABEL: } // end sil function 'testBitwiseClosureEscape'
906+ sil hidden [ossa] @testBitwiseClosureEscape : $@convention(thin) () -> () {
907+ bb0:
908+ %2 = function_ref @closureGetter : $@convention(thin) () -> @owned Optional<@Sendable @callee_guaranteed () -> ()>
909+ %3 = apply %2() : $@convention(thin) () -> @owned Optional<@Sendable @callee_guaranteed () -> ()>
910+ %13 = copy_value %3 : $Optional<@Sendable @callee_guaranteed () -> ()>
911+ %14 = alloc_stack $Optional<@callee_guaranteed () -> ()>
912+ destroy_value %3 : $Optional<@Sendable @callee_guaranteed () -> ()>
913+ %17 = unchecked_bitwise_cast %13 : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
914+ %18 = copy_value %17 : $Optional<@callee_guaranteed () -> ()>
915+ store %18 to [init] %14 : $*Optional<@callee_guaranteed () -> ()>
916+ destroy_addr %14 : $*Optional<@callee_guaranteed () -> ()>
917+ destroy_value %13 : $Optional<@Sendable @callee_guaranteed () -> ()>
918+ dealloc_stack %14 : $*Optional<@callee_guaranteed () -> ()>
919+ %99 = tuple ()
920+ return %99 : $()
921+ }
922+
923+ // Lexical destroy hoisting cannot handle a PointerEscape.
924+ //
925+ // CHECK-LABEL: sil [ossa] @testNoLexicalHoistEscape : $@convention(thin) (@owned Optional<@Sendable @callee_guaranteed () -> ()>) -> @owned Optional<@callee_guaranteed () -> ()> {
926+ // CHECK: bb0(%0 : @owned $Optional<@Sendable @callee_guaranteed () -> ()>):
927+ // CHECK: [[CAST:%.*]] = unchecked_bitwise_cast %0 : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
928+ // CHECK: [[COPY:%.*]] = copy_value [[CAST]] : $Optional<@callee_guaranteed () -> ()>
929+ // CHECK: destroy_value %0 : $Optional<@Sendable @callee_guaranteed () -> ()>
930+ // CHECK-LABEL: } // end sil function 'testNoLexicalHoistEscape'
931+ sil [ossa] @testNoLexicalHoistEscape : $@convention(thin) (@owned Optional<@Sendable @callee_guaranteed () -> ()>) -> @owned Optional<@callee_guaranteed () -> ()> {
932+ bb0(%0 : @owned $Optional<@Sendable @callee_guaranteed () -> ()>):
933+ %cast = unchecked_bitwise_cast %0 : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
934+ %copy = copy_value %cast : $Optional<@callee_guaranteed () -> ()>
935+ destroy_value %0 : $Optional<@Sendable @callee_guaranteed () -> ()>
936+ return %copy : $Optional<@callee_guaranteed () -> ()>
937+ }
0 commit comments