@@ -196,3 +196,111 @@ exit:
196196 destroy_value %value : $FakeOptional<X>
197197 return %retval : $()
198198}
199+
200+ // Ensure that an adjacent reborrow phi being reborrowed doesn't get counted as
201+ // a non-lifetime ending use and extend liveness beyond the instruction where
202+ // the reborrow occurs.
203+ // CHECK-LABEL: sil [ossa] @reborrow_adjacent_to_consume_doesnt_extend_lifetime : {{.*}} {
204+ // CHECK: bb1([[REBORROW:%[^,]+]] : @guaranteed $X, [[VALUE:%[^,]+]] :
205+ // CHECK: {{bb[0-9]+}}:
206+ // CHECK: end_borrow [[REBORROW]]
207+ // CHECK: destroy_value [[VALUE]]
208+ // CHECK-LABEL: } // end sil function 'reborrow_adjacent_to_consume_doesnt_extend_lifetime'
209+ sil [ossa] @reborrow_adjacent_to_consume_doesnt_extend_lifetime : $@convention(thin) (@owned X) -> () {
210+ bb0(%0 : @owned $X):
211+ %1 = begin_borrow %0 : $X
212+ br bb1(%1 : $X, %0 : $X)
213+
214+ bb1(%3 : @guaranteed $X, %4 : @owned $X):
215+ cond_br undef, bb2, bb10
216+
217+ bb2:
218+ br bb3
219+
220+ bb3:
221+ br bb4(%3 : $X, %4 : $X)
222+
223+ bb4(%8 : @guaranteed $X, %9 : @owned $X):
224+ cond_br undef, bb5, bb8
225+
226+ bb5:
227+ br bb6
228+
229+ bb6:
230+ br bb7
231+
232+ bb7:
233+ %13 = function_ref @getX : $@convention(thin) () -> @owned X
234+ %14 = apply %13() : $@convention(thin) () -> @owned X
235+ end_borrow %8 : $X
236+ destroy_value %9 : $X
237+ %17 = begin_borrow %14 : $X
238+ br bb4(%17 : $X, %14 : $X)
239+
240+ bb8:
241+ br bb9
242+
243+ bb9:
244+ br bb1(%8 : $X, %9 : $X)
245+
246+ bb10:
247+ // TODO: Remove the copy once it isn't necessary to trigger canonicalization.
248+ %bogus = copy_value %4 : $X
249+ destroy_value %bogus : $X
250+ %23 = tuple ()
251+ end_borrow %3 : $X
252+ destroy_value %4 : $X
253+ return %23 : $()
254+ }
255+
256+ // CHECK-LABEL: sil [ossa] @nohoist_destroy_over_endborrow_nonadjacent_reborrow : {{.*}} {
257+ // CHECK: end_borrow {{%[^,]+}}
258+ // CHECK: destroy_value {{%[^,]+}}
259+ // CHECK-LABEL: } // end sil function 'nohoist_destroy_over_endborrow_nonadjacent_reborrow'
260+ sil [ossa] @nohoist_destroy_over_endborrow_nonadjacent_reborrow : $@convention(thin) (@owned X) -> () {
261+ entry(%value_1 : @owned $X):
262+ %lifetime_1 = begin_borrow %value_1 : $X
263+ br consume_and_reborrow(%lifetime_1 : $X, %value_1 : $X)
264+
265+ consume_and_reborrow(%lifetime_2 : @guaranteed $X, %value_2 : @owned $X):
266+ br reborrow_only(%lifetime_2 : $X)
267+
268+ reborrow_only(%lifetime_3 : @guaranteed $X):
269+ br exit
270+
271+ exit:
272+ %bogus = copy_value %value_2 : $X
273+ destroy_value %bogus : $X
274+ %retval = tuple ()
275+ end_borrow %lifetime_3 : $X
276+ destroy_value %value_2 : $X
277+ return %retval : $()
278+ }
279+
280+ // CHECK-LABEL: sil [ossa] @nohoist_destroy_over_endborrow_nonadjacent_reborrow_2 : {{.*}} {
281+ // CHECK: end_borrow {{%[^,]+}}
282+ // CHECK: destroy_value {{%[^,]+}}
283+ // CHECK-LABEL: } // end sil function 'nohoist_destroy_over_endborrow_nonadjacent_reborrow_2'
284+ sil [ossa] @nohoist_destroy_over_endborrow_nonadjacent_reborrow_2 : $@convention(thin) (@owned X) -> () {
285+ entry(%value_1 : @owned $X):
286+ %lifetime_1 = begin_borrow %value_1 : $X
287+ br consume_and_reborrow(%lifetime_1 : $X, %value_1 : $X)
288+
289+ consume_and_reborrow(%lifetime_2 : @guaranteed $X, %value_2 : @owned $X):
290+ br reborrow_only_1(%lifetime_2 : $X)
291+
292+ reborrow_only_1(%lifetime_3 : @guaranteed $X):
293+ br reborrow_only_2(%lifetime_3 : $X)
294+
295+ reborrow_only_2(%lifetime_4 : @guaranteed $X):
296+ br exit
297+
298+ exit:
299+ %bogus = copy_value %value_2 : $X
300+ destroy_value %bogus : $X
301+ %retval = tuple ()
302+ end_borrow %lifetime_4 : $X
303+ destroy_value %value_2 : $X
304+ return %retval : $()
305+ }
306+
0 commit comments