Skip to content

Cross module optimization #28407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class SILOptions {
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.
bool DisableSILPerfOptimizations = false;

/// Controls whether cross module optimization is enabled.
bool CrossModuleOptimization = false;

/// Controls whether or not paranoid verification checks are run.
bool VerifyAll = false;

Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,10 @@ def Oplayground : Flag<["-"], "Oplayground">, Group<O_Group>,
Flags<[HelpHidden, FrontendOption, ModuleInterfaceOption]>,
HelpText<"Compile with optimizations appropriate for a playground">;

def CrossModuleOptimization : Flag<["-"], "cross-module-optimization">,
Flags<[HelpHidden, FrontendOption]>,
HelpText<"Perform cross-module optimization">;

def RemoveRuntimeAsserts : Flag<["-"], "remove-runtime-asserts">,
Flags<[FrontendOption]>,
HelpText<"Remove runtime safety checks.">;
Expand Down
13 changes: 13 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2892,6 +2892,10 @@ class KeyPathPatternComponent {
return KeyPathPatternComponent(tupleIndex, ty);
}

void visitReferencedFunctionsAndMethods(
std::function<void (SILFunction *)> functionCallBack,
std::function<void (SILDeclRef)> methodCallBack) const;

void incrementRefCounts() const;
void decrementRefCounts() const;

Expand Down Expand Up @@ -2948,6 +2952,15 @@ class KeyPathPattern final

ArrayRef<KeyPathPatternComponent> getComponents() const;

void visitReferencedFunctionsAndMethods(
std::function<void (SILFunction *)> functionCallBack,
std::function<void (SILDeclRef)> methodCallBack) {
for (auto &component : getComponents()) {
component.visitReferencedFunctionsAndMethods(functionCallBack,
methodCallBack);
}
}

