Skip to content

Commit 56d337d

Browse files
authored
Merge pull request #72249 from apple/es/pkg-cmo
2 parents d29f6a1 + a3250e4 commit 56d337d

File tree

14 files changed

+325
-21
lines changed

14 files changed

+325
-21
lines changed

include/swift/AST/SILOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ class SILOptions {
126126
/// Controls whether cross module optimization is enabled.
127127
CrossModuleOptimizationMode CMOMode = CrossModuleOptimizationMode::Off;
128128

129+
/// Optimization to perform default CMO within a package boundary.
130+
/// Unlike the existing CMO, package CMO can be built with
131+
/// -enable-library-evolution since package modules are required
132+
/// to be built in the same project. To enable this optimization, the
133+
/// module also needs to opt in to allow non-resilient access with
134+
/// -experimental-allow-non-resilient-access.
135+
bool EnableSerializePackage = true;
136+
129137
/// Enables the emission of stack protectors in functions.
130138
bool EnableStackProtection = true;
131139

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,10 @@ def Oplayground : Flag<["-"], "Oplayground">, Group<O_Group>,
984984
Flags<[HelpHidden, FrontendOption, ModuleInterfaceOption]>,
985985
HelpText<"Compile with optimizations appropriate for a playground">;
986986

987+
def ExperimentalPackageCMO : Flag<["-"], "experimental-package-cmo">,
988+
Flags<[FrontendOption]>,
989+
HelpText<"Enable optimization to perform defalut CMO within a package boundary">;
990+
987991
def EnbaleDefaultCMO : Flag<["-"], "enable-default-cmo">,
988992
Flags<[HelpHidden, FrontendOption]>,
989993
HelpText<"Perform conservative cross-module optimization">;

include/swift/SIL/SILLinkage.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,26 @@ inline bool hasPublicVisibility(SILLinkage linkage) {
289289
llvm_unreachable("Unhandled SILLinkage in switch.");
290290
}
291291

292+
inline bool hasPublicOrPackageVisibility(SILLinkage linkage, bool includePackage) {
293+
switch (linkage) {
294+
case SILLinkage::Public:
295+
case SILLinkage::PublicExternal:
296+
case SILLinkage::PublicNonABI:
297+
return true;
298+
case SILLinkage::Package:
299+
case SILLinkage::PackageExternal:
300+
case SILLinkage::PackageNonABI:
301+
return includePackage;
302+
case SILLinkage::Hidden:
303+
case SILLinkage::Shared:
304+
case SILLinkage::Private:
305+
case SILLinkage::HiddenExternal:
306+
return false;
307+
}
308+
309+
llvm_unreachable("Unhandled SILLinkage in switch.");
310+
}
311+
292312
inline bool hasSharedVisibility(SILLinkage linkage) {
293313
switch (linkage) {
294314
case SILLinkage::Shared:

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
300300
inputArgs.AddLastArg(arguments, options::OPT_suppress_warnings);
301301
inputArgs.AddLastArg(arguments, options::OPT_suppress_remarks);
302302
inputArgs.AddLastArg(arguments, options::OPT_experimental_package_bypass_resilience);
303+
inputArgs.AddLastArg(arguments, options::OPT_ExperimentalPackageCMO);
303304
inputArgs.AddLastArg(arguments, options::OPT_profile_generate);
304305
inputArgs.AddLastArg(arguments, options::OPT_profile_use);
305306
inputArgs.AddLastArg(arguments, options::OPT_profile_coverage_mapping);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,18 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
23412341
} else if (Args.hasArg(OPT_EnbaleCMOEverything)) {
23422342
Opts.CMOMode = CrossModuleOptimizationMode::Everything;
23432343
}
2344+
2345+
if (Args.hasArg(OPT_ExperimentalPackageCMO)) {
2346+
if (!FEOpts.AllowNonResilientAccess) {
2347+
Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option,
2348+
"-experimental-package-cmo",
2349+
"-experimental-allow-non-resilient-access");
2350+
} else {
2351+
Opts.EnableSerializePackage = true;
2352+
Opts.CMOMode = CrossModuleOptimizationMode::Default;
2353+
}
2354+
}
2355+
23442356
Opts.EnableStackProtection =
23452357
Args.hasFlag(OPT_enable_stack_protector, OPT_disable_stack_protector,
23462358
Opts.EnableStackProtection);

lib/IRGen/IRGenSIL.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,8 +2446,10 @@ void IRGenModule::emitSILFunction(SILFunction *f) {
24462446
f->getLoweredFunctionType()->isPolymorphic())
24472447
return;
24482448

2449-
// Do not emit bodies of public_external functions.
2450-
if (hasPublicVisibility(f->getLinkage()) && f->isAvailableExternally())
2449+
// Do not emit bodies of public_external or package_external functions.
2450+
if (hasPublicOrPackageVisibility(f->getLinkage(),
2451+
f->getASTContext().SILOpts.EnableSerializePackage) &&
2452+
f->isAvailableExternally())
24512453
return;
24522454

24532455
PrettyStackTraceSILFunction stackTrace("emitting IR", f);

lib/SIL/IR/SILFunction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,8 @@ bool SILFunction::hasValidLinkageForFragileRef() const {
898898
isAvailableExternally())
899899
return false;
900900

901-
// Otherwise, only public functions can be referenced.
902-
return hasPublicVisibility(getLinkage());
901+
// Otherwise, only public or package functions can be referenced.
902+
return hasPublicOrPackageVisibility(getLinkage(), getModule().getOptions().EnableSerializePackage);
903903
}
904904

