Skip to content

Commit 585c527

Browse files
authored
Merge pull request #8420 from swiftix/fix-rdar-31309883
[sil-capture-promotion] Properly handle generic SILBoxTypes
2 parents 4271687 + 7887eb3 commit 585c527

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

lib/SILOptimizer/IPO/CapturePromotion.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,7 @@ computeNewArgInterfaceTypes(SILFunction *F,
350350
assert(paramBoxTy->getLayout()->getFields().size() == 1
351351
&& "promoting compound box not implemented yet");
352352
auto paramBoxedTy = paramBoxTy->getFieldType(F->getModule(), 0);
353-
auto &paramTL = F->getModule().Types.getTypeLowering(paramBoxedTy);
354-
353+
auto &paramTL = F->getTypeLowering(paramBoxedTy);
355354
ParameterConvention convention;
356355
if (paramTL.isFormallyPassedIndirectly()) {
357356
convention = ParameterConvention::Indirect_In;
@@ -863,8 +862,12 @@ processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
863862
// Populate the argument list for a new partial_apply instruction, taking into
864863
// consideration any captures.
865864
auto CalleeFunctionTy = PAI->getCallee()->getType().castTo<SILFunctionType>();
866-
SILFunctionConventions calleeConv(CalleeFunctionTy, M);
867-
auto CalleePInfo = CalleeFunctionTy->getParameters();
865+
auto SubstCalleeFunctionTy = CalleeFunctionTy;
866+
if (PAI->hasSubstitutions())
867+
SubstCalleeFunctionTy =
868+
CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutions());
869+
SILFunctionConventions calleeConv(SubstCalleeFunctionTy, M);
870+
auto CalleePInfo = SubstCalleeFunctionTy->getParameters();
868871
SILFunctionConventions paConv(PAI->getType().castTo<SILFunctionType>(), M);
869872
unsigned FirstIndex = paConv.getNumSILArguments();
870873
unsigned OpNo = 1, OpCount = PAI->getNumOperands();
@@ -879,10 +882,6 @@ processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
879882
SILParameterInfo CPInfo = CalleePInfo[Index - NumIndirectResults];
880883
assert(calleeConv.getSILType(CPInfo) == BoxValue->getType()
881884
&& "SILType of parameter info does not match type of parameter");
882-
// Cleanup the captured argument.
883-
releasePartialApplyCapturedArg(B, PAI->getLoc(), BoxValue,
884-
CPInfo);
885-
886885
// Load and copy from the address value, passing the result as an argument
887886
// to the new closure.
888887
SILValue Addr;
@@ -906,6 +905,9 @@ processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
906905
auto &typeLowering = M.getTypeLowering(Addr->getType());
907906
Args.push_back(
908907
typeLowering.emitLoadOfCopy(B, PAI->getLoc(), Addr, IsNotTake));
908+
// Cleanup the captured argument.
909+
releasePartialApplyCapturedArg(B, PAI->getLoc(), BoxValue,
910+
CPInfo);
909911
++NumCapturesPromoted;
910912
} else {
911913
Args.push_back(PAI->getOperand(OpNo));

test/SILOptimizer/capture_promotion_generic_context.sil

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,56 @@ entry(%0 : $*T, %1 : $*U, %2 : $Int):
6767
%k = partial_apply %f<U>(%b) : $@convention(thin) <V> (@in V, <τ_0_0> { var τ_0_0 } <Int>) -> Int
6868
return %k : $@callee_owned (@in U) -> Int
6969
}
70+
71+
enum E<X> {
72+
case None
73+
case Some(X)
74+
}
75+
76+
struct R<T> {
77+
}
78+
79+
// Check that the capture promotion took place and the function now
80+
// take argument of a type E<(R<T>) -> Builtin.Int32>, which used
81+
// to be a slot inside a box.
82+
// CHECK-LABEL: sil @_T023generic_promotable_box2Tf2nni_n : $@convention(thin) <T> (@in R<T>, @in Builtin.Int32, @owned E<(R<T>) -> Builtin.Int32>) -> ()
83+
// CHECK: bb0(%0 : $*R<T>, %1 : $*Builtin.Int32, %2 : $E<(R<T>) -> Builtin.Int32>):
84+
// CHECK-NOT: project_box
85+
// CHECK: switch_enum %2 : $E<(R<T>) -> Builtin.Int32>
86+
// CHECK-NOT: project_box
87+
// CHECK: } // end sil function '_T023generic_promotable_box2Tf2nni_n'
88+
sil @generic_promotable_box2 : $@convention(thin) <T> (@in R<T>, @in Int, <τ_0_0> { var E<(R<τ_0_0>) -> Int> } <T>) -> () {
89+
entry(%0: $*R<T>, %1 : $*Int, %b : $<τ_0_0> { var E< (R<τ_0_0>)->Int > } <T>):
90+
%a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <T>, 0
91+
%e = load %a : $*E<(R<T>)->Int>
92+
switch_enum %e : $E<(R<T>)->Int>, case #E.Some!enumelt.1 : bb1, default bb2
93+
bb1(%f : $@callee_owned (@in R<T>) -> @out Int):
94+
%t = tuple ()
95+
apply %f(%1, %0) : $@callee_owned (@in R<T>) -> @out Int
96+
br exit
97+
bb2:
98+
br exit
99+
exit:
100+
%r = tuple ()
101+
return %r : $()
102+
}
103+
104+
// Check that alloc_box was eliminated and a specialized version of the
105+
// closure is invoked.
106+
// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic2
107+
// CHECK: bb0(%0 : $*R<T>, %1 : $*E<(R<U>) -> Builtin.Int32>, %2 : $*Builtin.Int32):
108+
// CHECK: %3 = load %1 : $*E<(R<U>) -> Builtin.Int32>
109+
// CHECK: [[F:%.*]] = function_ref @_T023generic_promotable_box2Tf2nni_n : $@convention(thin) <τ_0_0> (@in R<τ_0_0>, @in Builtin.Int32, @owned E<(R<τ_0_0>) -> Builtin.Int32>) -> ()
110+
// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [[F]]<U>(%2, %3)
111+
// CHECK-NEXT: return [[CLOSURE]]
112+
113+
sil @call_generic_promotable_box_from_different_generic2 : $@convention(thin) <T, U: P> (@in R<T>, @in E<(R<U>)->Int>, @in Int) -> @owned @callee_owned (@in R<U>) -> () {
114+
entry(%0 : $*R<T>, %1 : $*E<(R<U>)->Int>, %2 : $*Int):
115+
destroy_addr %0 : $*R<T>
116+
%f = function_ref @generic_promotable_box2 : $@convention(thin) <V> (@in R<V>, @in Int, <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
117+
%b = alloc_box $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>
118+
%a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>, 0
119+
copy_addr [take] %1 to [initialization] %a : $*E<(R<U>)->Int>
120+
%k = partial_apply %f<U>(%2, %b) : $@convention(thin) <V> (@in R<V>, @in Int, <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
121+
return %k : $@callee_owned (@in R<U>) -> ()
122+
}

0 commit comments

Comments
 (0)