Skip to content

Commit 47eba8a

Browse files
committed
CapturePromotion: Fix promotion of resilient but locally non-resilient types
Pass the resilience expansion to the cloner so that it can correctly (in agreement with the caller) decide whether something is address only. rdar://52263202
1 parent ebc5d76 commit 47eba8a

File tree

2 files changed

+73
-23
lines changed

2 files changed

+73
-23
lines changed

lib/SILOptimizer/IPO/CapturePromotion.cpp

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,9 @@ class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
197197
friend class SILInstructionVisitor<ClosureCloner>;
198198
friend class SILCloner<ClosureCloner>;
199199

200-
ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
201-
SILFunction *Orig, IsSerialized_t Serialized,
202-
StringRef ClonedName,
203-
IndicesSet &PromotableIndices);
200+
ClosureCloner(SILOptFunctionBuilder &FuncBuilder, SILFunction *Orig,
201+
IsSerialized_t Serialized, StringRef ClonedName,
202+
IndicesSet &PromotableIndices, ResilienceExpansion expansion);
204203

205204
void populateCloned();
206205

@@ -210,7 +209,8 @@ class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
210209
static SILFunction *initCloned(SILOptFunctionBuilder &FuncBuilder,
211210
SILFunction *Orig, IsSerialized_t Serialized,
212211
StringRef ClonedName,
213-
IndicesSet &PromotableIndices);
212+
IndicesSet &PromotableIndices,
213+
ResilienceExpansion expansion);
214214

215215
SILValue getProjectBoxMappedVal(SILValue Operand);
216216

@@ -224,6 +224,7 @@ class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
224224
void visitBeginAccessInst(BeginAccessInst *Inst);
225225
void visitEndAccessInst(EndAccessInst *Inst);
226226

227+
ResilienceExpansion resilienceExpansion;
227228
SILFunction *Orig;
228229
IndicesSet &PromotableIndices;
229230
llvm::DenseMap<SILArgument *, SILValue> BoxArgumentMap;
@@ -311,10 +312,12 @@ ReachabilityInfo::isReachable(SILBasicBlock *From, SILBasicBlock *To) {
311312
ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
312313
SILFunction *Orig, IsSerialized_t Serialized,
313314
StringRef ClonedName,
314-
IndicesSet &PromotableIndices)
315-
: SILClonerWithScopes<ClosureCloner>(
316-
*initCloned(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices)),
317-
Orig(Orig), PromotableIndices(PromotableIndices) {
315+
IndicesSet &PromotableIndices,
316+
ResilienceExpansion resilienceExpansion)
317+
: SILClonerWithScopes<ClosureCloner>(
318+
*initCloned(FuncBuilder, Orig, Serialized, ClonedName,
319+
PromotableIndices, resilienceExpansion)),
320+
Orig(Orig), PromotableIndices(PromotableIndices) {
318321
assert(Orig->getDebugScope()->Parent != getCloned()->getDebugScope()->Parent);
319322
}
320323

