1
+ // RUN: %target-swift-emit-silgen %s | %FileCheck %s
2
+
3
+ class Node < A, B> {
4
+ var next : Node < A , B > ?
5
+ }
6
+
7
+ // CHECK: sil hidden [ossa] @$s31deinit_recursive_linear_generic4NodeCfd : $@convention(method) <A, B> (@guaranteed Node<A, B>) -> @owned Builtin.NativeObject {
8
+ // CHECK: [[SELF:%.*]] "self"
9
+ // CHECK: bb0([[SELF]] : @guaranteed $Node<A, B>):
10
+ // CHECK: [[NIL:%.*]] = enum $Optional<Node<A, B>>, #Optional.none!enumelt
11
+ // CHECK: [[SELF_NEXT:%.*]] = ref_element_addr [[SELF]] : $Node<A, B>, #Node.next
12
+ // CHECK: [[ITER:%.*]] = alloc_stack $Optional<Node<A, B>>
13
+ // CHECK: [[SELF_NEXT_ACCESS:%.*]] = begin_access [modify] [static] [[SELF_NEXT]] : $*Optional<Node<A, B>>
14
+ // CHECK: [[SELF_NEXT_COPY:%.*]] = load [copy] [[SELF_NEXT_ACCESS]] : $*Optional<Node<A, B>>
15
+ // CHECK: store [[NIL]] to [assign] [[SELF_NEXT_ACCESS]] : $*Optional<Node<A, B>>
16
+ // CHECK: end_access [[SELF_NEXT_ACCESS]] : $*Optional<Node<A, B>>
17
+ // CHECK: store [[SELF_NEXT_COPY]] to [init] [[ITER]] : $*Optional<Node<A, B>>
18
+ // CHECK: br [[LOOPBB:bb.*]] //
19
+
20
+ // CHECK: [[LOOPBB]]:
21
+ // CHECK: [[ITER_ADDR:%.*]] = load [copy] [[ITER]] : $*Optional<Node<A, B>>
22
+ // CHECK: [[ITER_COPY:%.*]] = copy_value [[ITER_ADDR]] : $Optional<Node<A, B>>
23
+ // CHECK: [[ITER_COPY_ADDR:%.*]] = alloc_stack $Optional<Node<A, B>>
24
+ // CHECK: store [[ITER_COPY]] to [init] [[ITER_COPY_ADDR]] : $*Optional<Node<A, B>>
25
+ // CHECK: destroy_value [[ITER_ADDR]] : $Optional<Node<A, B>>
26
+ // CHECK: switch_enum_addr [[ITER_COPY_ADDR]] : $*Optional<Node<A, B>>, case #Optional.some!enumelt: [[IS_SOME_BB:bb.*]], case #Optional.none!enumelt: [[IS_NONE_BB:bb[0-9]+]]
27
+
28
+ // CHECK: [[IS_SOME_BB]]:
29
+ // CHECK: destroy_addr [[ITER_COPY_ADDR]] : $*Optional<Node<A, B>>
30
+ // CHECK: dealloc_stack [[ITER_COPY_ADDR]] : $*Optional<Node<A, B>>
31
+ // CHECK: [[IS_UNIQUE:%.*]] = is_unique [[ITER]] : $*Optional<Node<A, B>>
32
+ // CHECK: cond_br [[IS_UNIQUE]], [[IS_UNIQUE_BB:bb.*]], [[NOT_UNIQUE_BB:bb[0-9]*]]
33
+
34
+ // CHECK: [[IS_UNIQUE_BB]]:
35
+ // CHECK: [[ITER_ADDR:%.*]] = load [copy] [[ITER]] : $*Optional<Node<A, B>>
36
+ // CHECK: [[ITER_BORROW:%.*]] = begin_borrow [[ITER_ADDR]] : $Optional<Node<A, B>>
37
+ // CHECK: [[ITER_UNWRAPPED:%.*]] = unchecked_enum_data [[ITER_BORROW]] : $Optional<Node<A, B>>, #Optional.some!enumelt
38
+ // CHECK: [[NEXT_ADDR:%.*]] = ref_element_addr [[ITER_UNWRAPPED]] : $Node<A, B>, #Node.next
39
+ // CHECK: [[NEXT_ADDR_ACCESS:%.*]] = begin_access [read] [static] [[NEXT_ADDR]] : $*Optional<Node<A, B>>
40
+ // CHECK: [[NEXT_COPY:%.*]] = load [copy] [[NEXT_ADDR_ACCESS]] : $*Optional<Node<A, B>>
41
+ // CHECK: end_access [[NEXT_ADDR_ACCESS]] : $*Optional<Node<A, B>>
42
+ // CHECK: store [[NEXT_COPY]] to [assign] [[ITER]] : $*Optional<Node<A, B>>
43
+ // CHECK: end_borrow [[ITER_BORROW]] : $Optional<Node<A, B>>
44
+ // CHECK: destroy_value [[ITER_ADDR]] : $Optional<Node<A, B>>
45
+ // CHECK: br [[LOOPBB]]
46
+
47
+ // CHECK: [[NOT_UNIQUE_BB]]:
48
+ // CHECK: br bb6
49
+
50
+ // CHECK: [[IS_NONE_BB]]:
51
+ // CHECK: dealloc_stack [[ITER_COPY_ADDR]] : $*Optional<Node<A, B>>
52
+ // CHECK: br [[CLEAN_BB:bb[0-9]+]]
53
+
54
+ // CHECK: [[CLEAN_BB]]:
55
+ // CHECK: destroy_addr [[ITER]] : $*Optional<Node<A, B>>
56
+ // CHECK: dealloc_stack [[ITER]] : $*Optional<Node<A, B>>
57
+ // CHECK: [[SELF_NATIVE:%.*]] = unchecked_ref_cast [[SELF]] : $Node<A, B> to $Builtin.NativeObject
58
+ // CHECK: [[SELF_NATIVE_OWNED:%.*]] = unchecked_ownership_conversion [[SELF_NATIVE]] : $Builtin.NativeObject, @guaranteed to @owned
59
+ // CHECK: return [[SELF_NATIVE_OWNED]] : $Builtin.NativeObject
60
+ // CHECK: } // end sil function '$s31deinit_recursive_linear_generic4NodeCfd'
61
+
62
+
63
+ // Types of `self` and `next` don't match, so this should not be optimized
64
+ class Node2 < A, B> {
65
+ var next : Node2 < Int , ( A , B ) > ?
66
+ }
67
+
68
+ // CHECK: sil hidden [ossa] @$s31deinit_recursive_linear_generic5Node2Cfd : $@convention(method) <A, B> (@guaranteed Node2<A, B>) -> @owned Builtin.NativeObject {
69
+ // CHECK: [[SELF:%.*]] "self"
70
+ // CHECK: bb0([[SELF]] : @guaranteed $Node2<A, B>):
71
+ // CHECK: debug_value [[SELF]] : $Node2<A, B>, let, name "self", argno 1, implicit
72
+ // CHECK: [[NEXT_ADDR:%.*]] = ref_element_addr [[SELF]] : $Node2<A, B>, #Node2.next
73
+ // CHECK: [[NEXT_ACCESS:%.*]] = begin_access [deinit] [static] [[NEXT_ADDR]] : $*Optional<Node2<Int, (A, B)>>
74
+ // CHECK: destroy_addr [[NEXT_ACCESS]] : $*Optional<Node2<Int, (A, B)>>
75
+ // CHECK: end_access [[NEXT_ACCESS]] : $*Optional<Node2<Int, (A, B)>>
76
+ // CHECK: [[SELF_NATIVE:%.*]] = unchecked_ref_cast [[SELF]] : $Node2<A, B> to $Builtin.NativeObject
77
+ // CHECK: [[SELF_OWNED:%.*]] = unchecked_ownership_conversion [[SELF_NATIVE]] : $Builtin.NativeObject, @guaranteed to @owned
78
+ // CHECK: return [[SELF_OWNED]] : $Builtin.NativeObject
79
+ // CHECK: } // end sil function '$s31deinit_recursive_linear_generic5Node2Cfd'
0 commit comments