Skip to content

Commit 8b08a74

Browse files
committed
PartialApplySimplification: Use a tuple in a box.
IRGen only implements box lowering for single-field boxes at the moment. We can represent closure contexts that don't capture type info as just capturing a tuple of the values, so let's do that for now to allow for initial end-to-end testing of the pass.
1 parent 1e2bda9 commit 8b08a74

File tree

2 files changed

+80
-8
lines changed

2 files changed

+80
-8
lines changed

lib/SILOptimizer/Transforms/PartialApplySimplification.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,31 @@ void PartialApplySimplificationPass::processKnownCallee(SILFunction *callee,
297297
LLVM_DEBUG(llvm::dbgs() << "TODO: Nonescaping partial_apply not yet implemented\n");
298298
return;
299299
}
300-
300+
if (origTy->getInvocationGenericSignature()) {
301+
LLVM_DEBUG(llvm::dbgs() << "TODO: generic partial_apply not yet implemented\n");
302+
return;
303+
}
304+
305+
// TODO: SILBoxType is only implemented for a single field right now, so
306+
// represent the captures as a tuple.
307+
#if MULTI_FIELD_BOXES_ARE_SUPPORTED
301308
auto newBoxLayout = SILLayout::get(C,
302309
origTy->getInvocationGenericSignature(),
303310
boxFields,
304311
/*capturesGenerics*/ !origTy->getInvocationGenericSignature().isNull());
312+
#else
313+
llvm::SmallVector<TupleTypeElt, 4> tupleElts;
314+
for (auto field : boxFields) {
315+
tupleElts.push_back(TupleTypeElt(field.getLoweredType()));
316+
}
317+
auto tupleTy = TupleType::get(tupleElts, C)->getCanonicalType();
318+
SILField tupleField(tupleTy, /*mutable*/ false);
319+
320+
auto newBoxLayout = SILLayout::get(C,
321+
origTy->getInvocationGenericSignature(),
322+
tupleField,
323+
/*capturesGenerics*/ false);
324+
#endif
305325
SubstitutionMap identitySubstitutionMap;
306326
if (auto origSig = origTy->getInvocationGenericSignature()) {
307327
identitySubstitutionMap = origSig->getIdentitySubstitutionMap();
@@ -358,9 +378,15 @@ void PartialApplySimplificationPass::processKnownCallee(SILFunction *callee,
358378
for (unsigned i = 0; i < appliedBBArgs.size(); ++i) {
359379
auto appliedArg = appliedBBArgs[i];
360380
auto param = partiallyAppliedParams[i];
361-
362-
auto proj = B.createProjectBox(loc, boxArg, i);
363-
381+
382+
#if MULTI_FIELD_BOXES_ARE_SUPPORTED
383+
SILValue proj = B.createProjectBox(loc, boxArg, i);
384+
#else
385+
SILValue proj = B.createProjectBox(loc, boxArg, 0);
386+
if (boxFields.size() > 1) {
387+
proj = B.createTupleElementAddr(loc, proj, i);
388+
}
389+
#endif
364390
// Load the value out of the box according to the current ownership
365391
// mode of the function and the calling convention for the parameter.
366392
SILValue projectedArg;
@@ -493,7 +519,14 @@ void PartialApplySimplificationPass::processKnownCallee(SILFunction *callee,
493519
auto appliedArgs = pa->getArguments();
494520
for (unsigned i = 0; i < appliedArgs.size(); ++i) {
495521
auto arg = appliedArgs[i];
496-
auto proj = B.createProjectBox(loc, newBox, i);
522+
#if MULTI_FIELD_BOXES_ARE_SUPPORTED
523+
SILValue proj = B.createProjectBox(loc, newBox, i);
524+
#else
525+
SILValue proj = B.createProjectBox(loc, newBox, 0);
526+
if (boxFields.size() > 1) {
527+
proj = B.createTupleElementAddr(loc, proj, i);
528+
}
529+
#endif
497530
auto param = partiallyAppliedParams[i];
498531

499532
switch (auto conv = param.getConvention()) {

test/SILOptimizer/partial_apply_simplification.sil

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ entry(%x : $Int, %y : $Int):
1616
// CHECK-LABEL: sil @closure_common_uses_user_a
1717
// CHECK: bb0([[Y:%.*]] : $Int):
1818
// CHECK: [[F:%.*]] = function_ref @closure_common_uses
19-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ let Int }
19+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
2020
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
2121
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
2222
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
@@ -30,7 +30,7 @@ entry(%y : $Int):
3030
// CHECK-LABEL: sil @closure_common_uses_user_b
3131
// CHECK: bb0([[Y:%.*]] : $Int):
3232
// CHECK: [[F:%.*]] = function_ref @closure_common_uses
33-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ let Int }
33+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
3434
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
3535
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
3636
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
@@ -83,7 +83,7 @@ entry(%r : $*Int, %x : $Int, %y : $Int):
8383
// CHECK-LABEL: sil @closure_out_param_user
8484
// CHECK: bb0([[Y:%.*]] : $Int):
8585
// CHECK: [[F:%.*]] = function_ref @closure_out_param
86-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ let Int }
86+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box [reflection] ${ let Int }
8787
// CHECK-NEXT: [[BOX_0:%.*]] = project_box [[BOX]] : ${ let Int }, 0
8888
// CHECK-NEXT: store [[Y]] to [[BOX_0]]
8989
// CHECK-NEXT: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[BOX]])
@@ -93,3 +93,42 @@ entry(%y : $Int):
9393
%c = partial_apply [callee_guaranteed] %f(%y) : $@convention(thin) (Int, Int) -> @out Int
9494
return %c : $@callee_guaranteed (Int) -> @out Int
9595
}
96+
97+
sil @add : $@convention(thin) (Int, Int) -> Int
98+
99+
// CHECK-LABEL: sil private @closure_multi_capture
100+
// CHECK-SAME: : $@convention(method) (Int, @guaranteed { let (Int, Int) }) -> Int
101+
// CHECK: bb0([[X:%.*]] : $Int, [[YZ:%.*]] : ${ let (Int, Int) }):
102+
// CHECK-NEXT: [[BOX_PROJ:%.*]] = project_box [[YZ]] :
103+
// CHECK-NEXT: [[BOX_0:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 0
104+
// CHECK-NEXT: [[Y:%.*]] = load [[BOX_0]] : $*Int
105+
// CHECK-NEXT: [[BOX_PROJ:%.*]] = project_box [[YZ]] :
106+
// CHECK-NEXT: [[BOX_1:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 1
107+
// CHECK-NEXT: [[Z:%.*]] = load [[BOX_1]] : $*Int
108+
// CHECK: [[ADD:%.*]] = function_ref @add
109+
// CHECK-NEXT: apply [[ADD]]([[Y]], [[Z]])
110+
sil private @closure_multi_capture : $@convention(thin) (Int, Int, Int) -> Int {
111+
entry(%x : $Int, %y : $Int, %z : $Int):
112+
%f = function_ref @add : $@convention(thin) (Int, Int) -> Int
113+
%r = apply %f(%y, %z) : $@convention(thin) (Int, Int) -> Int
114+
return %r : $Int
115+
}
116+
117+
// CHECK-LABEL: sil @closure_multi_capture_user
118+
// CHECK: bb0([[Y:%.*]] : $Int, [[Z:%.*]] : $Int):
119+
// CHECK: [[BOX:%.*]] = alloc_box [reflection] ${ let (Int, Int) }
120+
// CHECK: [[BOX_PROJ:%.*]] = project_box [[BOX]]
121+
// CHECK: [[BOX_0:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 0
122+
// CHECK: store [[Y]] to [[BOX_0]]
123+
// CHECK: [[BOX_PROJ:%.*]] = project_box [[BOX]]
124+
// CHECK: [[BOX_1:%.*]] = tuple_element_addr [[BOX_PROJ]] : {{.*}}, 1
125+
// CHECK: store [[Z]] to [[BOX_1]]
126+
// CHECK: [[RESULT:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX]])
127+
// CHECK: return [[RESULT]]
128+
sil @closure_multi_capture_user : $@convention(thin) (Int, Int) -> @owned @callee_guaranteed (Int) -> Int {
129+
entry(%y : $Int, %z : $Int):
130+
%f = function_ref @closure_multi_capture : $@convention(thin) (Int, Int, Int) -> Int
131+
%c = partial_apply [callee_guaranteed] %f(%y, %z) : $@convention(thin) (Int, Int, Int) -> Int
132+
return %c : $@callee_guaranteed (Int) -> Int
133+
}
134+

0 commit comments

Comments
 (0)