Skip to content

Commit 8612cd0

Browse files
authored
Merge pull request #40589 from eeckstein/new-cmo
rework cross-module-optimization
2 parents 6b36b87 + 408cf02 commit 8612cd0

24 files changed

+474
-374
lines changed

include/swift/AST/TBDGenRequests.h

+27-7
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,13 @@ class TBDGenDescriptor final {
5050
FileOrModule Input;
5151
TBDGenOptions Opts;
5252

53-
TBDGenDescriptor(FileOrModule input, const TBDGenOptions &opts)
54-
: Input(input), Opts(opts) {
53+
/// Symbols (e.g. function names) which are made public by the
54+
/// CrossModuleOptimization pass and therefore must be included in the TBD file.
55+
TBDSymbolSetPtr publicCMOSymbols;
56+
57+
TBDGenDescriptor(FileOrModule input, const TBDGenOptions &opts,
58+
TBDSymbolSetPtr publicCMOSymbols)
59+
: Input(input), Opts(opts), publicCMOSymbols(publicCMOSymbols) {
5560
assert(input);
5661
}
5762

@@ -73,17 +78,21 @@ class TBDGenDescriptor final {
7378
const StringRef getDataLayoutString() const;
7479
const llvm::Triple &getTarget() const;
7580

81+
TBDSymbolSetPtr getPublicCMOSymbols() const { return publicCMOSymbols; }
82+
7683
bool operator==(const TBDGenDescriptor &other) const;
7784
bool operator!=(const TBDGenDescriptor &other) const {
7885
return !(*this == other);
7986
}
8087

81-
static TBDGenDescriptor forFile(FileUnit *file, const TBDGenOptions &opts) {
82-
return TBDGenDescriptor(file, opts);
88+
static TBDGenDescriptor forFile(FileUnit *file, const TBDGenOptions &opts,
89+
TBDSymbolSetPtr publicCMOSymbols) {
90+
return TBDGenDescriptor(file, opts, publicCMOSymbols);
8391
}
8492

85-
static TBDGenDescriptor forModule(ModuleDecl *M, const TBDGenOptions &opts) {
86-
return TBDGenDescriptor(M, opts);
93+
static TBDGenDescriptor forModule(ModuleDecl *M, const TBDGenOptions &opts,
94+
TBDSymbolSetPtr publicCMOSymbols) {
95+
return TBDGenDescriptor(M, opts, publicCMOSymbols);
8796
}
8897
};
8998

@@ -154,6 +163,9 @@ class SymbolSource {
154163
/// A symbol used to customize linker behavior, introduced by TBDGen.
155164
LinkerDirective,
156165

166+
/// A symbol which was made public by the CrossModuleOptimization pass.
167+
CrossModuleOptimization,
168+
157169
/// A symbol with an unknown origin.
158170
// FIXME: This should be eliminated.
159171
Unknown
@@ -173,7 +185,8 @@ class SymbolSource {
173185
irEntity = entity;
174186
}
175187
explicit SymbolSource(Kind kind) : kind(kind) {
176-
assert(kind == Kind::LinkerDirective || kind == Kind::Unknown);
188+
assert(kind == Kind::LinkerDirective || kind == Kind::Unknown ||
189+
kind == Kind::CrossModuleOptimization);
177190
}
178191

179192
public:
@@ -186,6 +199,9 @@ class SymbolSource {
186199
static SymbolSource forLinkerDirective() {
187200
return SymbolSource{Kind::LinkerDirective};
188201
}
202+
static SymbolSource forCrossModuleOptimization() {
203+
return SymbolSource{Kind::CrossModuleOptimization};
204+
}
189205
static SymbolSource forUnknown() {
190206
return SymbolSource{Kind::Unknown};
191207
}
@@ -194,6 +210,10 @@ class SymbolSource {
194210
return kind == Kind::LinkerDirective;
195211
}
196212

213+
bool isFromCrossModuleOptimization() const {
214+
return kind == Kind::CrossModuleOptimization;
215+
}
216+
197217
SILDeclRef getSILDeclRef() const {
198218
assert(kind == Kind::SIL);
199219
return silDeclRef;

include/swift/Frontend/Frontend.h

+5
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ class CompilerInstance {
432432
std::unique_ptr<ASTContext> Context;
433433
std::unique_ptr<Lowering::TypeConverter> TheSILTypes;
434434
std::unique_ptr<DiagnosticVerifier> DiagVerifier;
435+
TBDSymbolSetPtr publicCMOSymbols;
435436

436437
/// A cache describing the set of inter-module dependencies that have been queried.
437438
/// Null if not present.
@@ -583,6 +584,10 @@ class CompilerInstance {
583584
/// file.
584585
SourceFile *getCodeCompletionFile() const;
585586

587+
/// Return the symbols (e.g. function names) which are made public by the
588+
/// CrossModuleOptimization pass and therefore must be included in the TBD file.
589+
TBDSymbolSetPtr getPublicCMOSymbols() const { return publicCMOSymbols; }
590+
586591
private:
587592
/// Set up the file system by loading and validating all VFS overlay YAML
588593
/// files. If the process of validating VFS files failed, or the overlay

include/swift/SIL/SILModule.h

+11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "swift/SIL/SILVTable.h"
3939
#include "swift/SIL/SILWitnessTable.h"
4040
#include "swift/SIL/TypeLowering.h"
41+
#include "swift/TBDGen/TBDGen.h"
4142
#include "llvm/ADT/ArrayRef.h"
4243
#include "llvm/ADT/FoldingSet.h"
4344
#include "llvm/ADT/MapVector.h"
@@ -367,6 +368,10 @@ class SILModule {
367368

368369
/// Folding set for key path patterns.
369370
llvm::FoldingSet<KeyPathPattern> KeyPathPatterns;
371+
372+
/// Symbols (e.g. function names) which are made public by the
373+
/// CrossModuleOptimization pass and therefore must be included in the TBD file.
374+
TBDSymbolSetPtr publicCMOSymbols;
370375

371376
public:
372377
~SILModule();
@@ -506,6 +511,12 @@ class SILModule {
506511

507512
const SILOptions &getOptions() const { return Options; }
508513

514+
/// Return the symbols (e.g. function names) which are made public by the
515+
/// CrossModuleOptimization pass and therefore must be included in the TBD file.
516+
TBDSymbolSetPtr getPublicCMOSymbols() { return publicCMOSymbols; }
517+
518+
void addPublicCMOSymbol(StringRef symbol);
519+
509520
using iterator = FunctionListType::iterator;
510521
using const_iterator = FunctionListType::const_iterator;
511522
FunctionListType &getFunctionList() { return functions; }

include/swift/SILOptimizer/PassManager/Passes.def

+2-4
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ PASS(AccessEnforcementSelection, "access-enforcement-selection",
110110
"Access Enforcement Selection")
111111
PASS(AccessEnforcementWMO, "access-enforcement-wmo",
112112
"Access Enforcement Whole Module Optimization")
113-
PASS(CrossModuleSerializationSetup, "cross-module-serialization-setup",
114-
"Setup serialization flags for cross-module optimization")
113+
PASS(CrossModuleOptimization, "cmo",
114+
"Perform cross-module optimization")
115115
PASS(AccessSummaryDumper, "access-summary-dump",
116116
"Dump Address Parameter Access Summary")
117117
PASS(AccessStorageAnalysisDumper, "access-storage-analysis-dump",
@@ -405,8 +405,6 @@ PASS(SimplifyUnreachableContainingBlocks, "simplify-unreachable-containing-block
405405
"Utility pass. Removes all non-term insts from blocks with unreachable terms")
406406
PASS(SerializeSILPass, "serialize-sil",
407407
"Utility pass. Serializes the current SILModule")
408-
PASS(CMOSerializeSILPass, "cmo-serialize-sil",
409-
"Utility pass. Serializes the current SILModule for cross-module-optimization")
410408
PASS(YieldOnceCheck, "yield-once-check",
411409
"Check correct usage of yields in yield-once coroutines")
412410
PASS(OSLogOptimization, "os-log-optimization", "Optimize os log calls")

include/swift/TBDGen/TBDGen.h

+19-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include "llvm/ADT/StringSet.h"
1717
#include "swift/Basic/Version.h"
1818
#include <vector>
19+
#include <set>
20+
#include <string>
21+
#include <memory>
1922

2023
namespace llvm {
2124
class raw_ostream;
@@ -104,12 +107,26 @@ struct TBDGenOptions {
104107
}
105108
};
106109

110+
/// Used for symbols which are made public by the CrossModuleOptimization pass
111+
/// and therefore must be included in the TBD file.
112+
///
113+
/// We cannot use llvm::StringSet, because we need deterministic iteration order.
114+
using TBDSymbolSet = std::set<std::string>;
115+
116+
/// A pointer to TBDSymbolSet.
117+
///
118+
/// Do reference counting for memory management.
119+
/// This set is created in the optimizer and primarily stored in the SILModule.
120+
/// But then they need to be kept alive beyond the lifetime of the SILModule.
121+
using TBDSymbolSetPtr = std::shared_ptr<TBDSymbolSet>;
122+
107123
std::vector<std::string> getPublicSymbols(TBDGenDescriptor desc);
108124

109125
void writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
110-
const TBDGenOptions &opts);
126+
const TBDGenOptions &opts, TBDSymbolSetPtr publicCMOSymbols);
111127

112-
void writeAPIJSONFile(ModuleDecl *M, llvm::raw_ostream &os, bool PrettyPrint);
128+
void writeAPIJSONFile(ModuleDecl *M, llvm::raw_ostream &os, bool PrettyPrint,
129+
TBDSymbolSetPtr publicCMOSymbols);
113130

114131
} // end namespace swift
115132

lib/AST/Module.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -2374,17 +2374,18 @@ canBeUsedForCrossModuleOptimization(DeclContext *ctxt) const {
23742374
// See if context is imported in a "regular" way, i.e. not with
23752375
// @_implementationOnly or @_spi.
23762376
ModuleDecl::ImportFilter filter = {
2377-
ModuleDecl::ImportFilterKind::Exported,
2378-
ModuleDecl::ImportFilterKind::Default};
2377+
ModuleDecl::ImportFilterKind::ImplementationOnly,
2378+
ModuleDecl::ImportFilterKind::SPIAccessControl
2379+
};
23792380
SmallVector<ImportedModule, 4> results;
23802381
getImportedModules(results, filter);
23812382

23822383
auto &imports = getASTContext().getImportCache();
23832384
for (auto &desc : results) {
23842385
if (imports.isImportedBy(moduleOfCtxt, desc.importedModule))
2385-
return true;
2386+
return false;
23862387
}
2387-
return false;
2388+
return true;
23882389
}
23892390

23902391
void SourceFile::lookupImportedSPIGroups(

lib/DriverTool/swift_api_extract_main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class SwiftAPIExtractInvocation {
215215
return 1;
216216

217217
if (OutputFilename == "-") {
218-
writeAPIJSONFile(M, llvm::outs(), PrettyPrint);
218+
writeAPIJSONFile(M, llvm::outs(), PrettyPrint, nullptr);
219219
return 0;
220220
}
221221

@@ -227,7 +227,7 @@ class SwiftAPIExtractInvocation {
227227
return 1;
228228
}
229229

230-
writeAPIJSONFile(M, OS, PrettyPrint);
230+
writeAPIJSONFile(M, OS, PrettyPrint, nullptr);
231231
return 0;
232232
}
233233
};

lib/Frontend/Frontend.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,8 @@ bool CompilerInstance::performSILProcessing(SILModule *silModule) {
13361336

13371337
performSILOptimizations(Invocation, silModule);
13381338

1339+
publicCMOSymbols = silModule->getPublicCMOSymbols();
1340+
13391341
if (auto *stats = getStatsReporter())
13401342
countStatsPostSILOpt(*stats, *silModule);
13411343

lib/FrontendTool/FrontendTool.cpp

+16-17
Original file line numberDiff line numberDiff line change
@@ -692,15 +692,10 @@ static bool writeTBDIfNeeded(CompilerInstance &Instance) {
692692
return false;
693693
}
694694

695-
if (Invocation.getSILOptions().CrossModuleOptimization) {
696-
Instance.getDiags().diagnose(SourceLoc(),
697-
diag::tbd_not_supported_with_cmo);
698-
return false;
699-
}
700-
701695
const std::string &TBDPath = Invocation.getTBDPathForWholeModule();
702696

703-
return writeTBD(Instance.getMainModule(), TBDPath, tbdOpts);
697+
return writeTBD(Instance.getMainModule(), TBDPath, tbdOpts,
698+
Instance.getPublicCMOSymbols());
704699
}
705700

706701
static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
@@ -1353,19 +1348,19 @@ static bool processCommandLineAndRunImmediately(CompilerInstance &Instance,
13531348

13541349
static bool validateTBDIfNeeded(const CompilerInvocation &Invocation,
13551350
ModuleOrSourceFile MSF,
1356-
const llvm::Module &IRModule) {
1357-
const auto mode = Invocation.getFrontendOptions().ValidateTBDAgainstIR;
1351+
const llvm::Module &IRModule,
1352+
TBDSymbolSetPtr publicCMOSymbols) {
1353+
auto mode = Invocation.getFrontendOptions().ValidateTBDAgainstIR;
1354+
if (mode == FrontendOptions::TBDValidationMode::All &&
1355+
Invocation.getSILOptions().CrossModuleOptimization)
1356+
mode = FrontendOptions::TBDValidationMode::MissingFromTBD;
1357+
13581358
const bool canPerformTBDValidation = [&]() {
13591359
// If the user has requested we skip validation, honor it.
13601360
if (mode == FrontendOptions::TBDValidationMode::None) {
13611361
return false;
13621362
}
13631363

1364-
// Cross-module optimization does not support TBD.
1365-
if (Invocation.getSILOptions().CrossModuleOptimization) {
1366-
return false;
1367-
}
1368-
13691364
// If we can't validate the given input file, bail early. This covers cases
13701365
// like passing raw SIL as a primary file.
13711366
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
@@ -1426,9 +1421,10 @@ static bool validateTBDIfNeeded(const CompilerInvocation &Invocation,
14261421
// noise from e.g. statically-linked libraries.
14271422
Opts.embedSymbolsFromModules.clear();
14281423
if (auto *SF = MSF.dyn_cast<SourceFile *>()) {
1429-
return validateTBD(SF, IRModule, Opts, diagnoseExtraSymbolsInTBD);
1424+
return validateTBD(SF, IRModule, Opts, publicCMOSymbols,
1425+
diagnoseExtraSymbolsInTBD);
14301426
} else {
1431-
return validateTBD(MSF.get<ModuleDecl *>(), IRModule, Opts,
1427+
return validateTBD(MSF.get<ModuleDecl *>(), IRModule, Opts, publicCMOSymbols,
14321428
diagnoseExtraSymbolsInTBD);
14331429
}
14341430
}
@@ -1621,6 +1617,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
16211617
return processCommandLineAndRunImmediately(
16221618
Instance, std::move(SM), MSF, observer, ReturnValue);
16231619

1620+
TBDSymbolSetPtr publicCMOSymbols = SM->getPublicCMOSymbols();
1621+
16241622
StringRef OutputFilename = PSPs.OutputFilename;
16251623
std::vector<std::string> ParallelOutputFilenames =
16261624
opts.InputsAndOutputs.copyOutputFilenames();
@@ -1635,7 +1633,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
16351633
if (!IRModule)
16361634
return Instance.getDiags().hadAnyError();
16371635

1638-
if (validateTBDIfNeeded(Invocation, MSF, *IRModule.getModule()))
1636+
if (validateTBDIfNeeded(Invocation, MSF, *IRModule.getModule(),
1637+
publicCMOSymbols))
16391638
return true;
16401639

16411640
return generateCode(Instance, OutputFilename, IRModule.getModule(),

lib/FrontendTool/TBD.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static std::vector<StringRef> sortSymbols(llvm::StringSet<> &symbols) {
4242
}
4343

4444
bool swift::writeTBD(ModuleDecl *M, StringRef OutputFilename,
45-
const TBDGenOptions &Opts) {
45+
const TBDGenOptions &Opts, TBDSymbolSetPtr publicCMOSymbols) {
4646
std::error_code EC;
4747
llvm::raw_fd_ostream OS(OutputFilename, EC, llvm::sys::fs::OF_None);
4848
if (EC) {
@@ -51,7 +51,7 @@ bool swift::writeTBD(ModuleDecl *M, StringRef OutputFilename,
5151
return true;
5252
}
5353

54-
writeTBDFile(M, OS, Opts);
54+
writeTBDFile(M, OS, Opts, publicCMOSymbols);
5555

5656
return false;
5757
}
@@ -126,17 +126,21 @@ static bool validateSymbols(DiagnosticEngine &diags,
126126
bool swift::validateTBD(ModuleDecl *M,
127127
const llvm::Module &IRModule,
128128
const TBDGenOptions &opts,
129+
TBDSymbolSetPtr publicCMOSymbols,
129130
bool diagnoseExtraSymbolsInTBD) {
130-
auto symbols = getPublicSymbols(TBDGenDescriptor::forModule(M, opts));
131+
auto symbols = getPublicSymbols(TBDGenDescriptor::forModule(M, opts,
132+
publicCMOSymbols));
131133
return validateSymbols(M->getASTContext().Diags, symbols, IRModule,
132134
diagnoseExtraSymbolsInTBD);
133135
}
134136

135137
bool swift::validateTBD(FileUnit *file,
136138
const llvm::Module &IRModule,
137139
const TBDGenOptions &opts,
140+
TBDSymbolSetPtr publicCMOSymbols,
138141
bool diagnoseExtraSymbolsInTBD) {
139-
auto symbols = getPublicSymbols(TBDGenDescriptor::forFile(file, opts));
142+
auto symbols = getPublicSymbols(TBDGenDescriptor::forFile(file, opts,
143+
publicCMOSymbols));
140144
return validateSymbols(file->getParentModule()->getASTContext().Diags,
141145
symbols, IRModule, diagnoseExtraSymbolsInTBD);
142146
}

lib/FrontendTool/TBD.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_FRONTENDTOOL_TBD_H
1515

1616
#include "swift/Frontend/FrontendOptions.h"
17+
#include "swift/TBDGen/TBDGen.h"
1718

1819
namespace llvm {
1920
class StringRef;
@@ -26,14 +27,16 @@ class FrontendOptions;
2627
struct TBDGenOptions;
2728

2829
bool writeTBD(ModuleDecl *M, StringRef OutputFilename,
29-
const TBDGenOptions &Opts);
30+
const TBDGenOptions &Opts, TBDSymbolSetPtr publicCMOSymbols);
3031
bool validateTBD(ModuleDecl *M,
3132
const llvm::Module &IRModule,
3233
const TBDGenOptions &opts,
34+
TBDSymbolSetPtr publicCMOSymbols,
3335
bool diagnoseExtraSymbolsInTBD);
3436
bool validateTBD(FileUnit *M,
3537
const llvm::Module &IRModule,
3638
const TBDGenOptions &opts,
39+
TBDSymbolSetPtr publicCMOSymbols,
3740
bool diagnoseExtraSymbolsInTBD);
3841
}
3942

lib/IRGen/IRGen.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,7 @@ getSymbolSourcesToEmit(const IRGenDescriptor &desc) {
10321032
irEntitiesToEmit.push_back(source->getIRLinkEntity());
10331033
break;
10341034
case SymbolSource::Kind::LinkerDirective:
1035+
case SymbolSource::Kind::CrossModuleOptimization:
10351036
case SymbolSource::Kind::Unknown:
10361037
llvm_unreachable("Not supported");
10371038
}

0 commit comments

Comments
 (0)