Skip to content

Commit 89df042

Browse files
committed
[embedded] Specialize vtables when processing instructions, not bulk
1 parent 03f927e commit 89df042

File tree

6 files changed

+65
-42
lines changed

6 files changed

+65
-42
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,7 @@ private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
5050
return
5151
}
5252

53-
let vTablesFunctionsBefore = Set(moduleContext.vTables.flatMap { $0.entries.map { $0.function } })
54-
55-
optimize(function: f, context)
56-
57-
let vTablesFunctionsAfter = Set(moduleContext.vTables.flatMap { $0.entries.map { $0.function } })
58-
// Optimizing can trigger vtable specialization, add new vtable entries to the worklist
59-
for f in vTablesFunctionsAfter.subtracting(vTablesFunctionsBefore) {
60-
worklist.pushIfNotVisited(f)
61-
}
62-
63-
worklist.add(calleesOf: f)
53+
optimize(function: f, context, &worklist)
6454
}
6555
}
6656
}
@@ -70,7 +60,7 @@ fileprivate struct PathFunctionTuple: Hashable {
7060
var function: Function
7161
}
7262

73-
private func optimize(function: Function, _ context: FunctionPassContext) {
63+
private func optimize(function: Function, _ context: FunctionPassContext, _ worklist: inout FunctionWorklist) {
7464
var alreadyInlinedFunctions: Set<PathFunctionTuple> = Set()
7565

7666
var changed = true
@@ -85,21 +75,37 @@ private func optimize(function: Function, _ context: FunctionPassContext) {
8575
switch instruction {
8676
case let apply as FullApplySite:
8777
inlineAndDevirtualize(apply: apply, alreadyInlinedFunctions: &alreadyInlinedFunctions, context, simplifyCtxt)
78+
case let alloc as AllocRefInst:
79+
specializeVTableAndAddEntriesToWorklist(for: alloc.type, in: function, context, &worklist)
80+
case let metatype as MetatypeInst:
81+
specializeVTableAndAddEntriesToWorklist(for: metatype.type, in: function, context, &worklist)
82+
case let classMethod as ClassMethodInst:
83+
_ = context.specializeClassMethodInst(classMethod)
8884
default:
8985
break
9086
}
9187
}
9288

9389
_ = context.specializeApplies(in: function, isMandatory: true)
9490

95-
changed = context.specializeVTables(in: function) || changed
96-
9791
removeUnusedMetatypeInstructions(in: function, context)
9892

9993
// If this is a just specialized function, try to optimize copy_addr, etc.
10094
changed = context.optimizeMemoryAccesses(in: function) || changed
10195
_ = context.eliminateDeadAllocations(in: function)
10296
}
97+
98+
worklist.add(calleesOf: function)
99+
}
100+
101+
private func specializeVTableAndAddEntriesToWorklist(for type: Type, in function: Function, _ context: FunctionPassContext, _ worklist: inout FunctionWorklist) {
102+
guard let vtable = context.specializeVTable(for: type, in: function) else {
103+
return
104+
}
105+
106+
for entry in vtable.entries {
107+
worklist.pushIfNotVisited(entry.function)
108+
}
103109
}
104110

