@@ -11,8 +11,12 @@ import Builtin
1111import Swift
1212
1313class B {
14+ @_hasStorage var next: B
1415}
1516
17+ struct Str {
18+ @_hasStorage var b: B
19+ }
1620
1721// CHECK-LABEL: sil @devirtualize_object
1822// CHECK: [[A:%[0-9]+]] = alloc_ref
@@ -21,7 +25,7 @@ class B {
2125// CHECK: [[D:%[0-9]+]] = function_ref @$s4test1BCfD
2226// CHECK-NEXT: apply [[D]]([[A]])
2327// CHECK-NEXT: dealloc_stack_ref [[A]]
24- // CHECK: return
28+ // CHECK: } // end sil function 'devirtualize_object'
2529sil @devirtualize_object : $@convention(thin) () -> () {
2630bb0:
2731 %1 = alloc_ref [stack] $B
3640// CHECK-NEXT: strong_release
3741// CHECK-NEXT: dealloc_ref
3842// CHECK: return
43+ // CHECK: } // end sil function 'dont_devirtualize_heap_allocated'
3944sil @dont_devirtualize_heap_allocated : $@convention(thin) () -> () {
4045bb0:
4146 %1 = alloc_ref $B
7277// CHECK-NEXT: strong_release
7378// CHECK-NEXT: dealloc_ref
7479// CHECK: return
80+ // CHECK: } // end sil function 'dont_devirtualize_wrong_release'
7581sil @dont_devirtualize_wrong_release : $@convention(thin) (@owned B) -> () {
7682bb0(%0 : $B):
7783 %1 = alloc_ref $B
@@ -88,7 +94,7 @@ bb0(%0 : $B):
8894// CHECK: [[F:%[0-9]+]] = function_ref @unknown_func
8995// CHECK-NEXT: apply [[F]]()
9096// CHECK-NEXT: dealloc_ref
91- // CHECK: return
97+ // CHECK: } // end sil function 'dont_devirtualize_unknown_release'
9298sil @dont_devirtualize_unknown_release : $@convention(thin) (@owned B) -> () {
9399bb0(%0 : $B):
94100 %1 = alloc_ref $B
@@ -107,7 +113,7 @@ bb0(%0 : $B):
107113// CHECK: [[D:%[0-9]+]] = function_ref @$s4test1BCfD
108114// CHECK-NEXT: apply [[D]]([[A]])
109115// CHECK-NEXT: dealloc_stack_ref [[A]]
110- // CHECK: return
116+ // CHECK: } // end sil function 'dont_crash_with_missing_release'
111117sil @dont_crash_with_missing_release : $@convention(thin) () -> () {
112118bb0:
113119 %1 = alloc_ref [stack] $B
@@ -119,42 +125,93 @@ bb0:
119125 return %r : $()
120126}
121127
128+ // CHECK-LABEL: sil @long_chain_from_alloc_to_release
129+ // CHECK: set_deallocating
130+ // CHECK-NOT: release_value
131+ // CHECK: } // end sil function 'long_chain_from_alloc_to_release'
132+ sil @long_chain_from_alloc_to_release : $@convention(thin) () -> () {
133+ bb0:
134+ %1 = alloc_ref [stack] $B
135+ %2 = struct $Str(%1 : $B)
136+ %3 = struct_extract %2 : $Str, #Str.b
137+ cond_br undef, bb1, bb2
138+
139+ bb1:
140+ br bb3(%3 : $B)
141+
142+ bb2:
143+ br bb3(%3 : $B)
144+
145+ bb3(%a : $B):
146+ %s = struct $Str (%a : $B)
147+ %i = integer_literal $Builtin.Int64, 0
148+ %t = tuple (%s : $Str, %i : $Builtin.Int64)
149+ %o = enum $Optional<(Str, Builtin.Int64)>, #Optional.some!enumelt, %t : $(Str, Builtin.Int64)
150+ release_value %o : $Optional<(Str, Builtin.Int64)>
151+ dealloc_stack_ref %1 : $B
152+ %r = tuple ()
153+ return %r : $()
154+ }
122155
123- sil @unknown_func : $@convention(thin) () -> ()
124-
125- // test.B.__deallocating_deinit
126- sil hidden @$s4test1BCfD : $@convention(method) (@owned B) -> () {
127- // %0 // users: %1, %3
128- bb0(%0 : $B):
129- debug_value %0 : $B, let, name "self" // id: %1
130- // function_ref test.B.deinit
131- %2 = function_ref @$s4test1BCfd : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject // user: %3
132- %3 = apply %2(%0) : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject // user: %4
133- %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $B // user: %5
134- dealloc_ref %4 : $B // id: %5
135- %6 = tuple () // user: %7
136- return %6 : $() // id: %7
156+ // CHECK-LABEL: sil @dont_devirtualize_double_release
157+ // CHECK-NOT: set_deallocating
158+ // CHECK: release_value
159+ // CHECK: } // end sil function 'dont_devirtualize_double_release'
160+ sil @dont_devirtualize_double_release : $@convention(thin) () -> () {
161+ bb0:
162+ %1 = alloc_ref [stack] $B
163+ %t = tuple (%1 : $B, %1 : $B)
164+ release_value %t : $(B, B)
165+ dealloc_stack_ref %1 : $B
166+ %r = tuple ()
167+ return %r : $()
137168}
138169
139- // test.B.deinit
140- sil hidden @$s4test1BCfd : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject {
141- // %0 // users: %1, %2
142- bb0(%0 : $B):
143- debug_value %0 : $B, let, name "self" // id: %1
144- %2 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject // user: %3
145- return %2 : $Builtin.NativeObject // id: %3
170+ // CHECK-LABEL: sil @dont_devirtualize_release_of_load
171+ // CHECK-NOT: set_deallocating
172+ // CHECK: strong_release
173+ // CHECK: } // end sil function 'dont_devirtualize_release_of_load'
174+ sil @dont_devirtualize_release_of_load : $@convention(thin) () -> () {
175+ bb0:
176+ %1 = alloc_ref [stack] $B
177+ %2 = ref_element_addr %1 : $B, #B.next
178+ %3 = load %2 : $*B
179+ strong_release %3 : $B
180+ dealloc_stack_ref %1 : $B
181+ %r = tuple ()
182+ return %r : $()
146183}
147184
148- // test.B.init () -> test.B
149- sil hidden @$s4test1BCACycfc : $@convention(method) (@owned B) -> @owned B {
150- // %0 // users: %1, %2
151- bb0(%0 : $B):
152- debug_value %0 : $B, let, name "self" // id: %1
153- return %0 : $B // id: %2
185+ // CHECK-LABEL: sil @dont_devirtualize_release_of_different_allocations
186+ // CHECK-NOT: set_deallocating
187+ // CHECK: strong_release
188+ // CHECK: } // end sil function 'dont_devirtualize_release_of_different_allocations'
189+ sil @dont_devirtualize_release_of_different_allocations : $@convention(thin) () -> () {
190+ bb0:
191+ %1 = alloc_ref [stack] $B
192+ %2 = alloc_ref [stack] $B
193+ cond_br undef, bb1, bb2
194+
195+ bb1:
196+ br bb3(%1 : $B)
197+
198+ bb2:
199+ br bb3(%2 : $B)
200+
201+ bb3(%a : $B):
202+ strong_release %a : $B
203+ dealloc_stack_ref %2 : $B
204+ dealloc_stack_ref %1 : $B
205+ %r = tuple ()
206+ return %r : $()
154207}
155208
209+
210+ sil @unknown_func : $@convention(thin) () -> ()
211+
212+ sil @$s4test1BCfD : $@convention(method) (@owned B) -> ()
213+
156214sil_vtable B {
157- #B.deinit!deallocator: @$s4test1BCfD // test.B.__deallocating_deinit
158- #B.init!initializer: @$s4test1BCACycfc // test.B.init () -> test.B
215+ #B.deinit!deallocator: @$s4test1BCfD
159216}
160217
0 commit comments