1- // RUN: %target-sil-opt -opt-mode=none -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB
2- // RUN: %target-sil-opt -opt-mode=speed -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT
1+ // RUN: %target-sil-opt -opt-mode=none -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB --check-prefix=CHECK-DEB
2+ // RUN: %target-sil-opt -opt-mode=speed -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT --check-prefix=CHECK-OPT
33//
44// TODO: migrate the remaining tests from destroy_hoisting.sil.
55
@@ -188,9 +188,9 @@ bb0(%0 : $*T):
188188// bb2. Dead debug instructions then need to be deleted before the
189189// destroy can be merged back onto bb3.
190190//
191- // CHECK-LABEL: sil hidden [ossa] @destroyDiamond : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
191+ // CHECK-LABEL: sil hidden [ossa] @destroyDiamond_lexical : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
192192// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int1):
193- // CHECK: [[ALLOC:%.*]] = alloc_stack $T, var, name "t"
193+ // CHECK: [[ALLOC:%.*]] = alloc_stack [lexical] $T, var, name "t"
194194// CHECK-NOT: destroy
195195// CHECK: cond_br %{{.*}}, bb1, bb2
196196// CHECK: bb1:
@@ -199,13 +199,60 @@ bb0(%0 : $*T):
199199// CHECK: br bb3
200200// CHECK: bb2:
201201// CHECKDEB: debug_value [[ALLOC]] : $*T, let, name "t"
202- // CHECK-NOT: debug_val [[ALLOC]]
202+ // CHECK-NOT: debug_value [[ALLOC]]
203203// CHECK: br bb3
204204// CHECK: bb3:
205205// CHECK: destroy_addr [[ALLOC]] : $*T
206206// CHECK: return
207- // CHECK-LABEL: } // end sil function 'destroyDiamond'
208- sil hidden [ossa] @destroyDiamond : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
207+ // CHECK-LABEL: } // end sil function 'destroyDiamond_lexical'
208+ sil hidden [ossa] @destroyDiamond_lexical : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
209+ bb0(%0 : $*T, %1 : $Builtin.Int1):
210+ debug_value %0 : $*T, let, name "arg", argno 1, expr op_deref
211+ debug_value %1 : $Builtin.Int1, let, name "z", argno 2
212+ %4 = alloc_stack [lexical] $T, var, name "t"
213+ copy_addr %0 to [initialization] %4 : $*T
214+ cond_br %1, bb1, bb2
215+
216+ bb1:
217+ %8 = function_ref @unknown : $@convention(thin) () -> ()
218+ %9 = apply %8() : $@convention(thin) () -> ()
219+ br bb3
220+
221+ bb2:
222+ debug_value %4 : $*T, let, name "t"
223+ br bb3
224+
225+ bb3:
226+ destroy_addr %4 : $*T
227+ dealloc_stack %4 : $*T
228+ %14 = tuple ()
229+ return %14 : $()
230+ }
231+
232+ // In contrast to the lexical variant (destroyDiamond_lexical), the destroy can
233+ // be hoisted over the unknown apply. In the debug case, it can't be hoisted
234+ // over the debug_value. In the optimized case, it can be hoisted up to the
235+ // entry block.
236+ //
237+ // CHECK-LABEL: sil hidden [ossa] @destroyDiamond_nonlexical : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
238+ // CHECK: {{bb[0-9]+}}
239+ // CHECK: [[ALLOC:%.*]] = alloc_stack
240+ // CHECK-OPT: destroy_addr [[ALLOC]]
241+ // CHECK: cond_br %{{.*}}, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]]
242+ // CHECK: [[LEFT]]:
243+ // CHECK-DBG: destroy_addr [[ALLOC]]
244+ // CHECK: apply %{{.*}}()
245+ // CHECK-NOT: destroy_addr
246+ // CHECK: br [[EXIT:bb[0-9]+]]
247+ // CHECK: [[RIGHT]]:
248+ // CHECK-OPT-NOT: debug_value [[ALLOC]]
249+ // CHECK-DBG: debug_value [[ALLOC]]
250+ // CHECK-DBG: destroy_addr [[ALLOC]]
251+ // CHECK: br [[EXIT]]
252+ // CHECK: [[EXIT]]:
253+ // CHECK: return
254+ // CHECK-LABEL: } // end sil function 'destroyDiamond_nonlexical'
255+ sil hidden [ossa] @destroyDiamond_nonlexical : $@convention(thin) <T> (@in_guaranteed T, Builtin.Int1) -> () {
209256bb0(%0 : $*T, %1 : $Builtin.Int1):
210257 debug_value %0 : $*T, let, name "arg", argno 1, expr op_deref
211258 debug_value %1 : $Builtin.Int1, let, name "z", argno 2
229276 return %14 : $()
230277}
231278
232- // CHECK-LABEL: sil hidden [ossa] @destroyLoop : $@convention(thin) <T> (@in_guaranteed T) -> () {
233- // CHECK: [[ALLOC:%.*]] = alloc_stack $T, var, name "t"
279+ // CHECK-LABEL: sil hidden [ossa] @destroyLoop_lexical : $@convention(thin) <T> (@in_guaranteed T) -> () {
280+ // CHECK: [[ALLOC:%.*]] = alloc_stack [lexical] $T, var, name "t"
234281// CHECK: br bb1
235282// CHECK: bb1:
236283// CHECK: apply %{{.*}}() : $@convention(thin) () -> Builtin.Int1
@@ -242,8 +289,45 @@ bb3:
242289// CHECKOPT-NOT: debug_value
243290// CHECK: destroy_addr [[ALLOC]] : $*T
244291// CHECK: dealloc_stack [[ALLOC]] : $*T
245- // CHECK-LABEL: } // end sil function 'destroyLoop'
246- sil hidden [ossa] @destroyLoop : $@convention(thin) <T> (@in_guaranteed T) -> () {
292+ // CHECK-LABEL: } // end sil function 'destroyLoop_lexical'
293+ sil hidden [ossa] @destroyLoop_lexical : $@convention(thin) <T> (@in_guaranteed T) -> () {
294+ bb0(%0 : $*T):
295+ %a = alloc_stack [lexical] $T, var, name "t"
296+ copy_addr %0 to [initialization] %a : $*T
297+ br bb1
298+
299+ bb1:
300+ %f = function_ref @f_bool : $@convention(thin) () -> Builtin.Int1
301+ %c = apply %f() : $@convention(thin) () -> Builtin.Int1
302+ cond_br %c, bb2, bb3
303+
304+ bb2:
305+ br bb1
306+
307+ bb3:
308+ debug_value %a : $*T, let, name "t"
309+ destroy_addr %a : $*T
310+ dealloc_stack %a : $*T
311+ %16 = tuple ()
312+ return %16 : $()
313+ }
314+
315+ // CHECK-LABEL: sil hidden [ossa] @destroyLoop_nonlexical : $@convention(thin) <T> (@in_guaranteed T) -> () {
316+ // CHECK: [[ALLOC:%.*]] = alloc_stack $T, var, name "t"
317+ // CHECK-OPT: destroy_addr [[ALLOC]]
318+ // CHECK: br bb1
319+ // CHECK: bb1:
320+ // CHECK: apply %{{.*}}() : $@convention(thin) () -> Builtin.Int1
321+ // CHECK-NEXT: cond_br %{{.*}}, bb2, bb3
322+ // CHECK: bb2:
323+ // CHECK-NEXT: br bb1
324+ // CHECK: bb3:
325+ // CHECK-DEB: debug_value [[ALLOC]] : $*T, let, name "t"
326+ // CHECK-OPT-NOT: debug_value
327+ // CHECK-DEB: destroy_addr [[ALLOC]] : $*T
328+ // CHECK: dealloc_stack [[ALLOC]] : $*T
329+ // CHECK-LABEL: } // end sil function 'destroyLoop_nonlexical'
330+ sil hidden [ossa] @destroyLoop_nonlexical : $@convention(thin) <T> (@in_guaranteed T) -> () {
247331bb0(%0 : $*T):
248332 %a = alloc_stack $T, var, name "t"
249333 copy_addr %0 to [initialization] %a : $*T
@@ -352,11 +436,34 @@ exit:
352436// unreachable-at-begin block is added to the worklist but its predecessor
353437// isn't discovered.
354438//
355- // CHECK-LABEL: sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin : {{.*}} {
439+ // CHECK-LABEL: sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin_lexical : {{.*}} {
356440// CHECK: apply undef
357441// CHECK-NEXT: destroy_addr
358- // CHECK-LABEL: } // end sil function 'undiscovered_predecessor_of_unreachable_at_begin'
359- sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin : $@convention(thin) (@owned S) -> () {
442+ // CHECK-LABEL: } // end sil function 'undiscovered_predecessor_of_unreachable_at_begin_lexical'
443+ sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin_lexical : $@convention(thin) (@owned S) -> () {
444+ entry(%instance : @owned $S):
445+ %addr = alloc_stack [lexical] $S
446+ store %instance to [init] %addr : $*S
447+ br applier
448+
449+ applier:
450+ apply undef() : $@convention(thin) () -> ()
451+ br good
452+
453+ good:
454+ destroy_addr %addr : $*S
455+ dealloc_stack %addr : $*S
456+ %retval = tuple ()
457+ return %retval : $()
458+ }
459+
460+ // In contrast to the lexical case (undiscovered_predecessor_of_unreachable_at_begin_lexical)
461+ //
462+ // CHECK-LABEL: sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin_nonlexical : {{.*}} {
463+ // CHECK: store
464+ // CHECK-NEXT: destroy_addr
465+ // CHECK-LABEL: } // end sil function 'undiscovered_predecessor_of_unreachable_at_begin_nonlexical'
466+ sil [ossa] @undiscovered_predecessor_of_unreachable_at_begin_nonlexical : $@convention(thin) (@owned S) -> () {
360467entry(%instance : @owned $S):
361468 %addr = alloc_stack $S
362469 store %instance to [init] %addr : $*S
@@ -545,10 +652,32 @@ entry(%instance : @owned $S):
545652
546653// Don't fold when there's a deinit barrier in the way.
547654//
548- // CHECK-LABEL: sil [ossa] @nofold_scoped_load_barrier : {{.*}} {
655+ // CHECK-LABEL: sil [ossa] @nofold_scoped_load_barrier_lexical : {{.*}} {
549656// CHECK: load [copy]
550- // CHECK-LABEL: // end sil function 'nofold_scoped_load_barrier'
551- sil [ossa] @nofold_scoped_load_barrier : $@convention(thin) (@owned S) -> (@owned S) {
657+ // CHECK-LABEL: // end sil function 'nofold_scoped_load_barrier_lexical'
658+ sil [ossa] @nofold_scoped_load_barrier_lexical : $@convention(thin) (@owned S) -> (@owned S) {
659+ entry(%instance : @owned $S):
660+ %addr = alloc_stack [lexical] $S
661+ %store_scope = begin_access [modify] [static] %addr : $*S
662+ store %instance to [init] %store_scope : $*S
663+ end_access %store_scope : $*S
664+ %load_scope = begin_access [read] [static] %addr : $*S
665+ %value = load [copy] %load_scope : $*S
666+ %unknown = function_ref @unknown : $@convention(thin) () -> ()
667+ apply %unknown() : $@convention(thin) () -> ()
668+ end_access %load_scope : $*S
669+ destroy_addr %addr : $*S
670+ dealloc_stack %addr : $*S
671+ return %value : $S
672+ }
673+
674+ // Fold when there's a deinit barrier in the way if the alloc_stack is
675+ // non-lexical.
676+ //
677+ // CHECK-LABEL: sil [ossa] @nofold_scoped_load_barrier_nonlexical : {{.*}} {
678+ // CHECK: load [take]
679+ // CHECK-LABEL: // end sil function 'nofold_scoped_load_barrier_nonlexical'
680+ sil [ossa] @nofold_scoped_load_barrier_nonlexical : $@convention(thin) (@owned S) -> (@owned S) {
552681entry(%instance : @owned $S):
553682 %addr = alloc_stack $S
554683 %store_scope = begin_access [modify] [static] %addr : $*S
@@ -647,8 +776,8 @@ entry(%instance : @owned $S):
647776sil [ossa] @nofold_unrelated_scoped_load_copy : $@convention(thin) (@owned X) -> (@owned X) {
648777entry(%instance : @owned $X):
649778 %copy = copy_value %instance : $X
650- %addr_1 = alloc_stack $X
651- %addr_2 = alloc_stack $X
779+ %addr_1 = alloc_stack [lexical] $X
780+ %addr_2 = alloc_stack [lexical] $X
652781 store %instance to [init] %addr_1 : $*X
653782 store %copy to [init] %addr_2 : $*X
654783
0 commit comments