Skip to content

Commit 835c701

Browse files
authored
Merge pull request #28407 from eeckstein/cross-module-optimization
Cross module optimization
2 parents 213ccf8 + a5397b4 commit 835c701

23 files changed

+879
-71
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/SIL/SILInstruction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2892,6 +2892,10 @@ class KeyPathPatternComponent {
28922892
return KeyPathPatternComponent(tupleIndex, ty);
28932893
}
28942894

2895+
void visitReferencedFunctionsAndMethods(
2896+
std::function<void (SILFunction *)> functionCallBack,
2897+
std::function<void (SILDeclRef)> methodCallBack) const;
2898+
28952899
void incrementRefCounts() const;
28962900
void decrementRefCounts() const;
28972901

@@ -2948,6 +2952,15 @@ class KeyPathPattern final
29482952

29492953
ArrayRef<KeyPathPatternComponent> getComponents() const;
29502954

2955+
void visitReferencedFunctionsAndMethods(
2956+
std::function<void (SILFunction *)> functionCallBack,
2957+
std::function<void (SILDeclRef)> methodCallBack) {
2958+
for (auto &component : getComponents()) {
2959+
component.visitReferencedFunctionsAndMethods(functionCallBack,
2960+
methodCallBack);
2961+
}
2962+
}
2963+
29512964
static KeyPathPattern *get(SILModule &M,
29522965
CanGenericSignature signature,
29532966
CanType rootType,

include/swift/SIL/SILModule.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ class SILModule {
194194
/// The list of SILDefaultWitnessTables in the module.
195195
DefaultWitnessTableListType defaultWitnessTables;
196196

197+
/// Declarations which are externally visible.
198+
///
199+
/// These are method declarations which are referenced from inlinable
200+
/// functions due to cross-module-optimzation. Those declarations don't have
201+
/// any attributes or linkage which mark them as externally visible by
202+
/// default.
203+
/// Currently this table is not serialized.
204+
llvm::SetVector<ValueDecl *> externallyVisible;
205+
197206
/// Lookup table for SIL Global Variables.
198207
llvm::StringMap<SILGlobalVariable *> GlobalVariableMap;
199208

@@ -446,6 +455,13 @@ class SILModule {
446455
return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
447456
}
448457

458+
void addExternallyVisibleDecl(ValueDecl *decl) {
459+
externallyVisible.insert(decl);
460+
}
461+
bool isExternallyVisibleDecl(ValueDecl *decl) {
462+
return externallyVisible.count(decl) != 0;
463+
}
464+
449465
using sil_global_iterator = GlobalListType::iterator;
450466
using sil_global_const_iterator = GlobalListType::const_iterator;
451467
GlobalListType &getSILGlobalList() { return silGlobals; }

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",

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ struct LLVM_LIBRARY_VISIBILITY FindLocalApplySitesResult {
388388
Optional<FindLocalApplySitesResult>
389389
findLocalApplySites(FunctionRefBaseInst *fri);
390390

391+
/// Gets the base implementation of a method.
392+
AbstractFunctionDecl *getBaseMethod(AbstractFunctionDecl *FD);
393+
391394
} // end namespace swift
392395

393396
#endif

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/SIL/SILInstructions.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,46 @@ void KeyPathInst::dropReferencedPattern() {
24192419
Pattern = nullptr;
24202420
}
24212421

2422+
void KeyPathPatternComponent::
2423+
visitReferencedFunctionsAndMethods(
2424+
std::function<void (SILFunction *)> functionCallBack,
2425+
std::function<void (SILDeclRef)> methodCallBack) const {
2426+
switch (getKind()) {
2427+
case KeyPathPatternComponent::Kind::SettableProperty:
2428+
functionCallBack(getComputedPropertySetter());
2429+
LLVM_FALLTHROUGH;
2430+
case KeyPathPatternComponent::Kind::GettableProperty: {
2431+
functionCallBack(getComputedPropertyGetter());
2432+
auto id = getComputedPropertyId();
2433+
switch (id.getKind()) {
2434+
case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
2435+
methodCallBack(id.getDeclRef());
2436+
break;
2437+
}
2438+
case KeyPathPatternComponent::ComputedPropertyId::Function:
2439+
functionCallBack(id.getFunction());
2440+
break;
2441+
case KeyPathPatternComponent::ComputedPropertyId::Property:
2442+
break;
2443+
}
2444+
2445+
if (auto equals = getSubscriptIndexEquals())
2446+
functionCallBack(equals);
2447+
if (auto hash = getSubscriptIndexHash())
2448+
functionCallBack(hash);
2449+
2450+
break;
2451+
}
2452+
case KeyPathPatternComponent::Kind::StoredProperty:
2453+
case KeyPathPatternComponent::Kind::OptionalChain:
2454+
case KeyPathPatternComponent::Kind::OptionalForce:
2455+
case KeyPathPatternComponent::Kind::OptionalWrap:
2456+
case KeyPathPatternComponent::Kind::TupleElement:
2457+
break;
2458+
}
2459+
}
2460+
2461+
24222462
GenericSpecializationInformation::GenericSpecializationInformation(
24232463
SILFunction *Caller, SILFunction *Parent, SubstitutionMap Subs)
24242464
: Caller(Caller), Parent(Parent), Subs(Subs) {}

lib/SIL/SILPrinter.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2695,6 +2695,18 @@ static void printSILProperties(SILPrintContext &Ctx,
26952695
}
26962696
}
26972697

2698+
static void printExternallyVisibleDecls(SILPrintContext &Ctx,
2699+
ArrayRef<ValueDecl *> decls) {
2700+
if (decls.empty())
2701+
return;
2702+
Ctx.OS() << "/* externally visible decls: \n";
2703+
for (ValueDecl *decl : decls) {
2704+
printValueDecl(decl, Ctx.OS());
2705+
Ctx.OS() << '\n';
2706+
}
2707+
Ctx.OS() << "*/\n";
2708+
}
2709+
26982710
/// Pretty-print the SILModule to the designated stream.
26992711
void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M,
27002712
bool PrintASTDecls) const {
@@ -2761,7 +2773,8 @@ void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M,
27612773
printSILDefaultWitnessTables(PrintCtx, getDefaultWitnessTableList());
27622774
printSILCoverageMaps(PrintCtx, getCoverageMaps());
27632775
printSILProperties(PrintCtx, getPropertyList());
2764-
2776+
printExternallyVisibleDecls(PrintCtx, externallyVisible.getArrayRef());
2777+
27652778
OS << "\n\n";
27662779
}
27672780

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)