diff --git a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift index d0f25de54c928..1300e140fa2af 100644 --- a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift +++ b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift @@ -68,7 +68,7 @@ private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist, // We need handle this case with a function signature optimization. removeMetatypeArgumentsInCallees(of: f, moduleContext) - worklist.addCallees(of: f) + worklist.addCallees(of: f, moduleContext) } } @@ -521,29 +521,41 @@ fileprivate struct FunctionWorklist { return } - mutating func addCallees(of function: Function) { + mutating func addCallees(of function: Function, _ context: ModulePassContext) { for inst in function.instructions { switch inst { - case let apply as ApplySite: - if let callee = apply.referencedFunction { - pushIfNotVisited(callee) + case let fri as FunctionRefInst: + pushIfNotVisited(fri.referencedFunction) + case let alloc as AllocRefInst: + if context.options.enableEmbeddedSwift { + addVTableMethods(forClassType: alloc.type, context) } - case let bi as BuiltinInst: - switch bi.id { - case .Once, .OnceWithContext: - if let fri = bi.operands[1].value as? FunctionRefInst { - pushIfNotVisited(fri.referencedFunction) + case let metatype as MetatypeInst: + if context.options.enableEmbeddedSwift { + let instanceType = metatype.type.loweredInstanceTypeOfMetatype(in: function) + if instanceType.isClass { + addVTableMethods(forClassType: instanceType, context) } - break; - default: - break } + default: break } } } + mutating func addVTableMethods(forClassType classType: Type, _ context: ModulePassContext) { + guard let vtable = classType.isGenericAtAnyLevel ? + context.lookupSpecializedVTable(for: classType) : + context.lookupVTable(for: classType.nominal!) + else { + return + } + for entry in vtable.entries where !entry.implementation.isGeneric { + pushIfNotVisited(entry.implementation) + } + } + mutating func addWitnessMethods(of witnessTable: WitnessTable) { for entry in witnessTable.entries { if case .method(_, let witness) = entry, diff --git a/test/SILOptimizer/mandatory_performance_optimizations.sil b/test/SILOptimizer/mandatory_performance_optimizations.sil index 9298c1f2d45a2..3aa78ec7b391b 100644 --- a/test/SILOptimizer/mandatory_performance_optimizations.sil +++ b/test/SILOptimizer/mandatory_performance_optimizations.sil @@ -215,7 +215,7 @@ bb0(%0 : $Int, %1 : @owned $Builtin.NativeObject): return %8 : $Builtin.NativeObject } -// CHECK-LABEL: sil [signature_optimized_thunk] [ossa] @metatype_arg : +// CHECK-LABEL: sil [signature_optimized_thunk] [perf_constraint] [ossa] @metatype_arg : sil [ossa] @metatype_arg : $@convention(thin) (Int, @thick Int.Type, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { bb0(%0 : $Int, %1 : $@thick Int.Type, %2 : @owned $Builtin.NativeObject): fix_lifetime %1 : $@thick Int.Type @@ -243,7 +243,7 @@ bb2(%13 : @owned $any Error): throw %13 : $any Error } -// CHECK-LABEL: sil [signature_optimized_thunk] [ossa] @metatype_arg_throws : +// CHECK-LABEL: sil [signature_optimized_thunk] [perf_constraint] [ossa] @metatype_arg_throws : sil [ossa] @metatype_arg_throws : $@convention(thin) (Int, @thick Int.Type, @owned Builtin.NativeObject) -> (@owned Builtin.NativeObject, @error any Error) { bb0(%0 : $Int, %1 : $@thick Int.Type, %2 : @owned $Builtin.NativeObject): fix_lifetime %1 : $@thick Int.Type diff --git a/test/embedded/classes-multi-module.swift b/test/embedded/classes-multi-module.swift new file mode 100644 index 0000000000000..9bbc5664d3aa2 --- /dev/null +++ b/test/embedded/classes-multi-module.swift @@ -0,0 +1,58 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -enable-experimental-feature Embedded -c -I%t -parse-as-library %t/MyModule.swift -o %t/MyModule.o -emit-module -emit-module-path %t/MyModule.swiftmodule -emit-empty-object-file +// RUN: %target-swift-frontend -enable-experimental-feature Embedded -c -I%t %t/Main.swift -o %t/Main.o +// RUN: %target-clang %t/Main.o %t/MyModule.o -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s + +// REQUIRES: executable_test +// REQUIRES: swift_feature_Embedded + +//--- MyModule.swift + +public class C { + public func foo() { + let x = X(x: 27) + x.bar() + } +} + +class D: C { + override public func foo() { + print("D") + } +} + +class X { + var x: T + + init(x: T) { self.x = x } + + func bar() { + print(x) + } +} + +class Y: X { + override func bar() { + } +} + +@inline(never) +public func create(_ t: T.Type) -> C { + return C() +} + +//--- Main.swift + +import MyModule + +@inline(never) +public func testit() { + let c = create(Int.self) + c.foo() +} + +// CHECK: 27 +testit()