1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -partial-apply-simplification | %FileCheck %s
import Swift
// CHECK-LABEL: sil private @closure_common_uses
// CHECK-SAME: : $@convention(method) (Int, @guaranteed { let Int }) -> Int {
// CHECK: bb0([[X:%.*]] : $Int, [[BOX:%.*]] : ${ let Int }):
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
// CHECK-NEXT: return [[Y]]
sil private @closure_common_uses : $@convention(thin) (Int, Int) -> Int {
entry(%x : $Int, %y : $Int):
return %y : $Int
}
// CHECK-LABEL: sil @closure_common_uses_user_a
// CHECK: bb0([[Y:%.*]] : $Int):
// CHECK: [[F:%.*]] = function_ref @closure_common_uses
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
sil @closure_common_uses_user_a : $@convention(thin) (Int) -> @owned @callee_guaranteed (Int) -> Int {
entry(%y : $Int):
%f = function_ref @closure_common_uses : $@convention(thin) (Int, Int) -> Int
%c = partial_apply [callee_guaranteed] %f(%y) : $@convention(thin) (Int, Int) -> Int
return %c : $@callee_guaranteed (Int) -> Int
}
// CHECK-LABEL: sil @closure_common_uses_user_b
// CHECK: bb0([[Y:%.*]] : $Int):
// CHECK: [[F:%.*]] = function_ref @closure_common_uses
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
sil @closure_common_uses_user_b : $@convention(thin) (Int) -> @owned @callee_guaranteed (Int) -> Int {
entry(%y : $Int):
%f = function_ref @closure_common_uses : $@convention(thin) (Int, Int) -> Int
%c = partial_apply [callee_guaranteed] %f(%y) : $@convention(thin) (Int, Int) -> Int
return %c : $@callee_guaranteed (Int) -> Int
}
// CHECK-LABEL: sil private @closure_common_uses_owned
// CHECK-SAME: : $@convention(method) (Int, @owned { let Int }) -> Int {
// CHECK: bb0([[X:%.*]] : $Int, [[BOX:%.*]] : ${ let Int }):
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
// CHECK-NEXT: strong_release [[BOX]]
// CHECK-NEXT: return [[Y]]
sil private @closure_common_uses_owned : $@convention(thin) (Int, Int) -> Int {
entry(%x : $Int, %y : $Int):
return %y : $Int
}
sil @closure_common_uses_owned_user_a : $@convention(thin) (Int) -> @owned @callee_owned (Int) -> Int {
entry(%y : $Int):
%f = function_ref @closure_common_uses_owned : $@convention(thin) (Int, Int) -> Int
%c = partial_apply %f(%y) : $@convention(thin) (Int, Int) -> Int
return %c : $@callee_owned (Int) -> Int
}
sil @closure_common_uses_owned_user_b : $@convention(thin) (Int) -> @owned @callee_owned (Int) -> Int {
entry(%y : $Int):
%f = function_ref @closure_common_uses_owned : $@convention(thin) (Int, Int) -> Int
%c = partial_apply %f(%y) : $@convention(thin) (Int, Int) -> Int
return %c : $@callee_owned (Int) -> Int
}
// CHECK-LABEL: sil private @closure_out_param
// CHECK-SAME: : $@convention(method) (Int, @guaranteed { let Int }) -> @out Int {
// CHECK: bb0([[R:%.*]] : $*Int, [[X:%.*]] : $Int, [[BOX:%.*]] : ${ let Int }):
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
// CHECK-NEXT: store [[Y]] to [[R]]
// CHECK-NEXT: return
sil private @closure_out_param : $@convention(thin) (Int, Int) -> @out Int {
entry(%r : $*Int, %x : $Int, %y : $Int):
store %y to %r : $*Int
return undef : $()
}
// CHECK-LABEL: sil @closure_out_param_user
// CHECK: bb0([[Y:%.*]] : $Int):
// CHECK: [[F:%.*]] = function_ref @closure_out_param
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
sil @closure_out_param_user : $@convention(thin) (Int) -> @owned @callee_guaranteed (Int) -> @out Int {
entry(%y : $Int):
%f = function_ref @closure_out_param : $@convention(thin) (Int, Int) -> @out Int
%c = partial_apply [callee_guaranteed] %f(%y) : $@convention(thin) (Int, Int) -> @out Int
return %c : $@callee_guaranteed (Int) -> @out Int
}
sil @add : $@convention(thin) (Int, Int) -> Int
// CHECK-LABEL: sil private @closure_multi_capture
// CHECK-SAME: : $@convention(method) (Int, @guaranteed { let (Int, Int) }) -> Int
// CHECK: bb0([[X:%.*]] : $Int, [[YZ:%.*]] : ${ let (Int, Int) }):
// CHECK-NEXT: [[BOX_PROJ:%.*]] = project_box [[YZ]] :
// CHECK-NEXT: [[BOX_0:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 0
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
// CHECK-NEXT: [[BOX_PROJ:%.*]] = project_box [[YZ]] :
// CHECK-NEXT: [[BOX_1:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 1
// CHECK-NEXT: [[Z:%.*]] = load [[BOX_1]] : $*Int
// CHECK: [[ADD:%.*]] = function_ref @add
// CHECK-NEXT: apply [[ADD]]([[Y]], [[Z]])
sil private @closure_multi_capture : $@convention(thin) (Int, Int, Int) -> Int {
entry(%x : $Int, %y : $Int, %z : $Int):
%f = function_ref @add : $@convention(thin) (Int, Int) -> Int
%r = apply %f(%y, %z) : $@convention(thin) (Int, Int) -> Int
return %r : $Int
}
// CHECK-LABEL: sil @closure_multi_capture_user
// CHECK: bb0([[Y:%.*]] : $Int, [[Z:%.*]] : $Int):
// CHECK: [[BOX:%.*]] = alloc_box [reflection] ${ let (Int, Int) }
// CHECK: [[BOX_PROJ:%.*]] = project_box [[BOX]]
// CHECK: [[BOX_0:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 0
// CHECK: store [[Y]] to [[BOX_0]]
// CHECK: [[BOX_1:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 1
// CHECK: store [[Z]] to [[BOX_1]]
// CHECK: [[RESULT:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX]])
// CHECK: return [[RESULT]]
sil @closure_multi_capture_user : $@convention(thin) (Int, Int) -> @owned @callee_guaranteed (Int) -> Int {
entry(%y : $Int, %z : $Int):
%f = function_ref @closure_multi_capture : $@convention(thin) (Int, Int, Int) -> Int
%c = partial_apply [callee_guaranteed] %f(%y, %z) : $@convention(thin) (Int, Int, Int) -> Int
return %c : $@callee_guaranteed (Int) -> Int
}
// CHECK-LABEL: sil private @closure_nonescaping
// CHECK-SAME: : $@convention(method) (Int, @in_guaranteed (Int, Int)) -> Int
// CHECK: bb0([[X:%.*]] : $Int, [[YZ:%.*]] : $*(Int, Int)):
// CHECK: [[BOX_0:%.*]] = tuple_element_addr [[YZ]] : {{.*}}, 0
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
// CHECK-NEXT: [[BOX_1:%.*]] = tuple_element_addr [[YZ]] : {{.*}}, 1
// CHECK-NEXT: [[Z:%.*]] = load [[BOX_1]] : $*Int
// CHECK: [[ADD:%.*]] = function_ref @add
// CHECK-NEXT: apply [[ADD]]([[Y]], [[Z]])
sil private @closure_nonescaping : $@convention(thin) (Int, Int, Int) -> Int {
entry(%x : $Int, %y : $Int, %z : $Int):
%f = function_ref @add : $@convention(thin) (Int, Int) -> Int
%r = apply %f(%y, %z) : $@convention(thin) (Int, Int) -> Int
return %r : $Int
}
sil @closure_nonescaping_consumer : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, Int) -> Int {
entry(%f : $@noescape @callee_guaranteed (Int) -> Int, %x : $Int):
%y = apply %f(%x) : $@noescape @callee_guaranteed (Int) -> Int
return %y : $Int
}
// CHECK-LABEL: sil @closure_nonescaping_user
// CHECK: bb0([[X:%.*]] : $Int, [[Y:%.*]] : $Int, [[Z:%.*]] : $Int):
// CHECK: [[F:%.*]] = function_ref @closure_nonescaping
// CHECK: [[CONTEXT:%.*]] = alloc_stack $(Int, Int)
// CHECK: [[CONTEXT_Y:%.*]] = tuple_element_addr [[CONTEXT]] {{.*}}, 0
// CHECK: store [[Y]] to [[CONTEXT_Y]]
// CHECK: [[CONTEXT_Z:%.*]] = tuple_element_addr [[CONTEXT]] {{.*}}, 1
// CHECK: store [[Z]] to [[CONTEXT_Z]]
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[F]]([[CONTEXT]])
// CHECK: [[CONSUMER:%.*]] = function_ref @closure_nonescaping_consumer
// CHECK: apply [[CONSUMER]]([[CLOSURE]], [[X]])
sil @closure_nonescaping_user : $@convention(thin) (Int, Int, Int) -> Int {
entry(%x : $Int, %y : $Int, %z : $Int):
%f = function_ref @closure_nonescaping : $@convention(thin) (Int, Int, Int) -> Int
%c = partial_apply [callee_guaranteed] [on_stack] %f(%y, %z) : $@convention(thin) (Int, Int, Int) -> Int
%g = function_ref @closure_nonescaping_consumer : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, Int) -> Int
%r = apply %g(%c, %x) : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, Int) -> Int
dealloc_stack %c : $@noescape @callee_guaranteed (Int) -> Int
return %r : $Int
}
// CHECK-LABEL: sil @closure_nonescaping_full_apply
// CHECK: bb0([[X:%.*]] : $Int, [[Y:%.*]] : $Int, [[Z:%.*]] : $Int):
// CHECK: [[F:%.*]] = function_ref @closure_nonescaping
// CHECK: [[CONTEXT:%.*]] = alloc_stack $(Int, Int)
// CHECK: [[CONTEXT_Y:%.*]] = tuple_element_addr [[CONTEXT]] {{.*}}, 0
// CHECK: store [[Y]] to [[CONTEXT_Y]]
// CHECK: [[CONTEXT_Z:%.*]] = tuple_element_addr [[CONTEXT]] {{.*}}, 1
// CHECK: store [[Z]] to [[CONTEXT_Z]]
// CHECK: [[CLOSURE:%.*]] = apply [[F]]([[X]], [[CONTEXT]])
sil @closure_nonescaping_full_apply : $@convention(thin) (Int, Int, Int) -> Int {
entry(%x : $Int, %y : $Int, %z : $Int):
%f = function_ref @closure_nonescaping : $@convention(thin) (Int, Int, Int) -> Int
%r = apply %f(%x, %y, %z) : $@convention(thin) (Int, Int, Int) -> Int
return %r : $Int
}
// CHECK-LABEL: sil private @closure_nonescaping_convention_change
// CHECK-SAME: : $@convention(method) (Int, @in_guaranteed Int) -> Int {
sil private @closure_nonescaping_convention_change : $@convention(thin) (Int, @in_guaranteed Int) -> Int {
entry(%x : $Int, %y : $*Int):
%f = function_ref @add : $@convention(thin) (Int, Int) -> Int
%z = load %y : $*Int
%r = apply %f(%x, %z) : $@convention(thin) (Int, Int) -> Int
return %r : $Int
}
sil @closure_nonescaping_convention_change_user : $@convention(thin) (Int, @in_guaranteed Int) -> Int {
entry(%x : $Int, %y : $*Int):
%f = function_ref @closure_nonescaping_convention_change : $@convention(thin) (Int, @in_guaranteed Int) -> Int
%c = partial_apply [callee_guaranteed] [on_stack] %f(%y) : $@convention(thin) (Int, @in_guaranteed Int) -> Int
%g = function_ref @closure_nonescaping_consumer : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, Int) -> Int
%r = apply %g(%c, %x) : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, Int) -> Int
dealloc_stack %c : $@noescape @callee_guaranteed (Int) -> Int
return %r : $Int
}
|