Skip to content

Commit d23551a

Browse files
committed
Don't generate code for transparent functions.
They are mandatory inlined anyway. Therefore the binary code of transparent functions is not used in most cases. In case the address of a transparent function is taken, the main program (which deserialized the transparent function) generates code for it and treats it as shared function. This reduces the stdlib code size by 2.8%.
1 parent e69195b commit d23551a

File tree

7 files changed

+66
-3
lines changed

7 files changed

+66
-3
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,8 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
12161216
static std::pair<llvm::GlobalValue::LinkageTypes,
12171217
llvm::GlobalValue::VisibilityTypes>
12181218
getIRLinkage(IRGenModule &IGM,
1219-
SILLinkage linkage, bool isFragile, ForDefinition_t isDefinition,
1219+
SILLinkage linkage, bool isFragile, bool isSILOnly,
1220+
ForDefinition_t isDefinition,
12201221
bool isWeakImported) {
12211222

12221223
#define RESULT(LINKAGE, VISIBILITY) \
@@ -1260,6 +1261,22 @@ llvm::GlobalValue::VISIBILITY##Visibility }
12601261

12611262
switch (linkage) {
12621263
case SILLinkage::Public:
1264+
// Don't code-gen transparent functions. Internal linkage
1265+
// will enable llvm to delete transparent functions except
1266+
// they are referenced from somewhere (i.e. the function pointer
1267+
// is taken).
1268+
if (isSILOnly &&
1269+
// In case we are generating multiple LLVM modules, we still have to
1270+
// use ExternalLinkage so that modules can cross-reference transparent
1271+
// functions.
1272+
!IGM.IRGen.hasMultipleIGMs() &&
1273+
1274+
// TODO: In non-whole-module-opt the generated swiftmodules are "linked"
1275+
// and this strips all serialized transparent functions. So we have to
1276+
// code-gen transparent functions in non-whole-module-opt.
1277+
IGM.getSILModule().isWholeModule()) {
1278+
return RESULT(Internal, Default);
1279+
}
12631280
return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility};
12641281
case SILLinkage::Shared:
12651282
case SILLinkage::SharedExternal: return RESULT(LinkOnceODR, Hidden);
@@ -1273,6 +1290,10 @@ llvm::GlobalValue::VISIBILITY##Visibility }
12731290
return RESULT(Internal, Default);
12741291
case SILLinkage::PublicExternal:
12751292
if (isDefinition) {
1293+
if (isSILOnly) {
1294+
// Transparent function are not available externally.
1295+
return RESULT(LinkOnceODR, Hidden);
1296+
}
12761297
return RESULT(AvailableExternally, Default);
12771298
}
12781299

@@ -1303,6 +1324,7 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
13031324
IGM,
13041325
entity.getLinkage(IGM, ForDefinition),
13051326
entity.isFragile(IGM),
1327+
entity.isSILOnly(),
13061328
ForDefinition,
13071329
entity.isWeakImported(IGM.getSwiftModule()));
13081330
global->setLinkage(linkage.first);
@@ -1329,6 +1351,7 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
13291351
std::tie(result.Linkage, result.Visibility) =
13301352
getIRLinkage(IGM, entity.getLinkage(IGM, isDefinition),
13311353
entity.isFragile(IGM),
1354+
entity.isSILOnly(),
13321355
isDefinition,
13331356
entity.isWeakImported(IGM.getSwiftModule()));
13341357