static KeyPathPattern *get(SILModule &M,
CanGenericSignature signature,
CanType rootType,
Expand Down
16 changes: 16 additions & 0 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ class SILModule {
/// The list of SILDefaultWitnessTables in the module.
DefaultWitnessTableListType defaultWitnessTables;

/// Declarations which are externally visible.
///
/// These are method declarations which are referenced from inlinable
/// functions due to cross-module-optimzation. Those declarations don't have
/// any attributes or linkage which mark them as externally visible by
/// default.
/// Currently this table is not serialized.
llvm::SetVector<ValueDecl *> externallyVisible;

/// Lookup table for SIL Global Variables.
llvm::StringMap<SILGlobalVariable *> GlobalVariableMap;

Expand Down Expand Up @@ -446,6 +455,13 @@ class SILModule {
return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
}

void addExternallyVisibleDecl(ValueDecl *decl) {
externallyVisible.insert(decl);
}
bool isExternallyVisibleDecl(ValueDecl *decl) {
return externallyVisible.count(decl) != 0;
}

using sil_global_iterator = GlobalListType::iterator;
using sil_global_const_iterator = GlobalListType::const_iterator;
GlobalListType &getSILGlobalList() { return silGlobals; }
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SILOptimizer/PassManager/Passes.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ PASS(AccessEnforcementSelection, "access-enforcement-selection",
"Access Enforcement Selection")
PASS(AccessEnforcementWMO, "access-enforcement-wmo",
"Access Enforcement Whole Module Optimization")
PASS(CrossModuleSerializationSetup, "cross-module-serialization-setup",
"Setup serialization flags for cross-module optimization")
PASS(AccessSummaryDumper, "access-summary-dump",
"Dump Address Parameter Access Summary")
PASS(AccessedStorageDumper, "accessed-storage-dump",
Expand Down
3 changes: 3 additions & 0 deletions include/swift/SILOptimizer/Utils/InstOptUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ struct LLVM_LIBRARY_VISIBILITY FindLocalApplySitesResult {
Optional<FindLocalApplySitesResult>
findLocalApplySites(FunctionRefBaseInst *fri);

/// Gets the base implementation of a method.
AbstractFunctionDecl *getBaseMethod(AbstractFunctionDecl *FD);

} // end namespace swift

#endif
4 changes: 2 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2995,7 +2995,7 @@ SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
/// Returns true if \p VD needs to be treated as publicly-accessible
/// at the SIL, LLVM, and machine levels due to being @usableFromInline.
bool ValueDecl::isUsableFromInline() const {
assert(getFormalAccess() == AccessLevel::Internal);
assert(getFormalAccess() <= AccessLevel::Internal);

if (getAttrs().hasAttribute<UsableFromInlineAttr>() ||
getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
Expand Down Expand Up @@ -3092,7 +3092,7 @@ static AccessLevel getAdjustedFormalAccess(const ValueDecl *VD,
return getMaximallyOpenAccessFor(VD);

if (treatUsableFromInlineAsPublic &&
access == AccessLevel::Internal &&
(access == AccessLevel::Internal || access == AccessLevel::Private) &&
VD->isUsableFromInline()) {
return AccessLevel::Public;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ ToolChain::constructInvocation(const CompileJobAction &job,
Arguments.push_back("-module-name");
Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));

if (context.Args.hasArg(options::OPT_CrossModuleOptimization)) {
Arguments.push_back("-cross-module-optimization");
}

addOutputsOfType(Arguments, context.Output, context.Args,
file_types::TY_OptRecord, "-save-optimization-record-path");

Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);
Opts.DebugSerialization |= Args.hasArg(OPT_sil_debug_serialization);
Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
Expand Down
3 changes: 3 additions & 0 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,9 @@ static bool validateTBDIfNeeded(CompilerInvocation &Invocation,
if (!astGuaranteedToCorrespondToSIL ||
!inputFileKindCanHaveTBDValidated(Invocation.getInputKind()))
return false;

if (Invocation.getSILOptions().CrossModuleOptimization)
return false;

const auto &frontendOpts = Invocation.getFrontendOptions();
auto mode = frontendOpts.ValidateTBDAgainstIR;
Expand Down
3 changes: 2 additions & 1 deletion lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,8 @@ IRGenModule::getAddrOfParentContextDescriptor(DeclContext *from,

// Wrap up private types in an anonymous context for the containing file
// unit so that the runtime knows they have unstable identity.
if (!fromAnonymousContext && Type->isOutermostPrivateOrFilePrivateScope())
if (!fromAnonymousContext && Type->isOutermostPrivateOrFilePrivateScope()
&& !Type->isUsableFromInline())
return {getAddrOfAnonymousContextDescriptor(Type),
ConstantReference::Direct};
}
Expand Down
40 changes: 40 additions & 0 deletions lib/SIL/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,46 @@ void KeyPathInst::dropReferencedPattern() {
Pattern = nullptr;
}

void KeyPathPatternComponent::
visitReferencedFunctionsAndMethods(
std::function<void (SILFunction *)> functionCallBack,
std::function<void (SILDeclRef)> methodCallBack) const {
switch (getKind()) {
case KeyPathPatternComponent::Kind::SettableProperty:
functionCallBack(getComputedPropertySetter());
LLVM_FALLTHROUGH;
case KeyPathPatternComponent::Kind::GettableProperty: {
functionCallBack(getComputedPropertyGetter());
auto id = getComputedPropertyId();
switch (id.getKind()) {
case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
methodCallBack(id.getDeclRef());
break;
}
case KeyPathPatternComponent::ComputedPropertyId::Function:
functionCallBack(id.getFunction());
break;
case KeyPathPatternComponent::ComputedPropertyId::Property:
break;
}

if (auto equals = getSubscriptIndexEquals())
functionCallBack(equals);
if (auto hash = getSubscriptIndexHash())
functionCallBack(hash);

break;
}
case KeyPathPatternComponent::Kind::StoredProperty:
case KeyPathPatternComponent::Kind::OptionalChain:
case KeyPathPatternComponent::Kind::OptionalForce:
case KeyPathPatternComponent::Kind::OptionalWrap:
case KeyPathPatternComponent::Kind::TupleElement:
break;
}
}


GenericSpecializationInformation::GenericSpecializationInformation(
SILFunction *Caller, SILFunction *Parent, SubstitutionMap Subs)
: Caller(Caller), Parent(Parent), Subs(Subs) {}
Expand Down
15 changes: 14 additions & 1 deletion lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2695,6 +2695,18 @@ static void printSILProperties(SILPrintContext &Ctx,
}
}

static void printExternallyVisibleDecls(SILPrintContext &Ctx,
ArrayRef<ValueDecl *> decls) {
if (decls.empty())
return;
Ctx.OS() << "/* externally visible decls: \n";
for (ValueDecl *decl : decls) {
printValueDecl(decl, Ctx.OS());
Ctx.OS() << '\n';
}
Ctx.OS() << "*/\n";
}

/// Pretty-print the SILModule to the designated stream.
void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M,
bool PrintASTDecls) const {
Expand Down Expand Up @@ -2761,7 +2773,8 @@ void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M,
printSILDefaultWitnessTables(PrintCtx, getDefaultWitnessTableList());
printSILCoverageMaps(PrintCtx, getCoverageMaps());
printSILProperties(PrintCtx, getPropertyList());

printExternallyVisibleDecls(PrintCtx, externallyVisible.getArrayRef());

OS << "\n\n";
}

Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/IPO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ silopt_register_sources(
CapturePromotion.cpp
CapturePropagation.cpp
ClosureSpecializer.cpp
CrossModuleSerializationSetup.cpp
DeadFunctionElimination.cpp
EagerSpecializer.cpp
GlobalOpt.cpp
Expand Down
Loading