Skip to content

Remove the -sil-serialize-all option #12256

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 11 commits into from
Oct 6, 2017
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
16 changes: 7 additions & 9 deletions docs/HighLevelSILOptimizations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,13 @@ Cloning code from the standard library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Swift compiler can copy code from the standard library into the
application. This allows the optimizer to inline calls from stdlib and improve
the performance of code that uses common operators such as '++' or basic
containers such as Array. However, importing code from the standard library can
increase the binary size. Marking functions with @_semantics("stdlib_binary_only")
will prevent the copying of the marked function from the standard library into the
user program.

Notice that this annotation is similar to the resilient annotation that will
disallow the cloning of code into the user application.
application for functions marked @_inlineable. This allows the optimizer to
inline calls from the stdlib and improve the performance of code that uses
common operators such as '+=' or basic containers such as Array. However,
importing code from the standard library can increase the binary size.

To prevent copying of functions from the standard library into the user
program, make sure the function in question is not marked @_inlineable.

Array
~~~~~
Expand Down
6 changes: 0 additions & 6 deletions docs/Lexicon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,6 @@ source code, tests, and commit messages. See also the `LLVM lexicon`_.
"Swift Intermediate Language". A high-level IR used by the Swift compiler
for flow-sensitive diagnostics, optimization, and LLVM IR generation.

-sil-serialize-all
A mode where all functions in a library are made available for inlining by
any client, regardless of access control. Also called "magic performance
mode" as a reminder of how this drastically changes compilation. Not
guaranteed to work on arbitrary code.

SR
An issue reported on `bugs.swift.org <https://bugs.swift.org>`_. A
backronym for "Swift Report"; really the name is derived from LLVM's
Expand Down
8 changes: 1 addition & 7 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,7 @@ enum class ResilienceStrategy : unsigned {
/// Non-inlineable function bodies: resilient
///
/// This is the behavior with -enable-resilience.
Resilient,

/// Public nominal types: fragile
/// Non-inlineable function bodies: fragile
///
/// This is the behavior with -sil-serialize-all.
Fragile
Resilient
};