lib/IRGen/Linking.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,17 @@ class LinkEntity {
520520
assert(getKind() == Kind::SILFunction);
521521
return reinterpret_cast<SILFunction*>(Pointer);
522522
}
523-
523+
524+
/// Returns true if this function is only serialized, but not necessarily
525+
/// code-gen'd. These are fragile transparent functions.
526+
bool isSILOnly() const {
527+
if (getKind() != Kind::SILFunction)
528+
return false;
529+
530+
SILFunction *F = getSILFunction();
531+
return F->isTransparent() && F->isDefinition() && F->isFragile();
532+
}
533+
524534
SILGlobalVariable *getSILGlobalVariable() const {
525535
assert(getKind() == Kind::SILGlobalVariable);
526536
return reinterpret_cast<SILGlobalVariable*>(Pointer);

lib/SILOptimizer/IPO/ExternalDefsToDecls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ExternalDefsToDecls : public SILModuleTransform {
2626
for (auto &F : *getModule()) {
2727
SILLinkage linkage = F.getLinkage();
2828
if (isAvailableExternally(linkage) && F.isDefinition() &&
29-
!hasSharedVisibility(linkage)) {
29+
!hasSharedVisibility(linkage) && !F.isTransparent()) {
3030
F.convertToDeclaration();
3131
invalidateAnalysis(&F, SILAnalysis::InvalidationKind::FunctionBody);
3232
}

lib/SILOptimizer/Mandatory/MandatoryInlining.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,15 @@ class MandatoryInlining : public SILModuleTransform {
464464
SetFactory, SetFactory.getEmptySet(), CHA);
465465
}
466466

467+
// Make sure that we de-serialize all transparent functions,
468+
// even if we didn't inline them for some reason.
469+
// Transparent functions are not available externally, so we
470+
// have to generate code for them.
471+
for (auto &F : *M) {
472+
if (F.isTransparent())
473+
M->linkFunction(&F, Mode);
474+
}
475+
467476
if (!ShouldCleanup)
468477
return;
469478

test/IRGen/Inputs/multithread_module/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ private struct MyStruct : MyProto {
1919
}
2020
}
2121

22+
@_transparent public func transparentfunc(_ x: Int) -> Int {
23+
return x + 3
24+
}
25+
2226
public var g1 = 234
2327

2428
let i = testit(27)

test/IRGen/multithread_module.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ func callPrivInc(_ x: Int) -> Int {
4545
return privateInc(x)
4646
}
4747

48+
// Check if we use the correct linkage for a transparent function
49+
public var transparentfuncptr = transparentfunc
50+
4851
protocol MyProto {
4952
func protofunc() -> Int
5053
}

test/IRGen/sil_linkage.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
sil_stage canonical
44

55
// CHECK: define{{( protected)?}} void @public_fragile_function_test() {{.*}} {
6+
// CHECK: define{{( protected)?}} internal void @public_transparent_fragile_function_test() {{.*}} {
7+
// CHECK: define{{( protected)?}} void @public_transparent_function_test() {{.*}} {
68
// CHECK: define{{( protected)?}} void @hidden_fragile_function_test() {{.*}} {
79
// CHECK: define linkonce_odr hidden void @shared_fragile_function_test() {{.*}} {
810
// CHECK: define{{( protected)?}} void @private_fragile_function_test() {{.*}} {
@@ -23,6 +25,16 @@ sil public [fragile] @public_fragile_function_test : $@convention(thin) () -> ()
2325
return %0 : $()
2426
}
2527

28+
sil public [transparent] [fragile] @public_transparent_fragile_function_test : $@convention(thin) () -> () {
29+
%0 = tuple()
30+
return %0 : $()
31+
}
32+
33+
sil public [transparent] @public_transparent_function_test : $@convention(thin) () -> () {
34+
%0 = tuple()
35+
return %0 : $()
36+
}
37+
2638
sil hidden [fragile] @hidden_fragile_function_test : $@convention(thin) () -> () {
2739
%0 = tuple()
2840
return %0 : $()
@@ -122,6 +134,8 @@ sil hidden_external @hidden_external_resilient_function_decl_test : $@convention
122134

123135
sil public @use_all_symbols : $@convention(thin) () -> () {
124136
%0 = function_ref @public_fragile_function_test : $@convention(thin) () -> ()
137+
%t0 = function_ref @public_transparent_fragile_function_test : $@convention(thin) () -> ()
138+
%t1 = function_ref @public_transparent_function_test : $@convention(thin) () -> ()
125139
%1 = function_ref @hidden_fragile_function_test : $@convention(thin) () -> ()
126140
%2 = function_ref @shared_fragile_function_test : $@convention(thin) () -> ()
127141
%3 = function_ref @private_fragile_function_test : $@convention(thin) () -> ()

0 commit comments

Comments
 (0)