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
This commit is contained in:
Arnold Schwaighofer
2019-06-26 12:55:48 -07:00
parent ebc5d763d2
commit 47eba8af70
2 changed files with 73 additions and 23 deletions

View File

@@ -197,10 +197,9 @@ public:
friend class SILInstructionVisitor<ClosureCloner>;
friend class SILCloner<ClosureCloner>;
ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
SILFunction *Orig, IsSerialized_t Serialized,
StringRef ClonedName,
IndicesSet &PromotableIndices);
ClosureCloner(SILOptFunctionBuilder &FuncBuilder, SILFunction *Orig,
IsSerialized_t Serialized, StringRef ClonedName,
IndicesSet &PromotableIndices, ResilienceExpansion expansion);
void populateCloned();
@@ -210,7 +209,8 @@ private:
static SILFunction *initCloned(SILOptFunctionBuilder &FuncBuilder,
SILFunction *Orig, IsSerialized_t Serialized,
StringRef ClonedName,
IndicesSet &PromotableIndices);
IndicesSet &PromotableIndices,
ResilienceExpansion expansion);
SILValue getProjectBoxMappedVal(SILValue Operand);
@@ -224,6 +224,7 @@ private:
void visitBeginAccessInst(BeginAccessInst *Inst);
void visitEndAccessInst(EndAccessInst *Inst);
ResilienceExpansion resilienceExpansion;
SILFunction *Orig;
IndicesSet &PromotableIndices;
llvm::DenseMap<SILArgument *, SILValue> BoxArgumentMap;
@@ -311,10 +312,12 @@ ReachabilityInfo::isReachable(SILBasicBlock *From, SILBasicBlock *To) {
ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
SILFunction *Orig, IsSerialized_t Serialized,
StringRef ClonedName,
IndicesSet &PromotableIndices)
: SILClonerWithScopes<ClosureCloner>(
*initCloned(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices)),
Orig(Orig), PromotableIndices(PromotableIndices) {
IndicesSet &PromotableIndices,
ResilienceExpansion resilienceExpansion)
: SILClonerWithScopes<ClosureCloner>(
*initCloned(FuncBuilder, Orig, Serialized, ClonedName,
PromotableIndices, resilienceExpansion)),
Orig(Orig), PromotableIndices(PromotableIndices) {
assert(Orig->getDebugScope()->Parent != getCloned()->getDebugScope()->Parent);
}
@@ -326,9 +329,9 @@ ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
/// 2. Replace container box value arguments for the cloned closure with the
/// transformed address or value argument.
static void
computeNewArgInterfaceTypes(SILFunction *F,
IndicesSet &PromotableIndices,
SmallVectorImpl<SILParameterInfo> &OutTys) {
computeNewArgInterfaceTypes(SILFunction *F, IndicesSet &PromotableIndices,
SmallVectorImpl<SILParameterInfo> &OutTys,
ResilienceExpansion expansion) {
auto fnConv = F->getConventions();
auto Parameters = fnConv.funcTy->getParameters();
@@ -365,11 +368,9 @@ computeNewArgInterfaceTypes(SILFunction *F,
assert(paramBoxTy->getLayout()->getFields().size() == 1
&& "promoting compound box not implemented yet");
auto paramBoxedTy = paramBoxTy->getFieldType(F->getModule(), 0);
// FIXME: Expansion
auto &paramTL = Types.getTypeLowering(paramBoxedTy,
ResilienceExpansion::Minimal);
auto &paramTL = Types.getTypeLowering(paramBoxedTy, expansion);
ParameterConvention convention;
if (paramTL.isFormallyPassedIndirectly()) {
if (paramTL.isAddressOnly()) {
convention = ParameterConvention::Indirect_In;
} else if (paramTL.isTrivial()) {
convention = ParameterConvention::Direct_Unowned;
@@ -407,16 +408,17 @@ static std::string getSpecializedName(SILFunction *F,
///
/// *NOTE* PromotableIndices only contains the container value of the box, not
/// the address value.
SILFunction*
SILFunction *
ClosureCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder,
SILFunction *Orig, IsSerialized_t Serialized,
StringRef ClonedName,
IndicesSet &PromotableIndices) {
StringRef ClonedName, IndicesSet &PromotableIndices,
ResilienceExpansion resilienceExpansion) {
SILModule &M = Orig->getModule();
// Compute the arguments for our new function.
SmallVector<SILParameterInfo, 4> ClonedInterfaceArgTys;
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys);
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys,
resilienceExpansion);
SILFunctionType *OrigFTI = Orig->getLoweredFunctionType();
@@ -1149,7 +1151,8 @@ examineAllocBoxInst(AllocBoxInst *ABI, ReachabilityInfo &RI,
static SILFunction *
constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
PartialApplyInst *PAI, FunctionRefInst *FRI,
IndicesSet &PromotableIndices) {
IndicesSet &PromotableIndices,
ResilienceExpansion resilienceExpansion) {
SILFunction *F = PAI->getFunction();
// Create the Cloned Name for the function.
@@ -1168,7 +1171,8 @@ constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
}
// Otherwise, create a new clone.
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices);
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName,
PromotableIndices, resilienceExpansion);
cloner.populateCloned();
return cloner.getCloned();
}
@@ -1252,7 +1256,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
auto *FRI = dyn_cast<FunctionRefInst>(PAI->getCallee());
// Clone the closure with the given promoted captures.
SILFunction *ClonedFn = constructClonedFunction(FuncBuilder, PAI, FRI, PromotableIndices);
SILFunction *ClonedFn = constructClonedFunction(
FuncBuilder, PAI, FRI, PromotableIndices, F->getResilienceExpansion());
Worklist.push_back(ClonedFn);
// Initialize a SILBuilder and create a function_ref referencing the cloned

View File

@@ -0,0 +1,45 @@
// RUN: %target-sil-opt -enable-library-evolution -enable-sil-verify-all %s -capture-promotion | %FileCheck %s
sil_stage raw
import Swift
public struct ResilientStruct {
var x : Int64
}
sil @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> () {
bb0(%0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>):
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
%2 = tuple ()
return %2 : $()
}
// Primarily don't crash.
// CHECK-LABEL: sil @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () {
// CHECK: bb0(%0 : $ResilientStruct):
// CHECK: return {{.*}} : $()
// CHECK: }
// CHECK: sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
// CHECK: bb0([[ARG:%.*]] : $*ResilientStruct):
// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
// CHECK: [[F1:%.*]] = project_box [[BOX]]
// CHECK: [[F2:%.*]] = project_box [[BOX]]
// CHECK: copy_addr [[ARG]] to [initialization] [[F2]] : $*ResilientStruct
// CHECK: [[F:%.*]] = function_ref @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () // user: %8
// CHECK: [[R:%.*]] = load [[F1]] : $*ResilientStruct
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[R]])
// CHECK: return [[C]] : $@callee_guaranteed () -> ()
// CHECK: }
sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
bb0(%0 : $*ResilientStruct):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
copy_addr %0 to [initialization] %2 : $*ResilientStruct
%4 = function_ref @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
%5 = partial_apply [callee_guaranteed] %4(%1) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
return %5 : $@callee_guaranteed () -> ()
}