Skip to content

Commit f579794

Browse files
committed
[embedded] Specialize superclasses in VTableSpecializer as part of MandatoryPerformanceOptimizations
1 parent 8a4137a commit f579794

File tree

3 files changed

+80
-25
lines changed

3 files changed

+80
-25
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
5656
f.set(isPerformanceConstraint: true, context)
5757
}
5858

59-
optimize(function: f, context, &worklist)
59+
optimize(function: f, context, moduleContext, &worklist)
6060
}
6161

6262
// Generic specialization takes care of removing metatype arguments of generic functions.
@@ -73,7 +73,7 @@ fileprivate struct PathFunctionTuple: Hashable {
7373
var function: Function
7474
}
7575

76-
private func optimize(function: Function, _ context: FunctionPassContext, _ worklist: inout FunctionWorklist) {
76+
private func optimize(function: Function, _ context: FunctionPassContext, _ moduleContext: ModulePassContext, _ worklist: inout FunctionWorklist) {
7777
var alreadyInlinedFunctions: Set<PathFunctionTuple> = Set()
7878

7979
var changed = true
@@ -92,11 +92,11 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ work
9292
// Embedded Swift specific transformations
9393
case let alloc as AllocRefInst:
9494
if context.options.enableEmbeddedSwift {
95-
specializeVTableAndAddEntriesToWorklist(for: alloc.type, in: function, context, &worklist)
95+
specializeVTableAndAddEntriesToWorklist(for: alloc.type, in: function, context, moduleContext, &worklist)
9696
}
9797
case let metatype as MetatypeInst:
9898
if context.options.enableEmbeddedSwift {
99-
specializeVTableAndAddEntriesToWorklist(for: metatype.type, in: function, context, &worklist)
99+
specializeVTableAndAddEntriesToWorklist(for: metatype.type, in: function, context, moduleContext, &worklist)
100100
}
101101
case let classMethod as ClassMethodInst:
102102
if context.options.enableEmbeddedSwift {
@@ -133,13 +133,21 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ work
133133
}
134134
}
135135

136-
private func specializeVTableAndAddEntriesToWorklist(for type: Type, in function: Function, _ context: FunctionPassContext, _ worklist: inout FunctionWorklist) {
137-
guard let vtable = context.specializeVTable(for: type, in: function) else {
136+
private func specializeVTableAndAddEntriesToWorklist(for type: Type, in function: Function,
137+
_ context: FunctionPassContext, _ moduleContext: ModulePassContext,
138+
_ worklist: inout FunctionWorklist) {
139+
let vTablesCountBefore = moduleContext.vTables.count
140+
141+
guard context.specializeVTable(for: type, in: function) != nil else {
138142
return
139143
}
140144

141-
for entry in vtable.entries {
142-
worklist.pushIfNotVisited(entry.function)
145+
// More than one new vtable might have been created (superclasses), process them all
146+
let vTables = moduleContext.vTables
147+
for i in vTablesCountBefore ..< vTables.count {
148+
for entry in vTables[i].entries {
149+
worklist.pushIfNotVisited(entry.function)
150+
}
143151
}
144152
}
145153

lib/SILOptimizer/Transforms/VTableSpecializer.cpp

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ namespace {
3838

3939
class VTableSpecializer : public SILModuleTransform {
4040
bool specializeVTables(SILModule &module);
41-
bool specializeVTablesOfSuperclasses(SILModule &module);
4241

4342
/// The entry point to the transformation.
4443
void run() override {
@@ -59,6 +58,8 @@ static SILFunction *specializeVTableMethod(SILFunction *origMethod,
5958
SILModule &module,
6059
SILTransform *transform);
6160

61+
static bool specializeVTablesOfSuperclasses(SILModule &module, SILTransform *transform);
62+
6263
static bool specializeVTablesInFunction(SILFunction &func, SILModule &module,
6364
SILTransform *transform) {
6465
bool changed = false;
@@ -89,7 +90,7 @@ bool VTableSpecializer::specializeVTables(SILModule &module) {
8990
changed |= specializeVTablesInFunction(func, module, this);
9091
}
9192

92-
changed |= specializeVTablesOfSuperclasses(module);
93+
changed |= specializeVTablesOfSuperclasses(module, this);
9394

9495
for (SILVTable *vtable : module.getVTables()) {
9596
if (vtable->getClass()->isGenericContext()) continue;
@@ -115,24 +116,36 @@ bool VTableSpecializer::specializeVTables(SILModule &module) {
115116
return changed;
116117
}
117118

118-
bool VTableSpecializer::specializeVTablesOfSuperclasses(SILModule &module) {
119+
static bool specializeVTablesOfSuperclasses(SILVTable *vtable,
120+
SILModule &module,
121+
SILTransform *transform) {
122+
if (vtable->getClass()->isGenericContext() && !vtable->getClassType())
123+
return false;
124+
125+
SILType superClassTy;
126+
if (SILType classTy = vtable->getClassType()) {
127+
superClassTy = classTy.getSuperclass();
128+
} else {
129+
if (Type superTy = vtable->getClass()->getSuperclass())
130+
superClassTy =
131+
SILType::getPrimitiveObjectType(superTy->getCanonicalType());
132+
}
133+
if (superClassTy) {
134+
return (specializeVTableForType(superClassTy, module, transform) !=
135+
nullptr);
136+
}
137+
138+
return false;
139+
}
140+
141+
static bool specializeVTablesOfSuperclasses(SILModule &module,
142+
SILTransform *transform) {
119143
bool changed = false;
120-
// The module's vtable table can grow while we are specializing superclass vtables.
144+
// The module's vtable table can grow while we are specializing superclass
145+
// vtables.
121146
for (unsigned i = 0; i < module.getVTables().size(); ++i) {
122147
SILVTable *vtable = module.getVTables()[i];
123-
if (vtable->getClass()->isGenericContext() && !vtable->getClassType())
124-
continue;
125-
126-
SILType superClassTy;
127-
if (SILType classTy = vtable->getClassType()) {
128-
superClassTy = classTy.getSuperclass();
129-
} else {
130-
if (Type superTy = vtable->getClass()->getSuperclass())
131-
superClassTy = SILType::getPrimitiveObjectType(superTy->getCanonicalType());
132-
}
133-
if (superClassTy) {
134-
changed |= (specializeVTableForType(superClassTy, module, this) != nullptr);
135-
}
148+
specializeVTablesOfSuperclasses(vtable, module, transform);
136149
}
137150
return changed;
138151
}
@@ -173,6 +186,9 @@ SILVTable *swift::specializeVTableForType(SILType classTy, SILModule &module,
173186

174187
SILVTable *vtable = SILVTable::create(module, classDecl, classTy,
175188
IsNotSerialized, newEntries);
189+
190+
specializeVTablesOfSuperclasses(vtable, module, transform);
191+
176192
return vtable;
177193
}
178194

test/embedded/generic-classes2.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-Osize -enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
3+
4+
// REQUIRES: swift_in_compiler
5+
// REQUIRES: executable_test
6+
// REQUIRES: optimized_stdlib
7+
// REQUIRES: OS=macosx || OS=linux-gnu
8+
9+
class B<T> {
10+
}
11+
12+
class D<T>: B<T> {
13+
}
14+
15+
func callee<T>(_ t: T.Type) {
16+
_ = D<T>()
17+
}
18+
19+
public func test() {
20+
callee(Int.self)
21+
}
22+
23+
@main
24+
struct Main {
25+
static func main() {
26+
test()
27+
print("OK!")
28+
}
29+
}
30+
31+
// CHECK: OK!

0 commit comments

Comments
 (0)