905905
bool

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,7 +2419,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24192419
}
24202420
if (F.isSerialized()) {
24212421
require(RefG->isSerialized()
2422-
|| hasPublicVisibility(RefG->getLinkage()),
2422+
|| hasPublicOrPackageVisibility(RefG->getLinkage(), F.getModule().getOptions().EnableSerializePackage),
24232423
"alloc_global inside fragile function cannot "
24242424
"reference a private or hidden symbol");
24252425
}
@@ -2438,7 +2438,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24382438
}
24392439
if (F.isSerialized()) {
24402440
require(RefG->isSerialized()
2441-
|| hasPublicVisibility(RefG->getLinkage()),
2441+
|| hasPublicOrPackageVisibility(RefG->getLinkage(), F.getModule().getOptions().EnableSerializePackage),
24422442
"global_addr/value inside fragile function cannot "
24432443
"reference a private or hidden symbol");
24442444
}

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,26 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
161161
}
162162
};
163163

164+
static bool isVisible(SILLinkage linkage, SILOptions options) {
165+
if (options.EnableSerializePackage)
166+
return linkage == SILLinkage::Public || linkage == SILLinkage::Package;
167+
return linkage == SILLinkage::Public;
168+
}
169+
static bool isVisible(AccessLevel accessLevel, SILOptions options) {
170+
if (options.EnableSerializePackage)
171+
return accessLevel == AccessLevel::Package || accessLevel == AccessLevel::Public;
172+
return accessLevel == AccessLevel::Public;
173+
}
174+
164175
/// Select functions in the module which should be serialized.
165176
void CrossModuleOptimization::serializeFunctionsInModule() {
166177

167178
FunctionFlags canSerializeFlags;
168179

169180
// Start with public functions.
170181
for (SILFunction &F : M) {
171-
if (F.getLinkage() == SILLinkage::Public || everything) {
182+
if (isVisible(F.getLinkage(), M.getOptions()) ||
183+
everything) {
172184
if (canSerializeFunction(&F, canSerializeFlags, /*maxDepth*/ 64)) {
173185
serializeFunction(&F, canSerializeFlags);
174186
}
@@ -185,7 +197,6 @@ bool CrossModuleOptimization::canSerializeFunction(
185197
FunctionFlags &canSerializeFlags,
186198
int maxDepth) {
187199
auto iter = canSerializeFlags.find(function);
188-
189200
// Avoid infinite recursion in case it's a cycle in the call graph.
190201
if (iter != canSerializeFlags.end())
191202
return iter->second;
@@ -270,7 +281,7 @@ bool CrossModuleOptimization::canSerializeInstruction(SILInstruction *inst,
270281
// function is completely inlined afterwards.
271282
// Also, when emitting TBD files, we cannot introduce a new public symbol.
272283
if ((conservative || M.getOptions().emitTBD) &&
273-
!hasPublicVisibility(callee->getLinkage())) {
284+
!hasPublicOrPackageVisibility(callee->getLinkage(), M.getOptions().EnableSerializePackage)) {
274285
return false;
275286
}
276287

@@ -290,13 +301,12 @@ bool CrossModuleOptimization::canSerializeInstruction(SILInstruction *inst,
290301
// inline.
291302
if (!canUseFromInline(callee))
292303
return false;
293-
294304
return true;
295305
}
296306
if (auto *GAI = dyn_cast<GlobalAddrInst>(inst)) {
297307
SILGlobalVariable *global = GAI->getReferencedGlobal();
298308
if ((conservative || M.getOptions().emitTBD) &&
299-
!hasPublicVisibility(global->getLinkage())) {
309+
!hasPublicOrPackageVisibility(global->getLinkage(), M.getOptions().EnableSerializePackage)) {
300310
return false;
301311
}
302312

@@ -344,7 +354,7 @@ bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
344354
// function is completely inlined afterwards.
345355
// Also, when emitting TBD files, we cannot introduce a new public symbol.
346356
if ((conservative || M.getOptions().emitTBD) &&
347-
!hasPublicVisibility(referencedFunc->getLinkage())) {
357+
!hasPublicOrPackageVisibility(referencedFunc->getLinkage(), M.getOptions().EnableSerializePackage)) {
348358
return false;
349359
}
350360

@@ -368,7 +378,7 @@ bool CrossModuleOptimization::canSerializeType(SILType type) {
368378
if (conservative && subNT->getEffectiveAccess() < AccessLevel::Package) {
369379
return true;
370380
}
371-
381+
372382
// Exclude types which are defined in an @_implementationOnly imported
373383
// module. Such modules are not transitively available.
374384
if (!canUseFromInline(subNT)) {
@@ -542,15 +552,15 @@ void CrossModuleOptimization::serializeInstruction(SILInstruction *inst,
542552
}
543553
}
544554
serializeFunction(callee, canSerializeFlags);
545-
assert(callee->isSerialized() || callee->getLinkage() == SILLinkage::Public);
555+
assert(callee->isSerialized() || isVisible(callee->getLinkage(), M.getOptions()));
546556
return;
547557
}
548558
if (auto *GAI = dyn_cast<GlobalAddrInst>(inst)) {
549559
SILGlobalVariable *global = GAI->getReferencedGlobal();
550560
if (canSerializeGlobal(global)) {
551561
serializeGlobal(global);
552562
}
553-
if (!hasPublicVisibility(global->getLinkage())) {
563+
if (!hasPublicOrPackageVisibility(global->getLinkage(), M.getOptions().EnableSerializePackage)) {
554564
global->setLinkage(SILLinkage::Public);
555565
}
556566
return;
@@ -606,7 +616,7 @@ void CrossModuleOptimization::makeDeclUsableFromInline(ValueDecl *decl) {
606616
if (M.getSwiftModule() != decl->getDeclContext()->getParentModule())
607617
return;
608618

609-
if (decl->getFormalAccess() < AccessLevel::Public &&
619+
if (!isVisible(decl->getFormalAccess(), M.getOptions()) &&
610620
!decl->isUsableFromInline()) {
611621
// Mark the nominal type as "usableFromInline".
612622
// TODO: find a way to do this without modifying the AST. The AST should be

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static std::optional<SILLinkage> fromStableSILLinkage(unsigned value) {
7777
case SIL_LINKAGE_SHARED: return SILLinkage::Shared;
7878
case SIL_LINKAGE_PRIVATE: return SILLinkage::Private;
7979
case SIL_LINKAGE_PUBLIC_EXTERNAL: return SILLinkage::PublicExternal;
80+
case SIL_LINKAGE_PACKAGE_EXTERNAL: return SILLinkage::PackageExternal;
8081
case SIL_LINKAGE_HIDDEN_EXTERNAL: return SILLinkage::HiddenExternal;
8182
}
8283

0 commit comments

Comments
 (0)