[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

@@ -278,7 +278,7 @@ namespace {
void writeSILGlobalVar(const SILGlobalVariable &g);
void writeSILWitnessTable(const SILWitnessTable &wt);
void writeSILWitnessTableEntry(const SILWitnessTable::Entry &entry,
std::optional<SerializedKind_t> serializedKind = std::nullopt);
SerializedKind_t serializedKind);
void writeSILDefaultWitnessTable(const SILDefaultWitnessTable &wt);
void
writeSILDifferentiabilityWitness(const SILDifferentiabilityWitness &dw);
@@ -376,8 +376,7 @@ void SILSerializer::addReferencedSILFunction(const SILFunction *F,
}
if (F->getLinkage() == SILLinkage::Shared) {
assert(!F->isNotSerialized() ||
F->hasForeignBody());
assert(F->isAnySerialized() || F->hasForeignBody());
FuncsToEmit[F] = false;
functionWorklist.push_back(F);
@@ -495,7 +494,6 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
}
unsigned numAttrs = NoBody ? 0 : F.getSpecializeAttrs().size();
// pcmo TODO: check if package-cmo is enabled
auto resilience = F.getModule().getSwiftModule()->getResilienceStrategy();
bool serializeDerivedEffects = (resilience != ResilienceStrategy::Resilient) &&
!F.hasSemanticsAttr("optimize.no.crossmodule");
@@ -2879,7 +2877,7 @@ void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) {
TyID, dID);
// Don't emit the initializer instructions if not marked as "serialized".
if (g.isNotSerialized())
if (!g.isAnySerialized())
return;
ValueIDs.clear();
@@ -2926,8 +2924,8 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
SILFunction *impl = entry.getImplementation();
if (ShouldSerializeAll ||
impl->hasValidLinkageForFragileRef(vt.getSerializedKind(),
/*assumeFragileCaller*/ false)) {
(vt.isAnySerialized() &&
impl->hasValidLinkageForFragileRef(vt.getSerializedKind()))) {
handleSILDeclRef(S, entry.getMethod(), ListOfValues);
addReferencedSILFunction(impl, true);
// Each entry is a pair of SILDeclRef and SILFunction.
@@ -2950,7 +2948,7 @@ void SILSerializer::writeSILMoveOnlyDeinit(const SILMoveOnlyDeinit &deinit) {
return;
SILFunction *impl = deinit.getImplementation();
if (!ShouldSerializeAll && !impl->hasValidLinkageForFragileRef())
if (!ShouldSerializeAll && !impl->hasValidLinkageForFragileRef(IsSerialized))
return;
// Use the mangled name of the class as a key to distinguish between classes
@@ -3026,7 +3024,7 @@ void SILSerializer::writeSILWitnessTable(const SILWitnessTable &wt) {
void SILSerializer::writeSILWitnessTableEntry(
const SILWitnessTable::Entry &entry,
std::optional<SerializedKind_t> serializedKind) {
SerializedKind_t serializedKind) {
if (entry.getKind() == SILWitnessTable::BaseProtocol) {
auto &baseWitness = entry.getBaseProtocolWitness();
@@ -3068,8 +3066,8 @@ void SILSerializer::writeSILWitnessTableEntry(
IdentifierID witnessID = 0;
SILFunction *witness = methodWitness.Witness;
if (witness &&
witness->hasValidLinkageForFragileRef(serializedKind,
/*assumeFragileCaller*/ false)) {
serializedKind != IsNotSerialized &&
witness->hasValidLinkageForFragileRef(serializedKind)) {
addReferencedSILFunction(witness, true);
witnessID = S.addUniquedStringRef(witness->getName());
}
@@ -3102,7 +3100,7 @@ writeSILDefaultWitnessTable(const SILDefaultWitnessTable &wt) {
SILAbbrCodes[DefaultWitnessTableNoEntryLayout::Code]);
continue;
}
writeSILWitnessTableEntry(entry);
writeSILWitnessTableEntry(entry, IsNotSerialized);
}
}
@@ -3174,8 +3172,7 @@ bool SILSerializer::shouldEmitFunctionBody(const SILFunction *F,
// If F is serialized, we should always emit its body.
// Shared functions are only serialized if they are referenced from another
// serialized function. This is handled in `addReferencedSILFunction`.
if (!F->isNotSerialized() &&
!hasSharedVisibility(F->getLinkage()))
if (F->isAnySerialized() && !hasSharedVisibility(F->getLinkage()))
return true;
return false;
@@ -3237,13 +3234,13 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// serialize everything.
// FIXME: Resilience: could write out vtable for fragile classes.
for (const auto &vt : SILMod->getVTables()) {
if ((ShouldSerializeAll || !vt->isNotSerialized()) &&
if ((ShouldSerializeAll || vt->isAnySerialized()) &&
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(vt->getClass()))
writeSILVTable(*vt);
}
for (const auto &deinit : SILMod->getMoveOnlyDeinits()) {
if ((ShouldSerializeAll || !deinit->isNotSerialized()) &&
if ((ShouldSerializeAll || deinit->isAnySerialized()) &&
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(
deinit->getNominalDecl()))
writeSILMoveOnlyDeinit(*deinit);
@@ -3251,7 +3248,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// Write out property descriptors.
for (const SILProperty &prop : SILMod->getPropertyList()) {
if ((ShouldSerializeAll || !prop.isNotSerialized()) &&
if ((ShouldSerializeAll || prop.isAnySerialized()) &&
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(
prop.getDecl()->getInnermostDeclContext()))
writeSILProperty(prop);
@@ -3259,7 +3256,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// Write out fragile WitnessTables.
for (const SILWitnessTable &wt : SILMod->getWitnessTables()) {
if ((ShouldSerializeAll || !wt.isNotSerialized()) &&
if ((ShouldSerializeAll || wt.isAnySerialized()) &&
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(
wt.getConformance()->getDeclContext()))
writeSILWitnessTable(wt);
@@ -3276,7 +3273,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// Add global variables that must be emitted to the list.
for (const SILGlobalVariable &g : SILMod->getSILGlobals()) {
if (!g.isNotSerialized() || ShouldSerializeAll)
if (g.isAnySerialized() || ShouldSerializeAll)
addReferencedGlobalVariable(&g);
}
@@ -3322,7 +3319,6 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// Now write function declarations for every function we've
// emitted a reference to without emitting a function body for.
// pcmo TODO: check if package-cmo is enabled
auto resilience = SILMod->getSwiftModule()->getResilienceStrategy();
for (const SILFunction &F : *SILMod) {
auto iter = FuncsToEmit.find(&F);