mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[SILOptimizer] Preserve arg attrs at cloning.
Arguments are copied into new cloned functions in a number of places. Wherever that happens, be sure to transfer the attributes as well.
This commit is contained in:
@@ -123,8 +123,10 @@ void SILBasicBlock::cloneArgumentList(SILBasicBlock *Other) {
|
|||||||
if (isEntry()) {
|
if (isEntry()) {
|
||||||
assert(args_empty() && "Expected to have no arguments");
|
assert(args_empty() && "Expected to have no arguments");
|
||||||
for (auto *FuncArg : Other->getSILFunctionArguments()) {
|
for (auto *FuncArg : Other->getSILFunctionArguments()) {
|
||||||
createFunctionArgument(FuncArg->getType(),
|
auto *NewArg =
|
||||||
FuncArg->getDecl());
|
createFunctionArgument(FuncArg->getType(), FuncArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(FuncArg->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(FuncArg->getLifetimeAnnotation());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,9 +390,12 @@ void FunctionSignatureTransform::ArgumentExplosionFinalizeOptimizedFunction() {
|
|||||||
|
|
||||||
for (auto *Node : LeafNodes) {
|
for (auto *Node : LeafNodes) {
|
||||||
auto OwnershipKind = *AD.getTransformedOwnershipKind(Node->getType());
|
auto OwnershipKind = *AD.getTransformedOwnershipKind(Node->getType());
|
||||||
LeafValues.push_back(
|
auto *Argument =
|
||||||
BB->insertFunctionArgument(ArgOffset, Node->getType(), OwnershipKind,
|
BB->insertFunctionArgument(ArgOffset, Node->getType(), OwnershipKind,
|
||||||
BB->getArgument(OldArgIndex)->getDecl()));
|
BB->getArgument(OldArgIndex)->getDecl());
|
||||||
|
Argument->setNoImplicitCopy(AD.Arg->isNoImplicitCopy());
|
||||||
|
Argument->setLifetimeAnnotation(AD.Arg->getLifetimeAnnotation());
|
||||||
|
LeafValues.push_back(Argument);
|
||||||
TransformDescriptor.AIM[TotalArgIndex - 1] = AD.Index;
|
TransformDescriptor.AIM[TotalArgIndex - 1] = AD.Index;
|
||||||
++ArgOffset;
|
++ArgOffset;
|
||||||
++TotalArgIndex;
|
++TotalArgIndex;
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ void ExistentialSpecializerCloner::cloneArguments(
|
|||||||
LoweredTy.getCategoryType(ArgDesc.Arg->getType().getCategory());
|
LoweredTy.getCategoryType(ArgDesc.Arg->getType().getCategory());
|
||||||
auto *NewArg =
|
auto *NewArg =
|
||||||
ClonedEntryBB->createFunctionArgument(MappedTy, ArgDesc.Decl);
|
ClonedEntryBB->createFunctionArgument(MappedTy, ArgDesc.Decl);
|
||||||
|
NewArg->setNoImplicitCopy(ArgDesc.Arg->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(ArgDesc.Arg->getLifetimeAnnotation());
|
||||||
NewArg->setOwnershipKind(ValueOwnershipKind(
|
NewArg->setOwnershipKind(ValueOwnershipKind(
|
||||||
NewF, MappedTy, ArgDesc.Arg->getArgumentConvention()));
|
NewF, MappedTy, ArgDesc.Arg->getArgumentConvention()));
|
||||||
entryArgs.push_back(NewArg);
|
entryArgs.push_back(NewArg);
|
||||||
@@ -180,6 +182,8 @@ void ExistentialSpecializerCloner::cloneArguments(
|
|||||||
GenericSILType, ArgDesc.Decl,
|
GenericSILType, ArgDesc.Decl,
|
||||||
ValueOwnershipKind(NewF, GenericSILType,
|
ValueOwnershipKind(NewF, GenericSILType,
|
||||||
ArgDesc.Arg->getArgumentConvention()));
|
ArgDesc.Arg->getArgumentConvention()));
|
||||||
|
NewArg->setNoImplicitCopy(ArgDesc.Arg->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(ArgDesc.Arg->getLifetimeAnnotation());
|
||||||
// Determine the Conformances.
|
// Determine the Conformances.
|
||||||
SILType ExistentialType = ArgDesc.Arg->getType().getObjectType();
|
SILType ExistentialType = ArgDesc.Arg->getType().getObjectType();
|
||||||
CanType OpenedType = NewArg->getType().getASTType();
|
CanType OpenedType = NewArg->getType().getASTType();
|
||||||
@@ -402,7 +406,10 @@ void ExistentialTransform::populateThunkBody() {
|
|||||||
auto *ThunkBody = F->createBasicBlock();
|
auto *ThunkBody = F->createBasicBlock();
|
||||||
for (auto &ArgDesc : ArgumentDescList) {
|
for (auto &ArgDesc : ArgumentDescList) {
|
||||||
auto argumentType = ArgDesc.Arg->getType();
|
auto argumentType = ArgDesc.Arg->getType();
|
||||||
ThunkBody->createFunctionArgument(argumentType, ArgDesc.Decl);
|
auto *NewArg =
|
||||||
|
ThunkBody->createFunctionArgument(argumentType, ArgDesc.Decl);
|
||||||
|
NewArg->setNoImplicitCopy(ArgDesc.Arg->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(ArgDesc.Arg->getLifetimeAnnotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder to add new instructions in the Thunk.
|
/// Builder to add new instructions in the Thunk.
|
||||||
|
|||||||
@@ -566,7 +566,10 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
|
|||||||
F->setInlineStrategy(AlwaysInline);
|
F->setInlineStrategy(AlwaysInline);
|
||||||
SILBasicBlock *ThunkBody = F->createBasicBlock();
|
SILBasicBlock *ThunkBody = F->createBasicBlock();
|
||||||
for (auto &ArgDesc : TransformDescriptor.ArgumentDescList) {
|
for (auto &ArgDesc : TransformDescriptor.ArgumentDescList) {
|
||||||
ThunkBody->createFunctionArgument(ArgDesc.Arg->getType(), ArgDesc.Decl);
|
auto *NewArg =
|
||||||
|
ThunkBody->createFunctionArgument(ArgDesc.Arg->getType(), ArgDesc.Decl);
|
||||||
|
NewArg->setNoImplicitCopy(ArgDesc.Arg->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(ArgDesc.Arg->getLifetimeAnnotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
SILLocation Loc = RegularLocation::getAutoGeneratedLocation();
|
SILLocation Loc = RegularLocation::getAutoGeneratedLocation();
|
||||||
|
|||||||
@@ -197,8 +197,12 @@ void CapturePropagationCloner::cloneClosure(
|
|||||||
|
|
||||||
SILArgument *Arg = OrigEntryBB->getArgument(ArgIdx);
|
SILArgument *Arg = OrigEntryBB->getArgument(ArgIdx);
|
||||||
|
|
||||||
SILValue MappedValue = ClonedEntryBB->createFunctionArgument(
|
auto *MappedValue = ClonedEntryBB->createFunctionArgument(
|
||||||
remapType(Arg->getType()), Arg->getDecl());
|
remapType(Arg->getType()), Arg->getDecl());
|
||||||
|
MappedValue->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(Arg)->isNoImplicitCopy());
|
||||||
|
MappedValue->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(Arg)->getLifetimeAnnotation());
|
||||||
entryArgs.push_back(MappedValue);
|
entryArgs.push_back(MappedValue);
|
||||||
}
|
}
|
||||||
assert(OrigEntryBB->args_size() - ArgIdx == PartialApplyArgs.size()
|
assert(OrigEntryBB->args_size() - ArgIdx == PartialApplyArgs.size()
|
||||||
|
|||||||
@@ -806,8 +806,12 @@ void ClosureSpecCloner::populateCloned() {
|
|||||||
|
|
||||||
// Otherwise, create a new argument which copies the original argument
|
// Otherwise, create a new argument which copies the original argument
|
||||||
auto typeInContext = Cloned->getLoweredType(Arg->getType());
|
auto typeInContext = Cloned->getLoweredType(Arg->getType());
|
||||||
SILValue MappedValue =
|
auto *MappedValue =
|
||||||
ClonedEntryBB->createFunctionArgument(typeInContext, Arg->getDecl());
|
ClonedEntryBB->createFunctionArgument(typeInContext, Arg->getDecl());
|
||||||
|
MappedValue->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(Arg)->isNoImplicitCopy());
|
||||||
|
MappedValue->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(Arg)->getLifetimeAnnotation());
|
||||||
entryArgs.push_back(MappedValue);
|
entryArgs.push_back(MappedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -491,8 +491,12 @@ void ClosureCloner::populateCloned() {
|
|||||||
for (; ai != ae; ++argNo, ++ai) {
|
for (; ai != ae; ++argNo, ++ai) {
|
||||||
if (!promotableIndices.count(argNo)) {
|
if (!promotableIndices.count(argNo)) {
|
||||||
// Simply create a new argument which copies the original argument
|
// Simply create a new argument which copies the original argument
|
||||||
SILValue mappedValue = clonedEntryBB->createFunctionArgument(
|
auto *mappedValue = clonedEntryBB->createFunctionArgument(
|
||||||
(*ai)->getType(), (*ai)->getDecl());
|
(*ai)->getType(), (*ai)->getDecl());
|
||||||
|
mappedValue->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(*ai)->isNoImplicitCopy());
|
||||||
|
mappedValue->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(*ai)->getLifetimeAnnotation());
|
||||||
entryArgs.push_back(mappedValue);
|
entryArgs.push_back(mappedValue);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -504,8 +508,13 @@ void ClosureCloner::populateCloned() {
|
|||||||
auto boxedTy = getSILBoxFieldType(TypeExpansionContext(*cloned), boxTy,
|
auto boxedTy = getSILBoxFieldType(TypeExpansionContext(*cloned), boxTy,
|
||||||
cloned->getModule().Types, 0)
|
cloned->getModule().Types, 0)
|
||||||
.getObjectType();
|
.getObjectType();
|
||||||
SILValue mappedValue =
|
auto *newArg =
|
||||||
clonedEntryBB->createFunctionArgument(boxedTy, (*ai)->getDecl());
|
clonedEntryBB->createFunctionArgument(boxedTy, (*ai)->getDecl());
|
||||||
|
newArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(*ai)->isNoImplicitCopy());
|
||||||
|
newArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(*ai)->getLifetimeAnnotation());
|
||||||
|
SILValue mappedValue = newArg;
|
||||||
|
|
||||||
// If SIL ownership is enabled, we need to perform a borrow here if we have
|
// If SIL ownership is enabled, we need to perform a borrow here if we have
|
||||||
// a non-trivial value. We know that our value is not written to and it does
|
// a non-trivial value. We know that our value is not written to and it does
|
||||||
|
|||||||
@@ -799,6 +799,10 @@ PromotedParamCloner::populateCloned() {
|
|||||||
Cloned->getModule().Types, 0);
|
Cloned->getModule().Types, 0);
|
||||||
auto *promotedArg =
|
auto *promotedArg =
|
||||||
ClonedEntryBB->createFunctionArgument(promotedTy, (*I)->getDecl());
|
ClonedEntryBB->createFunctionArgument(promotedTy, (*I)->getDecl());
|
||||||
|
promotedArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(*I)->isNoImplicitCopy());
|
||||||
|
promotedArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(*I)->getLifetimeAnnotation());
|
||||||
OrigPromotedParameters.insert(*I);
|
OrigPromotedParameters.insert(*I);
|
||||||
|
|
||||||
NewPromotedArgs[ArgNo] = promotedArg;
|
NewPromotedArgs[ArgNo] = promotedArg;
|
||||||
@@ -811,8 +815,13 @@ PromotedParamCloner::populateCloned() {
|
|||||||
entryArgs.push_back(SILValue());
|
entryArgs.push_back(SILValue());
|
||||||
} else {
|
} else {
|
||||||
// Create a new argument which copies the original argument.
|
// Create a new argument which copies the original argument.
|
||||||
entryArgs.push_back(ClonedEntryBB->createFunctionArgument(
|
auto *newArg = ClonedEntryBB->createFunctionArgument((*I)->getType(),
|
||||||
(*I)->getType(), (*I)->getDecl()));
|
(*I)->getDecl());
|
||||||
|
newArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(*I)->isNoImplicitCopy());
|
||||||
|
newArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(*I)->getLifetimeAnnotation());
|
||||||
|
entryArgs.push_back(newArg);
|
||||||
}
|
}
|
||||||
++ArgNo;
|
++ArgNo;
|
||||||
++I;
|
++I;
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ void MapOpaqueArchetypes::replace() {
|
|||||||
SILType mappedType = remapType(origArg->getType());
|
SILType mappedType = remapType(origArg->getType());
|
||||||
auto *NewArg = clonedEntryBlock->createFunctionArgument(
|
auto *NewArg = clonedEntryBlock->createFunctionArgument(
|
||||||
mappedType, origArg->getDecl(), true);
|
mappedType, origArg->getDecl(), true);
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(origArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(origArg)->getLifetimeAnnotation());
|
||||||
entryArgs.push_back(NewArg);
|
entryArgs.push_back(NewArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ void GenericCloner::populateCloned() {
|
|||||||
mappedType = mappedType.getObjectType();
|
mappedType = mappedType.getObjectType();
|
||||||
auto *NewArg = ClonedEntryBB->createFunctionArgument(
|
auto *NewArg = ClonedEntryBB->createFunctionArgument(
|
||||||
mappedType, OrigArg->getDecl());
|
mappedType, OrigArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(OrigArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(OrigArg)->getLifetimeAnnotation());
|
||||||
|
|
||||||
// Try to create a new debug_value from an existing debug_value w/
|
// Try to create a new debug_value from an existing debug_value w/
|
||||||
// address value for the argument. We do this before storing to
|
// address value for the argument. We do this before storing to
|
||||||
@@ -164,6 +168,10 @@ void GenericCloner::populateCloned() {
|
|||||||
if (!handleConversion()) {
|
if (!handleConversion()) {
|
||||||
auto *NewArg =
|
auto *NewArg =
|
||||||
ClonedEntryBB->createFunctionArgument(mappedType, OrigArg->getDecl());
|
ClonedEntryBB->createFunctionArgument(mappedType, OrigArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(OrigArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(OrigArg)->getLifetimeAnnotation());
|
||||||
entryArgs.push_back(NewArg);
|
entryArgs.push_back(NewArg);
|
||||||
}
|
}
|
||||||
++ArgIdx;
|
++ArgIdx;
|
||||||
|
|||||||
@@ -2544,8 +2544,12 @@ SILFunction *ReabstractionThunkGenerator::createThunk() {
|
|||||||
|
|
||||||
if (!SILModuleConventions(M).useLoweredAddresses()) {
|
if (!SILModuleConventions(M).useLoweredAddresses()) {
|
||||||
for (auto SpecArg : SpecializedFunc->getArguments()) {
|
for (auto SpecArg : SpecializedFunc->getArguments()) {
|
||||||
SILArgument *NewArg = EntryBB->createFunctionArgument(SpecArg->getType(),
|
auto *NewArg = EntryBB->createFunctionArgument(SpecArg->getType(),
|
||||||
SpecArg->getDecl());
|
SpecArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->getLifetimeAnnotation());
|
||||||
Arguments.push_back(NewArg);
|
Arguments.push_back(NewArg);
|
||||||
}
|
}
|
||||||
FullApplySite ApplySite = createReabstractionThunkApply(Builder);
|
FullApplySite ApplySite = createReabstractionThunkApply(Builder);
|
||||||
@@ -2642,8 +2646,12 @@ SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
|
|||||||
auto cloneSpecializedArgument = [&]() {
|
auto cloneSpecializedArgument = [&]() {
|
||||||
// No change to the argument.
|
// No change to the argument.
|
||||||
SILArgument *SpecArg = *SpecArgIter++;
|
SILArgument *SpecArg = *SpecArgIter++;
|
||||||
SILArgument *NewArg =
|
auto *NewArg =
|
||||||
EntryBB->createFunctionArgument(SpecArg->getType(), SpecArg->getDecl());
|
EntryBB->createFunctionArgument(SpecArg->getType(), SpecArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->getLifetimeAnnotation());
|
||||||
Arguments.push_back(NewArg);
|
Arguments.push_back(NewArg);
|
||||||
};
|
};
|
||||||
// ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
|
// ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
|
||||||
@@ -2685,6 +2693,10 @@ SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
|
|||||||
SILArgument *SpecArg = *SpecArgIter++;
|
SILArgument *SpecArg = *SpecArgIter++;
|
||||||
SILFunctionArgument *NewArg =
|
SILFunctionArgument *NewArg =
|
||||||
EntryBB->createFunctionArgument(ParamTy, SpecArg->getDecl());
|
EntryBB->createFunctionArgument(ParamTy, SpecArg->getDecl());
|
||||||
|
NewArg->setNoImplicitCopy(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->isNoImplicitCopy());
|
||||||
|
NewArg->setLifetimeAnnotation(
|
||||||
|
cast<SILFunctionArgument>(SpecArg)->getLifetimeAnnotation());
|
||||||
if (!NewArg->getArgumentConvention().isGuaranteedConvention()) {
|
if (!NewArg->getArgumentConvention().isGuaranteedConvention()) {
|
||||||
SILValue argVal = Builder.emitLoadValueOperation(
|
SILValue argVal = Builder.emitLoadValueOperation(
|
||||||
Loc, NewArg, LoadOwnershipQualifier::Take);
|
Loc, NewArg, LoadOwnershipQualifier::Take);
|
||||||
|
|||||||
@@ -46,6 +46,22 @@ public struct ResilientContainer {
|
|||||||
let x = computedProperty
|
let x = computedProperty
|
||||||
print(x)
|
print(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
@_eagerMove
|
||||||
|
@_specialize(where T == Int)
|
||||||
|
public func genericEagerMoveInlineableContext<T>(_ t: T) {
|
||||||
|
let x = computedProperty
|
||||||
|
print(x)
|
||||||
|
print(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
@_eagerMove
|
||||||
|
public func eagerMoveInlineableContext() {
|
||||||
|
let x = computedProperty
|
||||||
|
print(x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct WrapperP2<Wrapped: ExternalP2>: ExternalP2 {
|
public struct WrapperP2<Wrapped: ExternalP2>: ExternalP2 {
|
||||||
|
|||||||
49
test/SILOptimizer/allocbox_to_stack_ownership_attrs.sil
Normal file
49
test/SILOptimizer/allocbox_to_stack_ownership_attrs.sil
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -allocbox-to-stack -enable-copy-propagation=requested-passes-only -enable-lexical-borrow-scopes=false | %FileCheck %s
|
||||||
|
|
||||||
|
sil_stage raw
|
||||||
|
|
||||||
|
protocol P {}
|
||||||
|
|
||||||
|
|
||||||
|
sil [ossa] @callWithAutoclosure_3 : $@convention(thin) <T where T : P> (@in T) -> () {
|
||||||
|
bb0(%0 : $*T):
|
||||||
|
debug_value %0 : $*T, expr op_deref
|
||||||
|
%2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
||||||
|
%3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
||||||
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
||||||
|
%4c = mark_uninitialized [var] %4 : $<τ_0_0> { var τ_0_0 } <T>
|
||||||
|
%4a = project_box %4c : $<τ_0_0> { var τ_0_0 } <T>, 0
|
||||||
|
%4copy = copy_value %4c : $<τ_0_0> { var τ_0_0 } <T>
|
||||||
|
copy_addr %0 to [initialization] %4a : $*T
|
||||||
|
%6 = partial_apply %3<T>(%4copy) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
||||||
|
%7 = apply %2<T>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
||||||
|
destroy_addr %0 : $*T
|
||||||
|
destroy_value %4c : $<τ_0_0> { var τ_0_0 } <T>
|
||||||
|
%9 = tuple ()
|
||||||
|
return %9 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s21closure_to_specializeTf0ns_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $*T, {{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s21closure_to_specializeTf0ns_n'
|
||||||
|
sil shared [ossa] @closure_to_specialize : $@convention(thin) <T where T : P> (@owned <τ_0_0> { var τ_0_0 } <T>) -> @out T {
|
||||||
|
bb0(%0 : @_eagerMove $*T, %1 : @_eagerMove @owned $<τ_0_0> { var τ_0_0 } <T>):
|
||||||
|
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
||||||
|
copy_addr %2 to [initialization] %0 : $*T
|
||||||
|
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <T>
|
||||||
|
%5 = tuple ()
|
||||||
|
return %5 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> () {
|
||||||
|
bb0(%0 : @owned $@callee_owned () -> @out U):
|
||||||
|
debug_value %0 : $@callee_owned () -> @out U
|
||||||
|
%1 = copy_value %0 : $@callee_owned () -> @out U
|
||||||
|
%3 = alloc_stack $U
|
||||||
|
%4 = apply %1(%3) : $@callee_owned () -> @out U
|
||||||
|
destroy_addr %3 : $*U
|
||||||
|
dealloc_stack %3 : $*U
|
||||||
|
destroy_value %0 : $@callee_owned () -> @out U
|
||||||
|
%8 = tuple ()
|
||||||
|
return %8 : $()
|
||||||
|
}
|
||||||
62
test/SILOptimizer/capture_promotion_attr.sil
Normal file
62
test/SILOptimizer/capture_promotion_attr.sil
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -capture-prop | %FileCheck %s
|
||||||
|
|
||||||
|
sil_stage raw
|
||||||
|
|
||||||
|
import Builtin
|
||||||
|
import Swift
|
||||||
|
|
||||||
|
class C {}
|
||||||
|
|
||||||
|
sil [ossa] @getC : $@convention(thin) () -> @owned C
|
||||||
|
|
||||||
|
sil [ossa] @test_capture_propagation : $@convention(thin) () -> () {
|
||||||
|
bb0:
|
||||||
|
%addr = alloc_stack $C
|
||||||
|
%getC = function_ref @getC : $@convention(thin) () -> @owned C
|
||||||
|
%c1 = apply %getC() : $@convention(thin) () -> @owned C
|
||||||
|
store %c1 to [init] %addr : $*C
|
||||||
|
|
||||||
|
%closure = function_ref @closure : $@convention(thin) (@owned C) -> ()
|
||||||
|
%thick_closure = thin_to_thick_function %closure : $@convention(thin) (@owned C) -> () to $@callee_owned (@owned C) -> ()
|
||||||
|
|
||||||
|
%thunk = function_ref @thunk : $@convention(thin) (@in C, @owned @callee_owned (@owned C) -> ()) -> ()
|
||||||
|
%thunked_closure = partial_apply %thunk(%thick_closure) : $@convention(thin) (@in C, @owned @callee_owned (@owned C) -> ()) -> ()
|
||||||
|
|
||||||
|
%apply_closure = function_ref @apply_closure : $@convention(thin) (@in C, @owned @callee_owned (@in C) -> ()) -> ()
|
||||||
|
apply %apply_closure(%addr, %thunked_closure) : $@convention(thin) (@in C, @owned @callee_owned (@in C) -> ()) -> ()
|
||||||
|
|
||||||
|
dealloc_stack %addr : $*C
|
||||||
|
%retval = tuple ()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sil [ossa] @closure : $@convention(thin) (@owned C) -> () {
|
||||||
|
bb0(%0 : @owned $C):
|
||||||
|
destroy_value %0 : $C
|
||||||
|
%retval = tuple ()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s5thunk7closureTf3npf_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s5thunk7closureTf3npf_n'
|
||||||
|
sil [ossa] [transparent] @thunk : $@convention(thin) (@in C, @owned @callee_owned (@owned C) -> ()) -> () {
|
||||||
|
bb0(%addr : @_eagerMove $*C, %closure : @owned $@callee_owned (@owned C) -> ()):
|
||||||
|
%instance = load [take] %addr : $*C
|
||||||
|
apply %closure(%instance) : $@callee_owned (@owned C) -> ()
|
||||||
|
%retval = tuple ()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sil [ossa] [noinline] @apply_closure : $@convention(thin) (@in C, @owned @callee_owned (@in C) -> ()) -> () {
|
||||||
|
bb0(%addr : $*C, %closure : @owned $@callee_owned (@in C) -> ()):
|
||||||
|
%stack_addr = alloc_stack $C
|
||||||
|
%instance = load [take] %addr : $*C
|
||||||
|
store %instance to [init] %stack_addr : $*C
|
||||||
|
apply %closure(%stack_addr) : $@callee_owned (@in C) -> ()
|
||||||
|
dealloc_stack %stack_addr : $*C
|
||||||
|
%retval = tuple ()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
54
test/SILOptimizer/capture_promotion_attrs.sil
Normal file
54
test/SILOptimizer/capture_promotion_attrs.sil
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -capture-prop | %FileCheck %s
|
||||||
|
|
||||||
|
sil_stage raw
|
||||||
|
|
||||||
|
import Builtin
|
||||||
|
import Swift
|
||||||
|
|
||||||
|
class C {}
|
||||||
|
|
||||||
|
struct Str {
|
||||||
|
@_hasStorage var a: C { get set }
|
||||||
|
}
|
||||||
|
|
||||||
|
sil @calleeWithKeypath : $@convention(thin) (@noescape @callee_guaranteed (@owned Str) -> @owned C) -> ()
|
||||||
|
sil @swift_getAtKeyPath : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil [ossa] @testKeypathNoescapeOSSA
|
||||||
|
// CHECK: [[K:%[0-9]+]] = keypath
|
||||||
|
// CHECK: [[C:%[0-9]+]] = function_ref @$s22closureWithKeypathOSSA{{.*}}main3StrVAC1CCTf3npk_n
|
||||||
|
// CHECK: [[T:%[0-9]+]] = thin_to_thick_function [[C]]
|
||||||
|
// CHECK: [[F:%[0-9]+]] = function_ref @calleeWithKeypath
|
||||||
|
// CHECK: apply [[F]]([[T]])
|
||||||
|
// CHECK: destroy_value [[K]]
|
||||||
|
// CHECK: } // end sil function 'testKeypathNoescapeOSSA'
|
||||||
|
sil [ossa] @testKeypathNoescapeOSSA : $@convention(thin) () -> () {
|
||||||
|
bb0:
|
||||||
|
%0 = keypath $KeyPath<Str, C>, (root $Str; stored_property #Str.a : $C)
|
||||||
|
%1 = function_ref @closureWithKeypathOSSA : $@convention(thin) (@owned Str, @guaranteed KeyPath<Str, C>) -> @owned C
|
||||||
|
%2 = partial_apply [callee_guaranteed] [on_stack] %1(%0) : $@convention(thin) (@owned Str, @guaranteed KeyPath<Str, C>) -> @owned C
|
||||||
|
%4 = function_ref @calleeWithKeypath : $@convention(thin) (@noescape @callee_guaranteed (@owned Str) -> @owned C) -> ()
|
||||||
|
%5 = apply %4(%2) : $@convention(thin) (@noescape @callee_guaranteed (@owned Str) -> @owned C) -> ()
|
||||||
|
dealloc_stack %2 : $@noescape @callee_guaranteed (@owned Str) -> @owned C
|
||||||
|
destroy_value %0 : $KeyPath<Str, C>
|
||||||
|
%7 = tuple ()
|
||||||
|
return %7 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s22closureWithKeypathOSSA{{.*}}main3StrVAC1CCTf3npk_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $
|
||||||
|
// CHECK: } // end sil function '$s22closureWithKeypathOSSA{{.*}}main3StrVAC1CCTf3npk_n'
|
||||||
|
sil [ossa] @closureWithKeypathOSSA : $@convention(thin) (@owned Str, @guaranteed KeyPath<Str, C>) -> @owned C {
|
||||||
|
bb0(%0 : @_eagerMove @owned $Str, %1 : @guaranteed $KeyPath<Str, C>):
|
||||||
|
%4 = alloc_stack $Str
|
||||||
|
store %0 to [init] %4 : $*Str
|
||||||
|
%6 = function_ref @swift_getAtKeyPath : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
|
||||||
|
%7 = alloc_stack $C
|
||||||
|
%8 = apply %6<Str, C>(%7, %4, %1) : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
|
||||||
|
%9 = load [take] %7 : $*C
|
||||||
|
dealloc_stack %7 : $*C
|
||||||
|
destroy_addr %4 : $*Str
|
||||||
|
dealloc_stack %4 : $*Str
|
||||||
|
return %9 : $C
|
||||||
|
}
|
||||||
|
|
||||||
46
test/SILOptimizer/closure_specialize_attrs.sil
Normal file
46
test/SILOptimizer/closure_specialize_attrs.sil
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// RUN: %target-sil-opt -enable-sil-verify-all -closure-specialize %s | %FileCheck %s
|
||||||
|
|
||||||
|
import Builtin
|
||||||
|
|
||||||
|
class C {}
|
||||||
|
|
||||||
|
sil [ossa] @getC : $@convention(thin) () -> @owned C
|
||||||
|
|
||||||
|
// Verify that the argument to the specialized take_closure is still @_eagerMove.
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s12take_closure0B04main1CCTf1nc_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $C, {{%[^,]+}} :
|
||||||
|
// CHECK-LABEL: } // end sil function '$s12take_closure0B04main1CCTf1nc_n'
|
||||||
|
|
||||||
|
sil [ossa] [noinline] @take_closure : $@convention(thin) (@owned C, @noescape @callee_guaranteed (@owned C, @owned C) -> ()) -> () {
|
||||||
|
bb0(%c : @_eagerMove @owned $C, %0 : $@noescape @callee_guaranteed (@owned C, @owned C) -> ()):
|
||||||
|
%getC = function_ref @getC : $@convention(thin) () -> @owned C
|
||||||
|
%c1 = apply %getC() : $@convention(thin) () -> @owned C
|
||||||
|
%c2 = apply %getC() : $@convention(thin) () -> @owned C
|
||||||
|
%3 = apply %0(%c1, %c2) : $@noescape @callee_guaranteed (@owned C, @owned C) -> ()
|
||||||
|
destroy_value %c : $C
|
||||||
|
%retval = tuple()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil shared [ossa] @closure : $@convention(thin) (@owned C, @owned C, @owned C) -> () {
|
||||||
|
bb0(%0 : @owned $C, %1 : @owned $C, %2 : @owned $C):
|
||||||
|
destroy_value %0 : $C
|
||||||
|
destroy_value %1 : $C
|
||||||
|
destroy_value %2 : $C
|
||||||
|
%15 = tuple ()
|
||||||
|
return %15 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil @caller : $@convention(thin) (@owned C) -> () {
|
||||||
|
bb0(%0 : $C):
|
||||||
|
%3 = function_ref @closure : $@convention(thin) (@owned C, @owned C, @owned C) -> ()
|
||||||
|
%4 = partial_apply [callee_guaranteed] [on_stack] %3(%0) : $@convention(thin) (@owned C, @owned C, @owned C) -> ()
|
||||||
|
%take_closure = function_ref @take_closure : $@convention(thin) (@owned C, @noescape @callee_guaranteed (@owned C, @owned C) -> ()) -> ()
|
||||||
|
strong_retain %0 : $C
|
||||||
|
%5 = apply %take_closure(%0, %4) : $@convention(thin) (@owned C, @noescape @callee_guaranteed (@owned C, @owned C) -> ()) -> ()
|
||||||
|
strong_release %0 : $C
|
||||||
|
dealloc_stack %4 : $@noescape @callee_guaranteed (@owned C, @owned C) -> ()
|
||||||
|
%retval = tuple()
|
||||||
|
return %retval : $()
|
||||||
|
}
|
||||||
68
test/SILOptimizer/eager_specialize_ossa_attr.sil
Normal file
68
test/SILOptimizer/eager_specialize_ossa_attr.sil
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// RUN: %target-sil-opt -enable-sil-verify-all -eager-specializer %s | %FileCheck %s
|
||||||
|
|
||||||
|
import Swift
|
||||||
|
|
||||||
|
public protocol AnElt {
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol HasElt {
|
||||||
|
associatedtype Elt
|
||||||
|
init(e: Elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X : AnElt {
|
||||||
|
@_hasStorage var i: Int { get set }
|
||||||
|
init(i: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S : HasElt {
|
||||||
|
typealias Elt = X
|
||||||
|
@_hasStorage var e: X { get set }
|
||||||
|
init(e: Elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Klass {}
|
||||||
|
|
||||||
|
class EltTrivialKlass : AnElt {
|
||||||
|
var i: Int { get set }
|
||||||
|
init(i: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerKlass : HasElt {
|
||||||
|
typealias Elt = EltTrivialKlass
|
||||||
|
var e: Elt { get set }
|
||||||
|
required init(e: Elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct G<Container : HasElt> {
|
||||||
|
var container: Container? = nil
|
||||||
|
public func getContainer(e: Container.Elt) -> Container
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct GTrivial<Container : HasElt> {
|
||||||
|
public func getContainer(e: Container.Elt) -> Container
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil [ossa] @callee : $@convention(method) <Container where Container : HasElt> (@in Container.Elt, @in_guaranteed G<Container>) -> @out Container {
|
||||||
|
bb0(%0 : $*Container, %1 : $*Container.Elt, %2 : $*G<Container>):
|
||||||
|
%4 = witness_method $Container, #HasElt.init!allocator : $@convention(witness_method: HasElt) <τ_0_0 where τ_0_0 : HasElt> (@in τ_0_0.Elt, @thick τ_0_0.Type) -> @out τ_0_0
|
||||||
|
%5 = metatype $@thick Container.Type
|
||||||
|
%6 = apply %4<Container>(%0, %1, %5) : $@convention(witness_method: HasElt) <τ_0_0 where τ_0_0 : HasElt> (@in τ_0_0.Elt, @thick τ_0_0.Type) -> @out τ_0_0
|
||||||
|
%7 = tuple ()
|
||||||
|
return %7 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s6caller4main1SV_Tg5 : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $G<S>, {{%[^,]+}} :
|
||||||
|
// CHECK-LABEL: } // end sil function '$s6caller4main1SV_Tg5'
|
||||||
|
|
||||||
|
sil [_specialize where T == S] [ossa] @caller : $@convention(thin) <T where T : HasElt, T.Elt : AnElt> (@in_guaranteed G<T>, @in T.Elt) -> @out T {
|
||||||
|
bb0(%0 : $*T, %1 : @_eagerMove $*G<T>, %2 : $*T.Elt):
|
||||||
|
%5 = function_ref @callee : $@convention(method) <τ_0_0 where τ_0_0 : HasElt> (@in τ_0_0.Elt, @in_guaranteed G<τ_0_0>) -> @out τ_0_0
|
||||||
|
%6 = apply %5<T>(%0, %2, %1) : $@convention(method) <τ_0_0 where τ_0_0 : HasElt> (@in τ_0_0.Elt, @in_guaranteed G<τ_0_0>) -> @out τ_0_0
|
||||||
|
%7 = tuple ()
|
||||||
|
return %7 : $()
|
||||||
|
}
|
||||||
|
|
||||||
58
test/SILOptimizer/functionsigopts_attrs.swift
Normal file
58
test/SILOptimizer/functionsigopts_attrs.swift
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// RUN: %target-swift-frontend -module-name main -O -emit-sil -primary-file %s | %FileCheck %s
|
||||||
|
|
||||||
|
protocol P {
|
||||||
|
func foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {}
|
||||||
|
|
||||||
|
public struct Inner {
|
||||||
|
var x: C
|
||||||
|
var y: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct S : P {
|
||||||
|
var i: Inner
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
print(i.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@_silgen_name("barrier")
|
||||||
|
func barrier()
|
||||||
|
|
||||||
|
// The specializations should be @_eagerMove.
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s4main27callee_guaranteed_eagerMoveyyAA1P_pFTf4e_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s4main27callee_guaranteed_eagerMoveyyAA1P_pFTf4e_n'
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s4main27callee_guaranteed_eagerMoveyyAA1P_pFTf4e_nAA1SV_Tg5Tf4x_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove
|
||||||
|
// CHECK-LABEL: } // end sil function '$s4main27callee_guaranteed_eagerMoveyyAA1P_pFTf4e_nAA1SV_Tg5Tf4x_n'
|
||||||
|
@inline(never)
|
||||||
|
func callee_guaranteed_eagerMove(@_eagerMove _ p: P) {
|
||||||
|
p.foo()
|
||||||
|
barrier()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func caller_guaranteed_eagerMove(s: S) {
|
||||||
|
callee_guaranteed_eagerMove(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s4main22callee_owned_eagerMoveyyAA1P_pnFTf4e_nTf4g_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s4main22callee_owned_eagerMoveyyAA1P_pnFTf4e_nTf4g_n'
|
||||||
|
// CHECK-LABEL: sil {{.*}}@$s4main22callee_owned_eagerMoveyyAA1P_pnFTf4e_nAA1SV_Tg5Tf4gX_n : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s4main22callee_owned_eagerMoveyyAA1P_pnFTf4e_nAA1SV_Tg5Tf4gX_n'
|
||||||
|
@inline(never)
|
||||||
|
func callee_owned_eagerMove(@_eagerMove _ p: __owned P) {
|
||||||
|
p.foo()
|
||||||
|
barrier()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func caller_owned_eagerMove(s: S) {
|
||||||
|
callee_owned_eagerMove(s)
|
||||||
|
}
|
||||||
@@ -372,12 +372,23 @@ public func testResilientInlinablePropertyCallsResilientInlinable() {
|
|||||||
useP(r.inlineablePropertyCallsResilientInlineable.myValue3())
|
useP(r.inlineablePropertyCallsResilientInlineable.myValue3())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RESILIENT-LABEL: sil {{.*}}@$s9External218ResilientContainerV33genericEagerMoveInlineableContextyyxlFSi_Tgq5 : {{.*}}{
|
||||||
|
// RESILIENT: {{bb[0-9]+}}({{%[^,]+}} : $Int, {{%[^,]+}} : @_eagerMove $
|
||||||
|
// RESILIENT-LABEL: } // end sil function '$s9External218ResilientContainerV33genericEagerMoveInlineableContextyyxlFSi_Tgq5'
|
||||||
|
|
||||||
|
// RESILIENT-LABEL: sil [serialized] [canonical] @$s9External218ResilientContainerV33genericEagerMoveInlineableContextyyxlF : {{.*}} {
|
||||||
|
// RESILIENT: {{bb[0-9]+}}({{%[^,]+}} : $*T, {{%[^,]+}} : @_eagerMove $
|
||||||
|
// RESILIENT-LABEL: } // end sil function '$s9External218ResilientContainerV33genericEagerMoveInlineableContextyyxlF'
|
||||||
|
|
||||||
|
// RESILIENT-LABEL: sil [serialized] [canonical] @$s9External218ResilientContainerV26eagerMoveInlineableContextyyF : $@convention(method) (@in_guaranteed ResilientContainer) -> () {
|
||||||
|
// RESILIENT: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// RESILIENT-LABEL: } // end sil function '$s9External218ResilientContainerV26eagerMoveInlineableContextyyF'
|
||||||
|
|
||||||
// RESILIENT-LABEL: sil [serialized] [canonical] @$s9External218ResilientContainerV17inlineableContextyyF
|
// RESILIENT-LABEL: sil [serialized] [canonical] @$s9External218ResilientContainerV17inlineableContextyyF
|
||||||
// RESILIENT: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0)
|
// RESILIENT: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0)
|
||||||
// RESILIENT: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV16computedPropertyQrvg
|
// RESILIENT: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV16computedPropertyQrvg
|
||||||
// RESILIENT: apply [[FUN]]([[RES]], %0)
|
// RESILIENT: apply [[FUN]]([[RES]], %0)
|
||||||
|
|
||||||
|
|
||||||
public protocol P4 {
|
public protocol P4 {
|
||||||
associatedtype AT
|
associatedtype AT
|
||||||
func foo(_ x: Int64) -> AT
|
func foo(_ x: Int64) -> AT
|
||||||
@@ -390,6 +401,19 @@ struct PA : P4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class K {}
|
||||||
|
|
||||||
|
public protocol P4EM {
|
||||||
|
associatedtype AT
|
||||||
|
func foo(@_eagerMove _ x: K) -> AT
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PAEM : P4EM {
|
||||||
|
func foo(@_eagerMove _ x: K) -> some P {
|
||||||
|
return 5 as Int64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: sil private [transparent] [thunk] @$s1A2PAVAA2P4A2aDP4testyyFTW
|
// CHECK-LABEL: sil private [transparent] [thunk] @$s1A2PAVAA2P4A2aDP4testyyFTW
|
||||||
// CHECK: [[V:%.*]] = load %0 : $*PA
|
// CHECK: [[V:%.*]] = load %0 : $*PA
|
||||||
// CHECK: [[F:%.*]] = function_ref @$s1A2PAV4testyyF
|
// CHECK: [[F:%.*]] = function_ref @$s1A2PAV4testyyF
|
||||||
@@ -426,6 +450,28 @@ public func testPartialApply() {
|
|||||||
testPartialApply(PA())
|
testPartialApply(PA())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil shared [noinline] @$s1A25testPartialApplyEagerMoveyyxAA4P4EMRzlFAA4PAEMV_Tg5 : {{.*}}{
|
||||||
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove $
|
||||||
|
// CHECK-LABEL: } // end sil function '$s1A25testPartialApplyEagerMoveyyxAA4P4EMRzlFAA4PAEMV_Tg5'
|
||||||
|
|
||||||
|
@inline(never)
|
||||||
|
func testItEagerMove<T>(cl: (K) throws -> T) {
|
||||||
|
do {
|
||||||
|
print(try cl(K()))
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(never)
|
||||||
|
func testPartialApplyEagerMove<T: P4EM>(@_eagerMove _ t: T) {
|
||||||
|
let fun = t.foo
|
||||||
|
testItEagerMove(cl: fun)
|
||||||
|
print(fun(K()))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func testPartialApplyEagerMove() {
|
||||||
|
testPartialApplyEagerMove(PAEM())
|
||||||
|
}
|
||||||
|
|
||||||
struct Trivial<T> {
|
struct Trivial<T> {
|
||||||
var x : Int64
|
var x : Int64
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user