Skip to content

Commit 169ffae

Browse files
authored
Merge pull request #10010 from swiftix/closure-specializer-improvements3
2 parents 9acac07 + 4f57305 commit 169ffae

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,9 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc,
298298
// implicit release of all captured arguments that occurs when the partial
299299
// apply is destroyed.
300300
SILModule &M = NewF->getModule();
301-
unsigned ClosureArgIdx = 0;
302301
auto ClosureCalleeConv = CSDesc.getClosureCallee()->getConventions();
302+
unsigned ClosureArgIdx =
303+
ClosureCalleeConv.getNumSILArguments() - CSDesc.getNumArguments();
303304
for (auto Arg : CSDesc.getArguments()) {
304305
SILType ArgTy = Arg->getType();
305306

@@ -504,7 +505,8 @@ static bool isSupportedClosure(const SILInstruction *Closure) {
504505
auto ClosureCallee = FRI->getReferencedFunction();
505506
assert(ClosureCallee);
506507
auto ClosureCalleeConv = ClosureCallee->getConventions();
507-
unsigned ClosureArgIdx = 0;
508+
unsigned ClosureArgIdx =
509+
ClosureCalleeConv.getNumSILArguments() - PAI->getNumArguments();
508510
for (auto Arg : PAI->getArguments()) {
509511
SILType ArgTy = Arg->getType();
510512
// If our argument is an object, continue...

test/SILOptimizer/closure_specialize_consolidated.sil

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ protocol P {
1212
func foo(f: (Int32)->Int32, _ j: Int32) -> Int32
1313
}
1414

15+
protocol Q {
16+
}
17+
1518
public class C {
1619
@sil_stored var c: C? { get set }
1720
init()
1821
}
1922

20-
public struct S {
23+
public struct S: Q {
2124
@sil_stored var c: C? { get set }
2225
init(c: C?)
2326
init()
@@ -244,14 +247,90 @@ bb0(%0 : $Int32):
244247
%2 = alloc_stack $Int32, var, name "xx"
245248
store %0 to %2 : $*Int32
246249
%4 = function_ref @address_closure_user : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
247-
%5 = function_ref @address_closure_trivial_mutating : $@convention(thin) (@inout_aliasable Int32) -> () // user: %6
248-
%6 = partial_apply %5(%2) : $@convention(thin) (@inout_aliasable Int32) -> () // user: %7
250+
%5 = function_ref @address_closure_trivial_mutating : $@convention(thin) (@inout_aliasable Int32) -> ()
251+
%6 = partial_apply %5(%2) : $@convention(thin) (@inout_aliasable Int32) -> ()
249252
%7 = apply %4(%6) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
250253
%8 = load %2 : $*Int32
251254
dealloc_stack %2 : $*Int32
252255
return %8 : $Int32
253256
}
254257

258+
sil @S_init : $@convention(method) (@thin S.Type) -> @owned S
259+
260+
sil hidden @address_closure_body_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q {
261+
bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q):
262+
%5 = init_existential_addr %0 : $*Q, $S
263+
// function_ref S.init()
264+
%6 = function_ref @S_init : $@convention(method) (@thin S.Type) -> @owned S
265+
%7 = metatype $@thin S.Type
266+
%8 = apply %6(%7) : $@convention(method) (@thin S.Type) -> @owned S
267+
store %8 to %5 : $*S
268+
destroy_addr %2 : $*Q
269+
destroy_addr %1 : $*Q
270+
%12 = tuple ()
271+
return %12 : $()
272+
}
273+
274+
sil @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q {
275+
bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q, %3 : $*Q):
276+
%7 = function_ref @address_closure_body_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q
277+
%8 = alloc_stack $Q
278+
copy_addr %2 to [initialization] %8 : $*Q
279+
%10 = alloc_stack $Q
280+
copy_addr %3 to [initialization] %10 : $*Q
281+
%12 = apply %7(%0, %8, %10) : $@convention(thin) (@in Q, @in Q) -> @out Q
282+
dealloc_stack %10 : $*Q
283+
dealloc_stack %8 : $*Q
284+
destroy_addr %1 : $*Q
285+
%16 = tuple ()
286+
return %16 : $()
287+
}
288+
289+
// Check that a specialization of address_closure_user_out_result was generated which does not
290+
// take a closure as a parameter anymore.
291+
// CHECK-LABEL: sil shared @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q
292+
// CHECK: function_ref @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
293+
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply %{{.*}} : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
294+
// CHECK: apply [[PARTIAL_APPLY]]
295+
// CHECK: return
296+
297+
sil @address_closure_user_out_result : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q {
298+
bb0(%0 : $*Q, %1 : $@callee_owned (@in Q) -> @out Q):
299+
%4 = alloc_stack $Q
300+
%5 = init_existential_addr %4 : $*Q, $S
301+
%6 = function_ref @S_init : $@convention(method) (@thin S.Type) -> @owned S
302+
%7 = metatype $@thin S.Type
303+
%8 = apply %6(%7) : $@convention(method) (@thin S.Type) -> @owned S
304+
store %8 to %5 : $*S
305+
%10 = apply %1(%0, %4) : $@callee_owned (@in Q) -> @out Q
306+
dealloc_stack %4 : $*Q
307+
strong_release %1 : $@callee_owned (@in Q) -> @out Q
308+
%13 = tuple ()
309+
return %13 : $()
310+
}
311+
312+
// Check that closure specialization can handle cases where the full closure type may have
313+
// unsupported address type arguments (e.g. @in or @out), but the partial_apply has only
314+
// supported address type arguments, i.e. @inout or @inout_aliasable.
315+
//
316+
// CHECK-LABEL: sil @address_caller_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q
317+
// CHECK-NOT: partial_apply
318+
// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q
319+
// CHECK: apply [[SPECIALIZED_FN1]]{{.*}}
320+
// CHECK-NOT: partial_apply
321+
// CHECK: return
322+
sil @address_caller_out_result: $@convention(thin) (@in Q, @in Q) -> @out Q {
323+
bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q):
324+
%5 = function_ref @address_closure_user_out_result : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q
325+
%6 = function_ref @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
326+
%7 = partial_apply %6(%1, %2) : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
327+
%8 = apply %5(%0, %7) : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q
328+
destroy_addr %2 : $*Q
329+
destroy_addr %1 : $*Q
330+
%11 = tuple ()
331+
return %11 : $()
332+
}
333+
255334
// CHECK-LABEL: sil @address_caller_existential
256335
// CHECK-NOT: partial_apply
257336
// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user{{.*}} : $@convention(thin) (@inout_aliasable P) -> ()
@@ -299,8 +378,8 @@ bb3:
299378

300379
sil shared @address_closure_existential : $@convention(thin) (@inout_aliasable P) -> () {
301380
bb0(%0 : $*P):
302-
%7 = tuple () // user: %8
303-
return %7 : $() // id: %8
381+
%7 = tuple ()
382+
return %7 : $()
304383
}
305384

306385
sil @address_closure_struct1 : $@convention(thin) (@inout_aliasable S, @owned S) -> () {

0 commit comments

Comments
 (0)