Introduce a PruneVTables pass to mark non-overridden entries.

Start with some high-level checks of whether a declaration is formally final, or has no visible overrides
in the domain of the program visible to the SIL module.

We can eventually adopt more of the logic from the Devirtualizer pass to tell whether call sites are
"effectively final", and maybe make the Devirtualizer consume that information applied by this pass.
This commit is contained in:
Joe Groff
2020-06-05 11:03:04 -07:00
parent 8e6840ddd5
commit e3ce94d97d
5 changed files with 231 additions and 1 deletions

View File

@@ -0,0 +1,72 @@
//===--- PruneVTables.cpp - Prune unnecessary vtable entries --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Mark sil_vtable entries as [nonoverridden] when possible, so that we know
// at IRGen time they can be elided from runtime vtables.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "prune-vtables"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
using namespace swift;
namespace {
class PruneVTables : public SILModuleTransform {
void runOnVTable(SILModule *M,
SILVTable *vtable) {
for (auto &entry : vtable->getMutableEntries()) {
// We don't need to worry about entries that are inherited, overridden,
// or have already been found to have no overrides.
if (entry.TheKind != SILVTable::Entry::Normal) {
continue;
}
// The destructor entry must remain.
if (entry.Method.kind == SILDeclRef::Kind::Deallocator) {
continue;
}
auto methodDecl = entry.Method.getAbstractFunctionDecl();
if (!methodDecl)
continue;
// Is the method declared final?
if (!methodDecl->isFinal()) {
// Are callees of this entry statically knowable?
if (!calleesAreStaticallyKnowable(*M, entry.Method))
continue;
// Does the method have any overrides in this module?
if (methodDecl->isOverridden())
continue;
}
entry.TheKind = SILVTable::Entry::NormalNonOverridden;
}
}
void run() override {
SILModule *M = getModule();
for (auto &vtable : M->getVTables()) {
runOnVTable(M, &vtable);
}
}
};
}
SILTransform *swift::createPruneVTables() {
return new PruneVTables();
}