Skip to content

Commit a3250e4

Browse files
committed
Support Package CMO
* Add a new flag -experimental-package-cmo that requires -experimental-allow-non-resilient-access. * Support serializing package decls for CMO in package if enabled. * Only applies to default mode CMO. * Unlike the existing CMO, package CMO can be built with -enable-library-evolution as package modules are required to be built together in the same project. * Create hasPublicOrPackageVisibility to opt in for package decls; needed for CMO, SILVerifier, and other call sites that verify or determine codegen. Resolves rdar://121976014
1 parent 8df1abe commit a3250e4

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
@@ -2335,6 +2335,18 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
23352335
} else if (Args.hasArg(OPT_EnbaleCMOEverything)) {
23362336
Opts.CMOMode = CrossModuleOptimizationMode::Everything;
23372337
}
2338+
2339+
if (Args.hasArg(OPT_ExperimentalPackageCMO)) {
2340+
if (!FEOpts.AllowNonResilientAccess) {
2341+
Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option,
2342+
"-experimental-package-cmo",
2343+
"-experimental-allow-non-resilient-access");
2344+
} else {
2345+
Opts.EnableSerializePackage = true;
2346+
Opts.CMOMode = CrossModuleOptimizationMode::Default;
2347+
}
2348+
}
2349+
23382350
Opts.EnableStackProtection =
23392351
Args.hasFlag(OPT_enable_stack_protector, OPT_disable_stack_protector,
23402352
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
@@ -2417,7 +2417,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24172417
}
24182418
if (F.isSerialized()) {
24192419
require(RefG->isSerialized()
2420-
|| hasPublicVisibility(RefG->getLinkage()),
2420+
|| hasPublicOrPackageVisibility(RefG->getLinkage(), F.getModule().getOptions().EnableSerializePackage),
24212421
"alloc_global inside fragile function cannot "
24222422
"reference a private or hidden symbol");
24232423
}
@@ -2436,7 +2436,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24362436
}
24372437
if (F.isSerialized()) {
24382438
require(RefG->isSerialized()
2439-
|| hasPublicVisibility(RefG->getLinkage()),
2439+
|| hasPublicOrPackageVisibility(RefG->getLinkage(), F.getModule().getOptions().EnableSerializePackage),
24402440
"global_addr/value inside fragile function cannot "
24412441
"reference a private or hidden symbol");
24422442
}

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)