@@ -116,6 +116,13 @@ struct NativeObjectWrapper {
116116
117117sil @owned_user_object_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
118118
119+ class X {}
120+ struct S {}
121+
122+ sil @getX : $@convention(thin) () -> @owned X
123+ sil @getS : $@convention(thin) (@owned X) -> @out S
124+ sil @loadWeakX_from : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
125+
119126///////////
120127// Tests //
121128///////////
@@ -923,3 +930,51 @@ bb0:
923930 destroy_value %0 : ${ var Bool }
924931 return %11 : $Bool
925932}
933+
934+ // Don't do this optimization:
935+ // Eliminate copy of lexical value which ends after lifetime of copy IF there
936+ // may be deinit barriers between the final consume and the copy.
937+ //
938+ // CHECK-LABEL: sil [ossa] @testDestroyedLexicalValue : {{.*}} {
939+ // CHECK: [[GET:%[^,]+]] = function_ref @getX
940+ // CHECK: [[X:%[^,]+]] = apply [[GET]]()
941+ // CHECK: [[MX:%[^,]+]] = move_value [lexical] [[X]]
942+ // CHECK: destroy_value [[MX]] : $X
943+ // CHECK-LABEL: } // end sil function 'testDestroyedLexicalValue'
944+ sil [ossa] @testDestroyedLexicalValue : $@convention(thin) () -> @owned FakeOptional<X> {
945+ bb0:
946+ %getX = function_ref @getX : $@convention(thin) () -> @owned X
947+ %x = apply %getX() : $@convention(thin) () -> @owned X
948+ %mx = move_value [lexical] %x : $X
949+ %a = alloc_stack [lexical] $S, let, name "s"
950+ %c = copy_value %mx : $X
951+ %getS = function_ref @getS : $@convention(thin) (@owned X) -> @out S
952+ %s = apply %getS(%a, %c) : $@convention(thin) (@owned X) -> @out S
953+ %loadWeakX_from = function_ref @loadWeakX_from : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
954+ %o = apply %loadWeakX_from(%a) : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
955+ // ^^^^^ Deinit barrier
956+ destroy_addr %a : $*S
957+ dealloc_stack %a : $*S
958+ destroy_value %mx : $X
959+ return %o : $FakeOptional<X>
960+ }
961+
962+ // CHECK-LABEL: sil [ossa] @testDestroyedLexicalValueNoBarriers : {{.*}} {
963+ // CHECK-NOT: destroy_value
964+ // CHECK-LABEL: } // end sil function 'testDestroyedLexicalValueNoBarriers'
965+ sil [ossa] @testDestroyedLexicalValueNoBarriers : $@convention(thin) () -> () {
966+ bb0:
967+ %getX = function_ref @getX : $@convention(thin) () -> @owned X
968+ %x = apply %getX() : $@convention(thin) () -> @owned X
969+ %mx = move_value [lexical] %x : $X
970+ %a = alloc_stack [lexical] $S, let, name "s"
971+ %c = copy_value %mx : $X
972+ %getS = function_ref @getS : $@convention(thin) (@owned X) -> @out S
973+ %s = apply %getS(%a, %c) : $@convention(thin) (@owned X) -> @out S
974+ destroy_addr %a : $*S
975+ dealloc_stack %a : $*S
976+ destroy_value %mx : $X
977+ %r = tuple ()
978+ return %r : $()
979+ }
980+
0 commit comments