105111
private func inlineAndDevirtualize(apply: FullApplySite, alreadyInlinedFunctions: inout Set<PathFunctionTuple>,

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,16 @@ struct FunctionPassContext : MutatingContext {
267267
return false
268268
}
269269

270-
func specializeVTables(in function: Function) -> Bool {
271-
if _bridged.specializeVTables(function.bridged) {
270+
func specializeVTable(for type: Type, in function: Function) -> VTable? {
271+
guard let vtablePtr = _bridged.specializeVTableForType(type.bridged, function.bridged) else {
272+
return nil
273+
}
274+
notifyInstructionsChanged()
275+
return VTable(bridged: BridgedVTable(vTable: vtablePtr))
276+
}
277+
278+
func specializeClassMethodInst(_ cm: ClassMethodInst) -> Bool {
279+
if _bridged.specializeClassMethodInst(cm.bridged) {
272280
notifyInstructionsChanged()
273281
return true
274282
}

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,9 @@ struct BridgedPassContext {
254254
SWIFT_IMPORT_UNSAFE
255255
OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const;
256256

257-
bool specializeVTables(BridgedFunction function) const;
257+
swift::SILVTable *specializeVTableForType(swift::SILType type, BridgedFunction function) const;
258+
259+
bool specializeClassMethodInst(BridgedInstruction cm) const;
258260

259261
bool specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const;
260262

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,9 @@ bool optimizeMemoryAccesses(SILFunction *fn);
597597
/// See the PredictableDeadAllocationElimination pass.
598598
bool eliminateDeadAllocations(SILFunction *fn);
599599

600-
bool specializeVTables(SILFunction *fn, SILTransform *transform);
600+
SILVTable *specializeVTableForType(SILType type, SILModule &mod, SILTransform *transform);
601+
602+
bool specializeClassMethodInst(ClassMethodInst *cm);
601603

602604
bool specializeAppliesInFunction(SILFunction &F,
603605
SILTransform *transform,

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,8 +1545,12 @@ SwiftInt BridgedPassContext::getStaticStride(swift::SILType type) const {
15451545
return integerValueFromConstant(c);
15461546
}
15471547

1548-
bool BridgedPassContext::specializeVTables(BridgedFunction function) const {
1549-
return ::specializeVTables(function.getFunction(), invocation->getTransform());
1548+
swift::SILVTable * BridgedPassContext::specializeVTableForType(swift::SILType type, BridgedFunction function) const {
1549+
return ::specializeVTableForType(type, function.getFunction()->getModule(), invocation->getTransform());
1550+
}
1551+
1552+
bool BridgedPassContext::specializeClassMethodInst(BridgedInstruction cm) const {
1553+
return ::specializeClassMethodInst(cm.getAs<ClassMethodInst>());
15501554
}
15511555

15521556
bool BridgedPassContext::specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const {

lib/SILOptimizer/Transforms/VTableSpecializer.cpp

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,26 @@ class VTableSpecializer : public SILModuleTransform {
5353

5454
} // end anonymous namespace
5555

56-
static bool specializeVTableFor(SILType classTy, SILModule &module,
57-
SILTransform *transform);
5856
static SILFunction *specializeVTableMethod(SILFunction *origMethod,
5957
SubstitutionMap subs,
6058
SILModule &module,
6159
SILTransform *transform);
62-
static bool specializeClassMethodInst(ClassMethodInst *cm);
6360

6461
static bool specializeVTablesInFunction(SILFunction &func, SILModule &module,
6562
SILTransform *transform) {
6663
bool changed = false;
67-
if (func.getLoweredFunctionType()->isPolymorphic()) return changed;
64+
if (func.getLoweredFunctionType()->isPolymorphic())
65+
return changed;
6866

6967
for (SILBasicBlock &block : func) {
7068
for (SILInstruction &inst : block) {
7169
if (auto *allocRef = dyn_cast<AllocRefInst>(&inst)) {
72-
changed |= specializeVTableFor(allocRef->getType(), module, transform);
70+
changed |= (specializeVTableForType(allocRef->getType(), module,
71+
transform) != nullptr);
7372
} else if (auto *metatype = dyn_cast<MetatypeInst>(&inst)) {
74-
changed |= specializeVTableFor(
75-
metatype->getType().getInstanceTypeOfMetatype(&func), module, transform);
73+
changed |= (specializeVTableForType(
74+
metatype->getType().getInstanceTypeOfMetatype(&func),
75+
module, transform) != nullptr);
7676
} else if (auto *cm = dyn_cast<ClassMethodInst>(&inst)) {
7777
changed |= specializeClassMethodInst(cm);
7878
}
@@ -104,13 +104,16 @@ bool VTableSpecializer::specializeVTables(SILModule &module) {
104104
return changed;
105105
}
106106

107-
static bool specializeVTableFor(SILType classTy, SILModule &module,
107+
SILVTable *swift::specializeVTableForType(SILType classTy, SILModule &module,
108108
SILTransform *transform) {
109+
if (!module.getASTContext().LangOpts.hasFeature(Feature::Embedded))
110+
return nullptr;
111+
109112
CanType astType = classTy.getASTType();
110113
BoundGenericClassType *genClassTy = dyn_cast<BoundGenericClassType>(astType);
111-
if (!genClassTy) return false;
114+
if (!genClassTy) return nullptr;
112115

113-
if (module.lookUpSpecializedVTable(classTy)) return false;
116+
if (module.lookUpSpecializedVTable(classTy)) return nullptr;
114117

115118
LLVM_DEBUG(llvm::errs() << "specializeVTableFor "
116119
<< genClassTy->getDecl()->getName() << ' '
@@ -138,8 +141,9 @@ static bool specializeVTableFor(SILType classTy, SILModule &module,
138141
entry.isNonOverridden()));
139142
}
140143

141-
SILVTable::create(module, classDecl, classTy, IsNotSerialized, newEntries);
142-
return true;
144+
SILVTable *vtable = SILVTable::create(module, classDecl, classTy,
145+
IsNotSerialized, newEntries);
146+
return vtable;
143147
}
144148

145149
static SILFunction *specializeVTableMethod(SILFunction *origMethod,
@@ -185,7 +189,13 @@ static SILFunction *specializeVTableMethod(SILFunction *origMethod,
185189
return SpecializedF;
186190
}
187191

188-
static bool specializeClassMethodInst(ClassMethodInst *cm) {
192+
bool swift::specializeClassMethodInst(ClassMethodInst *cm) {
193+
SILFunction *f = cm->getFunction();
194+
SILModule &m = f->getModule();
195+
196+
if (!m.getASTContext().LangOpts.hasFeature(Feature::Embedded))
197+
return false;
198+
189199
SILValue instance = cm->getOperand();
190200
SILType classTy = instance->getType();
191201
CanType astType = classTy.getASTType();
@@ -197,9 +207,6 @@ static bool specializeClassMethodInst(ClassMethodInst *cm) {
197207
classDecl->getParentModule(), classDecl);
198208

199209
SILType funcTy = cm->getType();
200-
201-
SILFunction *f = cm->getFunction();
202-
SILModule &m = f->getModule();
203210
SILType substitutedType =
204211
funcTy.substGenericArgs(m, subs, TypeExpansionContext::minimal());
205212

@@ -230,12 +237,6 @@ static bool specializeClassMethodInst(ClassMethodInst *cm) {
230237
return true;
231238
}
232239

233-
bool swift::specializeVTables(SILFunction *fn, SILTransform *transform) {
234-
if (!fn->getModule.getASTContext().LangOpts.hasFeature(Feature::Embedded))
235-
return false;
236-
return specializeVTablesInFunction(*fn, fn->getModule(), transform);
237-
}
238-
239240
SILTransform *swift::createVTableSpecializer() {
240241
return new VTableSpecializer();
241242
}

0 commit comments

Comments
 (0)