Skip to content

Commit 4fb66a1

Browse files
committed
CapturePromotion: Handle closures with indirect results correctly (#3169)
The code was not taking them into account when translating between arguments of the partial_apply and the parameter info. rdar://26214143
1 parent 47a247c commit 4fb66a1

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

lib/SILOptimizer/IPO/CapturePromotion.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -332,19 +332,26 @@ static void
332332
computeNewArgInterfaceTypes(SILFunction *F,
333333
IndicesSet &PromotableIndices,
334334
SmallVectorImpl<SILParameterInfo> &OutTys) {
335-
auto Parameters = F->getLoweredFunctionType()->getParameters();
335+
auto FunctionTy = F->getLoweredFunctionType();
336+
auto Parameters = FunctionTy->getParameters();
337+
auto NumIndirectResults = FunctionTy->getNumIndirectResults();
336338

337339
DEBUG(llvm::dbgs() << "Preparing New Args!\n");
338340

339341
// For each parameter in the old function...
340342
for (unsigned Index : indices(Parameters)) {
341343
auto &param = Parameters[Index];
342344

345+
// The PromotableIndices index is expressed as the argument index (num
346+
// indirect result + param index). Add back the num indirect results to get
347+
// the arg index when working with PromotableIndices.
348+
unsigned ArgIndex = Index + NumIndirectResults;
349+
343350
DEBUG(llvm::dbgs() << "Index: " << Index << "; PromotableIndices: "
344-
<< (PromotableIndices.count(Index)?"yes":"no")
351+
<< (PromotableIndices.count(ArgIndex)?"yes":"no")
345352
<< " Param: "; param.dump());
346353

347-
if (!PromotableIndices.count(Index)) {
354+
if (!PromotableIndices.count(ArgIndex)) {
348355
OutTys.push_back(param);
349356
continue;
350357
}
@@ -377,8 +384,14 @@ static std::string getSpecializedName(SILFunction *F,
377384
CanSILFunctionType FTy = F->getLoweredFunctionType();
378385

379386
ArrayRef<SILParameterInfo> Parameters = FTy->getParameters();
387+
auto NumIndirectResults = FTy->getNumIndirectResults();
388+
380389
for (unsigned Index : indices(Parameters)) {
381-
if (!PromotableIndices.count(Index))
390+
// The PromotableIndices index is expressed as the argument index (num
391+
// indirect result + param index). Add back the num indirect results to get
392+
// the arg index when working with PromotableIndices.
393+
unsigned ArgIndex = Index + NumIndirectResults;
394+
if (!PromotableIndices.count(ArgIndex))
382395
continue;
383396
FSSM.setArgumentBoxToValue(Index);
384397
}
@@ -747,11 +760,6 @@ examineAllocBoxInst(AllocBoxInst *ABI, ReachabilityInfo &RI,
747760
if (signatureHasDependentTypes(*CalleeTy))
748761
return false;
749762

750-
// The code currently does not handle indirect results correctly.
751-
// Conservatively, bail
752-
if (CalleeTy->hasIndirectResults())
753-
return false;
754-
755763
auto closureType = PAI->getType().castTo<SILFunctionType>();
756764

757765
// Calculate the index into the closure's argument list of the captured
@@ -912,19 +920,20 @@ processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
912920

913921
// Populate the argument list for a new partial_apply instruction, taking into
914922
// consideration any captures.
915-
auto CalleePInfo =
916-
PAI->getCallee()->getType().castTo<SILFunctionType>()->getParameters();
917-
auto PInfo = PAI->getType().castTo<SILFunctionType>()->getParameters();
918-
unsigned FirstIndex = PInfo.size();
923+
auto CalleeFunctionTy = PAI->getCallee()->getType().castTo<SILFunctionType>();
924+
auto CalleePInfo = CalleeFunctionTy->getParameters();
925+
unsigned FirstIndex =
926+
PAI->getType().castTo<SILFunctionType>()->getNumSILArguments();
919927
unsigned OpNo = 1, OpCount = PAI->getNumOperands();
920928
SmallVector<SILValue, 16> Args;
929+
auto NumIndirectResults = CalleeFunctionTy->getNumIndirectResults();
921930
while (OpNo != OpCount) {
922931
unsigned Index = OpNo - 1 + FirstIndex;
923932
if (PromotableIndices.count(Index)) {
924933
SILValue BoxValue = PAI->getOperand(OpNo);
925934
AllocBoxInst *ABI = cast<AllocBoxInst>(BoxValue);
926935

927-
SILParameterInfo CPInfo = CalleePInfo[Index];
936+
SILParameterInfo CPInfo = CalleePInfo[Index - NumIndirectResults];
928937
assert(CPInfo.getSILType() == BoxValue->getType() &&
929938
"SILType of parameter info does not match type of parameter");
930939
// Cleanup the captured argument.

test/SILOptimizer/capture_promotion.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,29 @@ bb0:
110110
%15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
111111
store %15 to %11a : $*Int
112112

113+
// CHECK-NOT: function_ref @closure_indirect_result :
114+
// CHECK: [[CLOSURE_PROMOTE:%.*]] = function_ref @_TTSf2i_i_i_n__closure_indirect_result
115+
// CHECK-NOT: function_ref @closure_indirect_result :
116+
117+
// The three strong retains are removed
118+
119+
// The Foo variable is loaded from and retained, because it is a reference type
120+
// CHECK-NEXT: [[LOADFOO:%.*]] = load {{.*}} : $*Foo
121+
// CHECK-NEXT: strong_retain [[LOADFOO]] : $Foo
122+
123+
// The Baz variable is loaded and retain_value'd, because it is a non-trivial
124+
// aggregate type
125+
// CHECK-NEXT: [[LOADBAZ:%.*]] = load {{.*}} : $*Baz
126+
// CHECK-NEXT: retain_value [[LOADBAZ:%.*]] : $Baz
127+
128+
// The Int variable is loaded only, because it is trivial
129+
// CHECK-NEXT: [[LOADINT:%.*]] = load {{.*}} : $*Int
130+
131+
// The partial apply has one value argument for each pair of arguments that was
132+
// previously used to capture and pass the variable by reference
133+
// CHECK-NEXT: {{.*}} = partial_apply [[CLOSURE_PROMOTE]]([[LOADFOO]], [[LOADBAZ]], [[LOADINT]])
134+
135+
113136
%17 = function_ref @closure_indirect_result : $@convention(thin) (@owned @box Foo, @owned @box Baz, @owned @box Int) -> @out Int
114137
strong_retain %1 : $@box Foo
115138
strong_retain %6 : $@box Baz

0 commit comments

Comments
 (0)