diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index e98508d96a6..e80d9604705 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -84,7 +84,8 @@ public: SILFunction(SILModule &Module, SILLinkage Linkage, StringRef MangledName, SILType LoweredType, Optional Loc = Nothing, - IsTransparent_t isTrans = IsNotTransparent); + IsTransparent_t isTrans = IsNotTransparent, + SILFunction *InsertBefore = nullptr); ~SILFunction(); diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp index ee08d9f58cf..7a2e0e829fd 100644 --- a/lib/SIL/SILFunction.cpp +++ b/lib/SIL/SILFunction.cpp @@ -18,7 +18,8 @@ using namespace swift; SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name, SILType LoweredType, Optional Loc, - IsTransparent_t isTrans) + IsTransparent_t isTrans, + SILFunction *InsertBefore) : ModuleAndLinkage(&Module, Linkage), Name(Name), LoweredType(LoweredType), @@ -26,7 +27,10 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, DeclCtx(nullptr), DebugScope(nullptr), Transparent(isTrans) { - Module.functions.push_back(this); + if (InsertBefore) + Module.functions.insert(SILModule::iterator(InsertBefore), this); + else + Module.functions.push_back(this); } SILFunction::~SILFunction() { diff --git a/lib/SILPasses/CapturePromotion.cpp b/lib/SILPasses/CapturePromotion.cpp index 3b51b580ec1..46f1f938cd0 100644 --- a/lib/SILPasses/CapturePromotion.cpp +++ b/lib/SILPasses/CapturePromotion.cpp @@ -305,13 +305,10 @@ ClosureCloner::initCloned(SILFunction *Orig, IndicesSet &PromotableIndices) { OrigLoweredTy.getAs().getResult(), M.getASTContext())); - // FIXME: This should insert the cloned function right before the existing - // 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. + // This inserts the new cloned function before the original function. return new (M) SILFunction(M, SILLinkage::Internal, ClonedName, M.Types.getLoweredType(ClonedTy), - Orig->getLocation()); + Orig->getLocation(), IsNotTransparent, Orig); } /// \brief Populate the body of the cloned closure, modifying instructions as diff --git a/test/SILPasses/capture_promotion.sil b/test/SILPasses/capture_promotion.sil index 618b2ec39b2..5f85e765c71 100644 --- a/test/SILPasses/capture_promotion.sil +++ b/test/SILPasses/capture_promotion.sil @@ -82,6 +82,31 @@ bb0: 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 { bb0(%0 : $Builtin.ObjectPointer, %1 : $*Foo, %2 : $Builtin.ObjectPointer, %3 : $*Baz, %4 : $Builtin.ObjectPointer, %5 : $*Int64): %6 = tuple () @@ -136,28 +161,3 @@ bb0(%0 : $Builtin.ObjectPointer, %1 : $*Foo): strong_release %0 : $Builtin.ObjectPointer 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