Skip to content

Commit e1ac443

Browse files
authored
Merge pull request #41642 from eeckstein/cmo-and-tbd
cross-module-optimization: be more conservative when emitting a TBD file.
2 parents adabdcb + 1dfb3b1 commit e1ac443

File tree

6 files changed

+99
-4
lines changed

6 files changed

+99
-4
lines changed

include/swift/AST/SILOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class SILOptions {
172172
/// Emit a mapping of profile counters for use in coverage.
173173
bool EmitProfileCoverageMapping = false;
174174

175+
bool emitTBD = false;
176+
175177
/// Should we use a pass pipeline passed in via a json file? Null by default.
176178
llvm::StringRef ExternalPassPipelineFilename;
177179

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
16701670
OPT_disable_previous_implementation_calls_in_dynamic_replacements);
16711671
Opts.ParseStdlib = FEOpts.ParseStdlib;
16721672

1673+
Opts.emitTBD = FEOpts.InputsAndOutputs.hasTBDPath();
1674+
16731675
if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_EQ)) {
16741676
llvm::Expected<llvm::remarks::Format> formatOrErr =
16751677
llvm::remarks::parseFormat(A->getValue());

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,12 +338,40 @@ bool CrossModuleOptimization::canSerializeType(SILType type) {
338338
return success;
339339
}
340340

341+
/// Returns true if the function in \p funcCtxt could be linked statically to
342+
/// this module.
343+
static bool couldBeLinkedStatically(DeclContext *funcCtxt, SILModule &module) {
344+
if (!funcCtxt)
345+
return true;
346+
ModuleDecl *funcModule = funcCtxt->getParentModule();
347+
// If the function is in the same module, it's not in another module which
348+
// could be linked statically.
349+
if (module.getSwiftModule() == funcModule)
350+
return false;
351+
352+
// The stdlib module is always linked dynamically.
353+
if (funcModule == module.getASTContext().getStdlibModule())
354+
return false;
355+
356+
// Conservatively assume the function is in a statically linked module.
357+
return true;
358+
}
359+
341360
/// Returns true if the function \p func can be used from a serialized function.
342361
bool CrossModuleOptimization::canUseFromInline(SILFunction *function) {
343-
if (DeclContext *funcCtxt = function->getDeclContext()) {
344-
if (!M.getSwiftModule()->canBeUsedForCrossModuleOptimization(funcCtxt))
345-
return false;
346-
}
362+
DeclContext *funcCtxt = function->getDeclContext();
363+
if (funcCtxt && !M.getSwiftModule()->canBeUsedForCrossModuleOptimization(funcCtxt))
364+
return false;
365+
366+
/// If we are emitting a TBD file, the TBD file only contains public symbols
367+
/// of this module. But not public symbols of imported modules which are
368+
/// statically linked to the current binary.
369+
/// This prevents referencing public symbols from other modules which could
370+
/// (potentially) linked statically. Unfortunately there is no way to find out
371+
/// if another module is linked statically or dynamically, so we have to be
372+
/// conservative here.
373+
if (conservative && M.getOptions().emitTBD && couldBeLinkedStatically(funcCtxt, M))
374+
return false;
347375

348376
switch (function->getLinkage()) {
349377
case SILLinkage::PublicNonABI:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import Submodule
3+
4+
public func incrementByThree(_ x: Int) -> Int {
5+
return incrementByOne(x) + 2
6+
}
7+
8+
public func incrementByThreeWithCall(_ x: Int) -> Int {
9+
return incrementByOneNoCMO(x) + 2
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
public func incrementByOne(_ x: Int) -> Int {
3+
return x + 1
4+
}
5+
6+
@_semantics("optimize.no.crossmodule")
7+
public func incrementByOneNoCMO(_ x: Int) -> Int {
8+
return x + 1
9+
}
10+

test/SILOptimizer/default-cmo.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
// RUN: %empty-directory(%t)
3+
4+
// RUN: %target-build-swift -O -wmo -parse-as-library -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule %S/Inputs/cross-module/default-submodule.swift -c -o %t/submodule.o
5+
// RUN: %target-build-swift -O -wmo -parse-as-library -emit-module -emit-module-path=%t/Module.swiftmodule -module-name=Module -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/module.o
6+
// RUN: %target-build-swift -O -wmo -parse-as-library -emit-tbd -emit-tbd-path %t/ModuleTBD.tbd -emit-module -emit-module-path=%t/ModuleTBD.swiftmodule -module-name=ModuleTBD -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/moduletbd.o
7+
8+
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %s -emit-sil | %FileCheck %s
9+
10+
11+
import Module
12+
import ModuleTBD
13+
14+
// CHECK-LABEL: sil @$s4Main11doIncrementyS2iF
15+
// CHECK-NOT: function_ref
16+
// CHECK-NOT: apply
17+
// CHECK: } // end sil function '$s4Main11doIncrementyS2iF'
18+
public func doIncrement(_ x: Int) -> Int {
19+
return Module.incrementByThree(x)
20+
}
21+
22+
// CHECK-LABEL: sil @$s4Main19doIncrementWithCallyS2iF
23+
// CHECK: function_ref @$s9Submodule19incrementByOneNoCMOyS2iF
24+
// CHECK: } // end sil function '$s4Main19doIncrementWithCallyS2iF'
25+
public func doIncrementWithCall(_ x: Int) -> Int {
26+
return Module.incrementByThreeWithCall(x)
27+
}
28+
29+
// CHECK-LABEL: sil @$s4Main14doIncrementTBDyS2iF
30+
// CHECK-NOT: function_ref
31+
// CHECK-NOT: apply
32+
// CHECK: } // end sil function '$s4Main14doIncrementTBDyS2iF'
33+
public func doIncrementTBD(_ x: Int) -> Int {
34+
return ModuleTBD.incrementByThree(x)
35+
}
36+
37+
// CHECK-LABEL: sil @$s4Main22doIncrementTBDWithCallyS2iF
38+
// CHECK: function_ref @$s9ModuleTBD24incrementByThreeWithCallyS2iF
39+
// CHECK: } // end sil function '$s4Main22doIncrementTBDWithCallyS2iF'
40+
public func doIncrementTBDWithCall(_ x: Int) -> Int {
41+
return ModuleTBD.incrementByThreeWithCall(x)
42+
}
43+

0 commit comments

Comments
 (0)