Capture Promotion: have new closures inserted before their original versions

Swift SVN r10554
This commit is contained in:
Stephen Lin
2013-11-19 03:29:00 +00:00
parent cacdcabad1
commit 4ebdf9c80f
4 changed files with 35 additions and 33 deletions

View File

@@ -84,7 +84,8 @@ public:
SILFunction(SILModule &Module, SILLinkage Linkage, SILFunction(SILModule &Module, SILLinkage Linkage,
StringRef MangledName, SILType LoweredType, StringRef MangledName, SILType LoweredType,
Optional<SILLocation> Loc = Nothing, Optional<SILLocation> Loc = Nothing,
IsTransparent_t isTrans = IsNotTransparent); IsTransparent_t isTrans = IsNotTransparent,
SILFunction *InsertBefore = nullptr);
~SILFunction(); ~SILFunction();

View File

@@ -18,7 +18,8 @@ using namespace swift;
SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
StringRef Name, SILType LoweredType, StringRef Name, SILType LoweredType,
Optional<SILLocation> Loc, Optional<SILLocation> Loc,
IsTransparent_t isTrans) IsTransparent_t isTrans,
SILFunction *InsertBefore)
: ModuleAndLinkage(&Module, Linkage), : ModuleAndLinkage(&Module, Linkage),
Name(Name), Name(Name),
LoweredType(LoweredType), LoweredType(LoweredType),
@@ -26,7 +27,10 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
DeclCtx(nullptr), DeclCtx(nullptr),
DebugScope(nullptr), DebugScope(nullptr),
Transparent(isTrans) { Transparent(isTrans) {
Module.functions.push_back(this); if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
else
Module.functions.push_back(this);
} }
SILFunction::~SILFunction() { SILFunction::~SILFunction() {

View File

@@ -305,13 +305,10 @@ ClosureCloner::initCloned(SILFunction *Orig, IndicesSet &PromotableIndices) {
OrigLoweredTy.getAs<AnyFunctionType>().getResult(), OrigLoweredTy.getAs<AnyFunctionType>().getResult(),
M.getASTContext())); M.getASTContext()));
// FIXME: This should insert the cloned function right before the existing // This inserts the new cloned function before the original function.
// SILFunction for the closure, so that these naturally clump together and
// so that testcases are easier to write. This can be done by creating the
// function then using the splice method on the module's ilist of functions.
return new (M) SILFunction(M, SILLinkage::Internal, ClonedName, return new (M) SILFunction(M, SILLinkage::Internal, ClonedName,
M.Types.getLoweredType(ClonedTy), M.Types.getLoweredType(ClonedTy),
Orig->getLocation()); Orig->getLocation(), IsNotTransparent, Orig);
} }
/// \brief Populate the body of the cloned closure, modifying instructions as /// \brief Populate the body of the cloned closure, modifying instructions as

View File

@@ -82,6 +82,31 @@ bb0:
return %21 : $() -> Int64 return %21 : $() -> Int64
} }
// CHECK-LABEL: sil internal @closure0_promote0 : $@thin (Foo, Baz, Int64) -> Int64
// CHECK: [[DUMMY_FUNC:%.*]] = function_ref @dummy_func : $@thin (a: Int64, b: Int64, c: Int64) -> Int64
// The load of %1 is removed, and its uses replaced with the Foo argument
// CHECK-NEXT: strong_retain {{.*}} : $Foo
// CHECK-NEXT: [[METHOD_FOO:%.*]] = class_method {{.*}} : $Foo, #Foo.foo!1 : $@cc(method) @thin ((), Foo) -> Int64
// CHECK-NEXT: [[APPLY_FOO:%.*]] = apply [[METHOD_FOO]]({{.*}}) : $@cc(method) @thin ((), Foo) -> Int64
// The struct_element_addr of %3 followed by a load is replaced by a struct_extract of the Baz argument
// CHECK-NEXT: [[EXTRACT_BAZ_X:%.*]] = struct_extract {{.*}} : $Baz, #x
// CHECK-NEXT: [[RETVAL:%.*]] = apply [[DUMMY_FUNC]]([[APPLY_FOO]], [[EXTRACT_BAZ_X]], {{.*}}) : $@thin (a: Int64, b: Int64, c: Int64) -> Int64
// The release of %4 is removed because the Int64 type is trivial
// The release of %2 is replaced by a destroy_value of the Baz argument, since
// it is a non-trivial aggregate
// CHECK-NEXT: destroy_value {{.*}} : $Baz
// The release of %0 is replaced by a strong_release of the Foo argument, since
// is is a reference type
// CHECK-NEXT: strong_release {{.*}} : $Foo
// CHECK-NEXT: return [[RETVAL]] : $Int64
sil internal @closure0 : $@thin ((), (Builtin.ObjectPointer, @inout Foo, Builtin.ObjectPointer, @inout Baz, Builtin.ObjectPointer, @inout Int64)) -> Int64 { sil internal @closure0 : $@thin ((), (Builtin.ObjectPointer, @inout Foo, Builtin.ObjectPointer, @inout Baz, Builtin.ObjectPointer, @inout Int64)) -> Int64 {
bb0(%0 : $Builtin.ObjectPointer, %1 : $*Foo, %2 : $Builtin.ObjectPointer, %3 : $*Baz, %4 : $Builtin.ObjectPointer, %5 : $*Int64): bb0(%0 : $Builtin.ObjectPointer, %1 : $*Foo, %2 : $Builtin.ObjectPointer, %3 : $*Baz, %4 : $Builtin.ObjectPointer, %5 : $*Int64):
%6 = tuple () %6 = tuple ()
@@ -136,28 +161,3 @@ bb0(%0 : $Builtin.ObjectPointer, %1 : $*Foo):
strong_release %0 : $Builtin.ObjectPointer strong_release %0 : $Builtin.ObjectPointer
return %11 : $Int64 return %11 : $Int64
} }
// CHECK-LABEL: sil internal @closure0_promote0 : $@thin (Foo, Baz, Int64) -> Int64
// CHECK: [[DUMMY_FUNC:%.*]] = function_ref @dummy_func : $@thin (a: Int64, b: Int64, c: Int64) -> Int64
// The load of %1 is removed, and its uses replaced with the Foo argument
// CHECK-NEXT: strong_retain {{.*}} : $Foo
// CHECK-NEXT: [[METHOD_FOO:%.*]] = class_method {{.*}} : $Foo, #Foo.foo!1 : $@cc(method) @thin ((), Foo) -> Int64
// CHECK-NEXT: [[APPLY_FOO:%.*]] = apply [[METHOD_FOO]]({{.*}}) : $@cc(method) @thin ((), Foo) -> Int64
// The struct_element_addr of %3 followed by a load is replaced by a struct_extract of the Baz argument
// CHECK-NEXT: [[EXTRACT_BAZ_X:%.*]] = struct_extract {{.*}} : $Baz, #x
// CHECK-NEXT: [[RETVAL:%.*]] = apply [[DUMMY_FUNC]]([[APPLY_FOO]], [[EXTRACT_BAZ_X]], {{.*}}) : $@thin (a: Int64, b: Int64, c: Int64) -> Int64
// The release of %4 is removed because the Int64 type is trivial
// The release of %2 is replaced by a destroy_value of the Baz argument, since
// it is a non-trivial aggregate
// CHECK-NEXT: destroy_value {{.*}} : $Baz
// The release of %0 is replaced by a strong_release of the Foo argument, since
// is is a reference type
// CHECK-NEXT: strong_release {{.*}} : $Foo
// CHECK-NEXT: return [[RETVAL]] : $Int64