@@ -326,9 +329,9 @@ ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
326329
/// 2. Replace container box value arguments for the cloned closure with the
327330
/// transformed address or value argument.
328331
static void
329-
computeNewArgInterfaceTypes(SILFunction *F,
330-
IndicesSet &PromotableIndices,
331-
SmallVectorImpl<SILParameterInfo> &OutTys) {
332+
computeNewArgInterfaceTypes(SILFunction *F, IndicesSet &PromotableIndices,
333+
SmallVectorImpl<SILParameterInfo> &OutTys,
334+
ResilienceExpansion expansion) {
332335
auto fnConv = F->getConventions();
333336
auto Parameters = fnConv.funcTy->getParameters();
334337

@@ -365,11 +368,9 @@ computeNewArgInterfaceTypes(SILFunction *F,
365368
assert(paramBoxTy->getLayout()->getFields().size() == 1
366369
&& "promoting compound box not implemented yet");
367370
auto paramBoxedTy = paramBoxTy->getFieldType(F->getModule(), 0);
368-
// FIXME: Expansion
369-
auto &paramTL = Types.getTypeLowering(paramBoxedTy,
370-
ResilienceExpansion::Minimal);
371+
auto &paramTL = Types.getTypeLowering(paramBoxedTy, expansion);
371372
ParameterConvention convention;
372-
if (paramTL.isFormallyPassedIndirectly()) {
373+
if (paramTL.isAddressOnly()) {
373374
convention = ParameterConvention::Indirect_In;
374375
} else if (paramTL.isTrivial()) {
375376
convention = ParameterConvention::Direct_Unowned;
@@ -407,16 +408,17 @@ static std::string getSpecializedName(SILFunction *F,
407408
///
408409
/// *NOTE* PromotableIndices only contains the container value of the box, not
409410
/// the address value.
410-
SILFunction*
411+
SILFunction *
411412
ClosureCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder,
412413
SILFunction *Orig, IsSerialized_t Serialized,
413-
StringRef ClonedName,
414-
IndicesSet &PromotableIndices) {
414+
StringRef ClonedName, IndicesSet &PromotableIndices,
415+
ResilienceExpansion resilienceExpansion) {
415416
SILModule &M = Orig->getModule();
416417

417418
// Compute the arguments for our new function.
418419
SmallVector<SILParameterInfo, 4> ClonedInterfaceArgTys;
419-
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys);
420+
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys,
421+
resilienceExpansion);
420422

421423
SILFunctionType *OrigFTI = Orig->getLoweredFunctionType();
422424

@@ -1149,7 +1151,8 @@ examineAllocBoxInst(AllocBoxInst *ABI, ReachabilityInfo &RI,
11491151
static SILFunction *
11501152
constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
11511153
PartialApplyInst *PAI, FunctionRefInst *FRI,
1152-
IndicesSet &PromotableIndices) {
1154+
IndicesSet &PromotableIndices,
1155+
ResilienceExpansion resilienceExpansion) {
11531156
SILFunction *F = PAI->getFunction();
11541157

11551158
// Create the Cloned Name for the function.
@@ -1168,7 +1171,8 @@ constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
11681171
}
11691172

11701173
// Otherwise, create a new clone.
1171-
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices);
1174+
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName,
1175+
PromotableIndices, resilienceExpansion);
11721176
cloner.populateCloned();
11731177
return cloner.getCloned();
11741178
}
@@ -1252,7 +1256,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
12521256
auto *FRI = dyn_cast<FunctionRefInst>(PAI->getCallee());
12531257

12541258
// Clone the closure with the given promoted captures.
1255-
SILFunction *ClonedFn = constructClonedFunction(FuncBuilder, PAI, FRI, PromotableIndices);
1259+
SILFunction *ClonedFn = constructClonedFunction(
1260+
FuncBuilder, PAI, FRI, PromotableIndices, F->getResilienceExpansion());
12561261
Worklist.push_back(ClonedFn);
12571262

12581263
// Initialize a SILBuilder and create a function_ref referencing the cloned
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-sil-opt -enable-library-evolution -enable-sil-verify-all %s -capture-promotion | %FileCheck %s
2+
3+
sil_stage raw
4+
5+
import Swift
6+
7+
public struct ResilientStruct {
8+
var x : Int64
9+
}
10+
11+
sil @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> () {
12+
bb0(%0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>):
13+
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
14+
%2 = tuple ()
15+
return %2 : $()
16+
}
17+
18+
// Primarily don't crash.
19+
20+
// CHECK-LABEL: sil @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () {
21+
// CHECK: bb0(%0 : $ResilientStruct):
22+
// CHECK: return {{.*}} : $()
23+
// CHECK: }
24+
25+
// CHECK: sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
26+
// CHECK: bb0([[ARG:%.*]] : $*ResilientStruct):
27+
// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
28+
// CHECK: [[F1:%.*]] = project_box [[BOX]]
29+
// CHECK: [[F2:%.*]] = project_box [[BOX]]
30+
// CHECK: copy_addr [[ARG]] to [initialization] [[F2]] : $*ResilientStruct
31+
// CHECK: [[F:%.*]] = function_ref @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () // user: %8
32+
// CHECK: [[R:%.*]] = load [[F1]] : $*ResilientStruct
33+
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[R]])
34+
// CHECK: return [[C]] : $@callee_guaranteed () -> ()
35+
// CHECK: }
36+
37+
sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
38+
bb0(%0 : $*ResilientStruct):
39+
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
40+
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
41+
copy_addr %0 to [initialization] %2 : $*ResilientStruct
42+
%4 = function_ref @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
43+
%5 = partial_apply [callee_guaranteed] %4(%1) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
44+
return %5 : $@callee_guaranteed () -> ()
45+
}

0 commit comments

Comments
 (0)