@@ -31,6 +31,17 @@ struct Wrapper<T>: ~Copyable {
3131 var t: T
3232}
3333
34+ struct NonCopyableForwardingStruct : ~Copyable {
35+ var some: Int
36+ deinit
37+ }
38+
39+ enum NonCopyableForwardingEnum : ~Copyable {
40+ case some(Int)
41+ case nothing
42+ deinit
43+ }
44+
3445sil @getWrappedValue : $@convention(thin) <T> (@in_guaranteed Wrapper<T>) -> @out T
3546
3647// Test that a release_value is not removed for a struct-with-deinit.
@@ -110,3 +121,51 @@ bb0(%0 : @owned $S):
110121 %64 = tuple ()
111122 return %64 : $()
112123}
124+
125+ // Test a "dead" non-Copyable struct-with-deinit that forwards a
126+ // single trivial value. The destroy_value cannot be eliminated
127+ // without first devirtualizing the deinit.
128+ //
129+ // CHECK-LABEL: sil [ossa] @testNonCopyableForwardingStructDeinit : $@convention(thin) (Int) -> () {
130+ // CHECK: [[STRUCT:%[0-9]+]] = struct $NonCopyableForwardingStruct (%0 : $Int)
131+ // CHECK: destroy_value [[STRUCT]]
132+ // CHECK-LABEL: } // end sil function 'testNonCopyableForwardingStructDeinit'
133+ sil [ossa] @testNonCopyableForwardingStructDeinit : $@convention(thin) (Int) -> () {
134+ bb0(%0: $Int):
135+ %1 = struct $NonCopyableForwardingStruct(%0 : $Int)
136+ destroy_value %1
137+ %13 = tuple ()
138+ return %13
139+ }
140+
141+ // Test a "dead" non-Copyable enum-with-deinit that forwards a single
142+ // trivial value. The destroy_value cannot be eliminated without first
143+ // devirtualizing the deinit.
144+ //
145+ // CHECK-LABEL: sil [ossa] @testNonCopyableForwardingEnumDeinit : $@convention(thin) (Int) -> () {
146+ // CHECK: [[ENUM:%[0-9]+]] = enum $NonCopyableForwardingEnum, #NonCopyableForwardingEnum.some!enumelt, %0
147+ // CHECK: destroy_value [[ENUM]]
148+ // CHECK-LABEL: } // end sil function 'testNonCopyableForwardingEnumDeinit'
149+ sil [ossa] @testNonCopyableForwardingEnumDeinit : $@convention(thin) (Int) -> () {
150+ bb0(%0 : $Int):
151+ %1 = enum $NonCopyableForwardingEnum, #NonCopyableForwardingEnum.some!enumelt, %0
152+ destroy_value %1
153+ %13 = tuple ()
154+ return %13
155+ }
156+
157+ // Test a "dead" non-Copyable enum-with-deinit and an empty case. The
158+ // destroy_value cannot be eliminated without first devirtualizing the
159+ // deinit.
160+ //
161+ // CHECK-LABEL: sil [ossa] @testNonCopyableEmptyEnumDeinit : $@convention(thin) () -> () {
162+ // CHECK: [[ENUM:%[0-9]+]] = enum $NonCopyableForwardingEnum, #NonCopyableForwardingEnum.nothing
163+ // CHECK: destroy_value [[ENUM]]
164+ // CHECK-LABEL: } // end sil function 'testNonCopyableEmptyEnumDeinit'
165+ sil [ossa] @testNonCopyableEmptyEnumDeinit : $@convention(thin) () -> () {
166+ bb0:
167+ %0 = enum $NonCopyableForwardingEnum, #NonCopyableForwardingEnum.nothing
168+ destroy_value %0
169+ %13 = tuple ()
170+ return %13
171+ }
0 commit comments