/// The minimum unit of compilation.
Expand Down
5 changes: 0 additions & 5 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,6 @@ class SILOptions {
/// \brief Enable large loadable types IRGen pass.
bool EnableLargeLoadableTypes = true;

/// Enables the "fully fragile" resilience strategy.
///
/// \see ResilienceStrategy::Fragile
bool SILSerializeAll = false;

/// If set, SIL witness tables will be serialized.
///
/// It is supposed to be used only for compiling overlays.
Expand Down
6 changes: 0 additions & 6 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,11 +567,6 @@ class LinkEntity {
///
bool isAvailableExternally(IRGenModule &IGM) const;

/// Returns true if this function or global variable may be inlined into
/// another module.
///
bool isFragile(ForDefinition_t isDefinition) const;

const ValueDecl *getDecl() const {
assert(isDeclKind(getKind()));
return reinterpret_cast<ValueDecl*>(Pointer);
Expand Down Expand Up @@ -686,7 +681,6 @@ class LinkInfo {
static LinkInfo get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
bool isFragile,
bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported);
Expand Down
3 changes: 0 additions & 3 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,6 @@ def sil_merge_partial_modules : Flag<["-"], "sil-merge-partial-modules">,
def sil_link_all : Flag<["-"], "sil-link-all">,
HelpText<"Link all SIL functions">;

def sil_serialize_all : Flag<["-"], "sil-serialize-all">,
HelpText<"Serialize all generated SIL">;

def sil_serialize_witness_tables : Flag<["-"], "sil-serialize-witness-tables">,
HelpText<"Serialize eligible SIL witness tables">;

Expand Down
3 changes: 0 additions & 3 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,6 @@ class SILModule {
return wholeModule;
}

/// Returns true if everything in this SILModule is being serialized.
bool isWholeModuleSerialized() const { return Options.SILSerializeAll; }

/// Returns true if it is the OnoneSupport module.
bool isOnoneSupportModule() const;

Expand Down
2 changes: 0 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,6 @@ bool AbstractStorageDecl::hasFixedLayout() const {
switch (getDeclContext()->getParentModule()->getResilienceStrategy()) {
case ResilienceStrategy::Resilient:
return false;
case ResilienceStrategy::Fragile:
case ResilienceStrategy::Default:
return true;
}
Expand Down Expand Up @@ -2217,7 +2216,6 @@ bool NominalTypeDecl::hasFixedLayout() const {
switch (getParentModule()->getResilienceStrategy()) {
case ResilienceStrategy::Resilient:
return false;
case ResilienceStrategy::Fragile:
case ResilienceStrategy::Default:
return true;
}
Expand Down
1 change: 0 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,6 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_sil_merge_partial_modules))
Opts.MergePartialModules = true;

Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
Opts.SILSerializeWitnessTables |=
Args.hasArg(OPT_sil_serialize_witness_tables);
Opts.SILSerializeVTables |=
Expand Down
2 changes: 0 additions & 2 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,6 @@ ModuleDecl *CompilerInstance::getMainModule() {

if (Invocation.getFrontendOptions().EnableResilience)
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
else if (Invocation.getSILOptions().SILSerializeAll)
MainModule->setResilienceStrategy(ResilienceStrategy::Fragile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot to remove ResiienceStrategy::Fragile

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slavapestov In cases like below, should we check instead for SILSerializeWitnessTables or remove them alltogether?


if (isProtocolConformanceKind(getKind())) {
    auto conformance = getProtocolConformance();

    auto conformanceModule = conformance->getDeclContext()->getParentModule();
    auto isCompletelySerialized = conformanceModule->getResilienceStrategy() ==
                                  ResilienceStrategy::Fragile;

    // The conformance is fragile if it is in a -sil-serialize-all module.
    return isCompletelySerialized;
  }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should check your flag yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slavapestov Hmm. There is a small problem here. The code above is inside LinkEntity::isFragile, which does not contain any reference to the SILModule, which has SILSerializeWitnessTables flag. It can only access ModuleDecl through conformance->getDeclContext()->getParentModule().

How do we solve this in the cleanest way? Should we add an IGM argument to the function? Should we add a flag for -sil-serialize-witness-tables and -sil-serialize-vtables to the ModuleDecl or may be even have a reference from ModuleDecl to SILOptions?

BTW, why don't ModuleDecls have a back-reference to the SILModules? It could be useful for such cases...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I moved SILSerializeWitnessTables and SILSerializeVTables into LanguageOptions, so that they are accessible from ASTContext and ModuleDecl.

}
return MainModule;
}
Expand Down
2 changes: 0 additions & 2 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,8 +925,6 @@ static bool performCompile(CompilerInstance &Instance,
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str();
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
serializationOpts.SerializeAllSIL =
Invocation.getSILOptions().SILSerializeAll;
if (opts.SerializeBridgingHeader)
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
Expand Down
72 changes: 7 additions & 65 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,44 +1314,11 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
llvm_unreachable("bad link entity kind");
}

bool LinkEntity::isFragile(ForDefinition_t isDefinition) const {
switch (getKind()) {
case Kind::SILFunction:
return getSILFunction()->isSerialized();

case Kind::SILGlobalVariable:
return getSILGlobalVariable()->isSerialized();

case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ReflectionSuperclassDescriptor:
case Kind::AssociatedTypeMetadataAccessFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::GenericProtocolWitnessTableCache:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::ObjCClassRef:
return false;

default:
break;
}
if (isProtocolConformanceKind(getKind())) {
auto conformance = getProtocolConformance();

auto conformanceModule = conformance->getDeclContext()->getParentModule();
auto isCompletelySerialized = conformanceModule->getResilienceStrategy() ==
ResilienceStrategy::Fragile;

// The conformance is fragile if it is in a -sil-serialize-all module.
return isCompletelySerialized;
}
return false;
}

static std::tuple<llvm::GlobalValue::LinkageTypes,
llvm::GlobalValue::VisibilityTypes,
llvm::GlobalValue::DLLStorageClassTypes>
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
bool isFragile, bool isSILOnly, ForDefinition_t isDefinition,
bool isSILOnly, ForDefinition_t isDefinition,
bool isWeakImported) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage, \
Expand All @@ -1372,29 +1339,6 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
info.UseDLLStorage ? llvm::GlobalValue::DLLImportStorageClass
: llvm::GlobalValue::DefaultStorageClass;

if (isFragile) {
// Fragile functions/globals must be visible from outside, regardless of
// their access level. If a caller is also fragile and inlined into another
// module it must be able to access this (not-inlined) function/global.
switch (linkage) {
case SILLinkage::Hidden:
case SILLinkage::Private:
linkage = SILLinkage::Public;
break;

case SILLinkage::HiddenExternal:
case SILLinkage::PrivateExternal:
linkage = SILLinkage::PublicExternal;
break;

case SILLinkage::Public:
case SILLinkage::Shared:
case SILLinkage::PublicExternal:
case SILLinkage::SharedExternal:
break;
}
}

switch (linkage) {
case SILLinkage::Public:
// Don't code-gen transparent functions. Internal linkage will enable llvm
Expand Down Expand Up @@ -1453,8 +1397,7 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
return std::make_tuple(isDefinition
? llvm::GlobalValue::AvailableExternallyLinkage
: llvm::GlobalValue::ExternalLinkage,
isFragile ? llvm::GlobalValue::DefaultVisibility
: llvm::GlobalValue::HiddenVisibility,
llvm::GlobalValue::HiddenVisibility,
ImportedStorage);

}
Expand All @@ -1472,7 +1415,7 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
UniversalLinkageInfo linkInfo(IGM);
auto linkage =
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
entity.isFragile(ForDefinition), entity.isSILOnly(),
entity.isSILOnly(),
ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
global->setLinkage(std::get<0>(linkage));
global->setVisibility(std::get<1>(linkage));
Expand Down Expand Up @@ -1504,7 +1447,7 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,

std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(linkInfo, entity.getLinkage(isDefinition),
entity.isFragile(isDefinition), entity.isSILOnly(),
entity.isSILOnly(),
isDefinition, entity.isWeakImported(swiftModule));

result.ForDefinition = isDefinition;
Expand All @@ -1515,20 +1458,19 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
bool isFragile,
bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported) {
LinkInfo result;

result.Name += name;
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(linkInfo, linkage, isFragile, isSILOnly,
getIRLinkage(linkInfo, linkage, isSILOnly,
isDefinition, isWeakImported);
result.ForDefinition = isDefinition;
return result;
}

static bool isPointerTo(llvm::Type *ptrTy, llvm::Type *objTy) {
return cast<llvm::PointerType>(ptrTy)->getElementType() == objTy;
}
Expand Down
1 change: 0 additions & 1 deletion lib/IRGen/GenKeyPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ getWitnessTableForComputedComponent(IRGenModule &IGM,

auto linkInfo = LinkInfo::get(IGM, "swift_keyPathGenericWitnessTable",
SILLinkage::PublicExternal,
/*fragile*/ false,
/*sil only*/ false,
NotForDefinition,
/*weak imported*/ false);
Expand Down
29 changes: 0 additions & 29 deletions lib/SIL/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,6 @@ using namespace Lowering;

STATISTIC(NumFuncLinked, "Number of SIL functions linked");

//===----------------------------------------------------------------------===//
// Utility
//===----------------------------------------------------------------------===//

/// \return True if the function \p F should be imported into the current
/// module.
static bool shouldImportFunction(SILFunction *F) {
// Skip functions that are marked with the 'no import' tag. These
// are functions that we don't want to copy from the module.
if (F->hasSemanticsAttr("stdlib_binary_only")) {
// If we are importing a function declaration mark it as external since we
// are not importing the body.
if (F->isExternalDeclaration())
F->setLinkage(SILLinkage::PublicExternal);
return false;
}

return true;
}

//===----------------------------------------------------------------------===//
// Linker Helpers
//===----------------------------------------------------------------------===//
Expand All @@ -55,9 +35,6 @@ bool SILLinkerVisitor::processFunction(SILFunction *F) {
if (Mode == LinkingMode::LinkNone)
return false;

if (!shouldImportFunction(F))
return false;

// If F is a declaration, first deserialize it.
if (F->isExternalDeclaration()) {
auto *NewFn = Loader->lookupSILFunction(F);
Expand Down Expand Up @@ -334,9 +311,6 @@ bool SILLinkerVisitor::process() {
while (!Worklist.empty()) {
auto *Fn = Worklist.pop_back_val();

if (!shouldImportFunction(Fn))
continue;

DEBUG(llvm::dbgs() << "Process imports in function: "
<< Fn->getName() << "\n");

Expand All @@ -346,9 +320,6 @@ bool SILLinkerVisitor::process() {
if (visit(&I)) {
for (auto *F : FunctionDeserializationWorklist) {

if (!shouldImportFunction(F))
continue;

DEBUG(llvm::dbgs() << "Imported function: "
<< F->getName() << "\n");
F->setBare(IsBare);
Expand Down
5 changes: 0 additions & 5 deletions lib/SIL/SIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ FormalLinkage swift::getDeclLinkage(const ValueDecl *D) {
case AccessLevel::Open:
return FormalLinkage::PublicUnique;
case AccessLevel::Internal:
// If we're serializing all function bodies, type metadata for internal
// types needs to be public too.
if (D->getDeclContext()->getParentModule()->getResilienceStrategy()
== ResilienceStrategy::Fragile)
return FormalLinkage::PublicUnique;
return FormalLinkage::HiddenUnique;
case AccessLevel::FilePrivate:
case AccessLevel::Private:
Expand Down
14 changes: 1 addition & 13 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,6 @@ SILFunction *SILGenModule::getEmittedFunction(SILDeclRef constant,
if (isAvailableExternally(F->getLinkage())) {
F->setLinkage(constant.getLinkage(ForDefinition));
}
if (isMakeModuleFragile()) {
F->setSerialized(IsSerialized);
}
}
return F;
}
Expand Down Expand Up @@ -523,13 +520,6 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,

assert(F && "SILFunction should have been defined");

if (isMakeModuleFragile()) {
SILLinkage linkage = constant.getLinkage(forDefinition);
if (linkage != SILLinkage::PublicExternal) {
F->setSerialized(IsSerialized);
}
}

emittedFunctions[constant] = F;

// If we delayed emitting this function previously, we need it now.
Expand Down Expand Up @@ -994,9 +984,7 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
M.createFunction(SILLinkage::Private,
funcName, initSILType, nullptr,
SILLocation(binding), IsNotBare, IsNotTransparent,
isMakeModuleFragile()
? IsSerialized
: IsNotSerialized);
IsNotSerialized);
f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
SILGenFunction(*this, *f).emitLazyGlobalInitializer(binding, pbdEntry);
f->verify();
Expand Down
Loading