@@ -2901,3 +2901,44 @@ bb6(%14 : $foo):
2901
2901
%16 = tuple ()
2902
2902
return %16 : $()
2903
2903
}
2904
+
2905
+ protocol Q {}
2906
+
2907
+ class IsQ : Q {}
2908
+
2909
+ // checked_cast_br take_* should be replaced by a destroy in case it ever
2910
+ // converts a managed object to an unmanaged value. Currently this doesn't
2911
+ // happen at the language level because bridge (NSNumber->Int) casts aren't
2912
+ // represented with checked_cast_br.
2913
+ // ---
2914
+ // CHECK-LABEL: sil @test_dead_checked_cast_br : $@convention(thin) (@in IsQ) -> () {
2915
+ // CHECK: bb0(%0 : $*IsQ):
2916
+ // CHECK: [[Q:%.*]] = alloc_stack $Q
2917
+ // CHECK: destroy_addr %0 : $*IsQ
2918
+ // CHECK: dealloc_stack [[Q]] : $*Q
2919
+ // CHECK: [[R:%.*]] = tuple ()
2920
+ // CHECK: return [[R]] : $()
2921
+ // CHECK-LABEL: } // end sil function 'test_dead_checked_cast_br'
2922
+ sil @test_dead_checked_cast_br : $@convention(thin) (@in IsQ) -> () {
2923
+ bb0(%0 : $*IsQ):
2924
+ %p = alloc_stack $Q
2925
+ checked_cast_addr_br take_always IsQ in %0 : $*IsQ to Q in %p : $*Q, bb1, bb3
2926
+
2927
+ bb1:
2928
+ %m1 = integer_literal $Builtin.Int1, -1
2929
+ br bb2(%m1 : $Builtin.Int1)
2930
+
2931
+ bb2(%5 : $Builtin.Int1):
2932
+ // To avoid violating ownership, Q needs to be destroyed here. However, that
2933
+ // would create a use of the checked_cast, defeating the test. In theory, Q
2934
+ // could be some unmananged type with no destroy, but we don't have a way to
2935
+ // express that in the type system, and bridged casts don't yet go through
2936
+ // this optimization path.
2937
+ dealloc_stack %p : $*Q
2938
+ %r = tuple ()
2939
+ return %r : $()
2940
+
2941
+ bb3:
2942
+ %z = integer_literal $Builtin.Int1, 0
2943
+ br bb2(%z : $Builtin.Int1)
2944
+ }
0 commit comments