Skip to content

Commit a5397b4

Browse files
committed
Cross module optimization
This is a first version of cross module optimization (CMO). The basic idea for CMO is to use the existing library evolution compiler features, but in an automated way. A new SIL module pass "annotates" functions and types with @inlinable and @usableFromInline. This results in functions being serialized into the swiftmodule file and thus available for optimizations in client modules. The annotation is done with a worklist-algorithm, starting from public functions and continuing with entities which are used from already selected functions. A heuristic performs a preselection on which functions to consider - currently just generic functions are selected. The serializer then writes annotated functions (including function bodies) into the swiftmodule file of the compiled module. Client modules are able to de-serialize such functions from their imported modules and use them for optimiations, like generic specialization. The optimization is gated by a new compiler option -cross-module-optimization (also available in the swift driver). By default this option is off. Without turning the option on, this change is (almost) a NFC. rdar://problem/22591518
1 parent 0b6e3bf commit a5397b4

File tree

15 files changed

+739
-4
lines changed

15 files changed

+739
-4
lines changed

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class SILOptions {
6262
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.
6363
bool DisableSILPerfOptimizations = false;
6464

65+
/// Controls whether cross module optimization is enabled.
66+
bool CrossModuleOptimization = false;
67+
6568
/// Controls whether or not paranoid verification checks are run.
6669
bool VerifyAll = false;
6770

include/swift/Option/Options.td

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

592+
def CrossModuleOptimization : Flag<["-"], "cross-module-optimization">,
593+
Flags<[HelpHidden, FrontendOption]>,
594+
HelpText<"Perform cross-module optimization">;
595+
592596
def RemoveRuntimeAsserts : Flag<["-"], "remove-runtime-asserts">,
593597
Flags<[FrontendOption]>,
594598
HelpText<"Remove runtime safety checks.">;

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ PASS(AccessEnforcementSelection, "access-enforcement-selection",
6464
"Access Enforcement Selection")
6565
PASS(AccessEnforcementWMO, "access-enforcement-wmo",
6666
"Access Enforcement Whole Module Optimization")
67+
PASS(CrossModuleSerializationSetup, "cross-module-serialization-setup",
68+
"Setup serialization flags for cross-module optimization")
6769
PASS(AccessSummaryDumper, "access-summary-dump",
6870
"Dump Address Parameter Access Summary")
6971
PASS(AccessedStorageDumper, "accessed-storage-dump",

lib/AST/Decl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,7 +2995,7 @@ SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
29952995
/// Returns true if \p VD needs to be treated as publicly-accessible
29962996
/// at the SIL, LLVM, and machine levels due to being @usableFromInline.
29972997
bool ValueDecl::isUsableFromInline() const {
2998-
assert(getFormalAccess() == AccessLevel::Internal);
2998+
assert(getFormalAccess() <= AccessLevel::Internal);
29992999

30003000
if (getAttrs().hasAttribute<UsableFromInlineAttr>() ||
30013001
getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
@@ -3092,7 +3092,7 @@ static AccessLevel getAdjustedFormalAccess(const ValueDecl *VD,
30923092
return getMaximallyOpenAccessFor(VD);
30933093

30943094
if (treatUsableFromInlineAsPublic &&
3095-
access == AccessLevel::Internal &&
3095+
(access == AccessLevel::Internal || access == AccessLevel::Private) &&
30963096
VD->isUsableFromInline()) {
30973097
return AccessLevel::Public;
30983098
}

lib/Driver/ToolChains.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ ToolChain::constructInvocation(const CompileJobAction &job,
400400
Arguments.push_back("-module-name");
401401
Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
402402

403+
if (context.Args.hasArg(options::OPT_CrossModuleOptimization)) {
404+
Arguments.push_back("-cross-module-optimization");
405+
}
406+
403407
addOutputsOfType(Arguments, context.Output, context.Args,
404408
file_types::TY_OptRecord, "-save-optimization-record-path");
405409

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
871871
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
872872
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
873873
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
874+
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
874875
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);
875876
Opts.DebugSerialization |= Args.hasArg(OPT_sil_debug_serialization);
876877
Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);

lib/FrontendTool/FrontendTool.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,9 @@ static bool validateTBDIfNeeded(CompilerInvocation &Invocation,
13941394
if (!astGuaranteedToCorrespondToSIL ||
13951395
!inputFileKindCanHaveTBDValidated(Invocation.getInputKind()))
13961396
return false;
1397+
1398+
if (Invocation.getSILOptions().CrossModuleOptimization)
1399+
return false;
13971400

13981401
const auto &frontendOpts = Invocation.getFrontendOptions();
13991402
auto mode = frontendOpts.ValidateTBDAgainstIR;

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,8 @@ IRGenModule::getAddrOfParentContextDescriptor(DeclContext *from,
831831

832832
// Wrap up private types in an anonymous context for the containing file
833833
// unit so that the runtime knows they have unstable identity.
834-
if (!fromAnonymousContext && Type->isOutermostPrivateOrFilePrivateScope())
834+
if (!fromAnonymousContext && Type->isOutermostPrivateOrFilePrivateScope()
835+
&& !Type->isUsableFromInline())
835836
return {getAddrOfAnonymousContextDescriptor(Type),
836837
ConstantReference::Direct};
837838
}

lib/SILOptimizer/IPO/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ silopt_register_sources(
22
CapturePromotion.cpp
33
CapturePropagation.cpp
44
ClosureSpecializer.cpp
5+
CrossModuleSerializationSetup.cpp
56
DeadFunctionElimination.cpp
67
EagerSpecializer.cpp
78
GlobalOpt.cpp

0 commit comments

Comments
 (0)