[SIL][PackageCMO] Allow optimizing [serialized_for_pkg] functions during SIL

inlining, generic/closure specialization, and devirtualization optimization passes.

SILFunction::canBeInlinedIntoCaller now exlicitly requires a caller's SerializedKind_t arg.
isAnySerialized() is added as a convenience function that checks if [serialized] or [serialized_for_pkg].

Resolves rdar://128704752
This commit is contained in:
Ellie Shin
2024-05-23 16:14:15 -07:00
parent 67e9df028e
commit 4ecfc96578
25 changed files with 123 additions and 178 deletions

View File

@@ -199,15 +199,19 @@ static bool isPackageOrPublic(AccessLevel accessLevel, SILOptions options) {
/// is the correct behavior.
static bool isSerializedWithRightKind(const SILModule &mod,
SILFunction *f) {
// If Package CMO is enabled in resilient mode, return
// true if the function is [serialized] due to @inlinable
// (or similar) or [serialized_for_pkg] due to this
// optimization.
return mod.getSwiftModule()->serializePackageEnabled() &&
mod.getSwiftModule()->isResilient() ?
f->isSerializedForPackage() : f->isSerialized();
f->isAnySerialized() : f->isSerialized();
}
static bool isSerializedWithRightKind(const SILModule &mod,
SILGlobalVariable *g) {
return mod.getSwiftModule()->serializePackageEnabled() &&
mod.getSwiftModule()->isResilient() ?
g->isSerializedForPackage() : g->isSerialized();
g->isAnySerialized() : g->isSerialized();
}
static SerializedKind_t getRightSerializedKind(const SILModule &mod) {
return mod.getSwiftModule()->serializePackageEnabled() &&
@@ -271,19 +275,19 @@ void CrossModuleOptimization::serializeTablesInModule() {
return;
for (const auto &vt : M.getVTables()) {
if (vt->isNotSerialized() &&
if (!vt->isAnySerialized() &&
vt->getClass()->getEffectiveAccess() >= AccessLevel::Package) {
vt->setSerializedKind(getRightSerializedKind(M));
}
}
for (auto &wt : M.getWitnessTables()) {
if (wt.isNotSerialized() &&
if (!wt.isAnySerialized() &&
hasPublicOrPackageVisibility(wt.getLinkage(), /*includePackage*/ true)) {
for (auto &entry : wt.getEntries()) {
// Witness thunks are not serialized, so serialize them here.
if (entry.getKind() == SILWitnessTable::Method &&
entry.getMethodWitness().Witness->isNotSerialized() &&
!entry.getMethodWitness().Witness->isAnySerialized() &&
isSerializeCandidate(entry.getMethodWitness().Witness,
M.getOptions())) {
entry.getMethodWitness().Witness->setSerializedKind(getRightSerializedKind(M));
@@ -322,8 +326,7 @@ bool CrossModuleOptimization::canSerializeFunction(
return false;
}
if (function->isSerialized() ||
isSerializedWithRightKind(M, function)) {
if (function->isAnySerialized()) {
canSerializeFlags[function] = true;
return true;
}
@@ -615,13 +618,6 @@ bool CrossModuleOptimization::shouldSerialize(SILFunction *function) {
/// marked in \p canSerializeFlags.
void CrossModuleOptimization::serializeFunction(SILFunction *function,
const FunctionFlags &canSerializeFlags) {
// This means the function is @inlinable (or similar)
// so should have [serialized] attribute.
if (function->isSerialized())
return;
// If not, check whether it was serialized with
// this optimization.
if (isSerializedWithRightKind(M, function))
return;