Skip to content

Commit 17e84c2

Browse files
authored
Merge pull request #36795 from slavapestov/lazily-emit-alwaysEmitIntoClient
Lazily emit @_alwaysEmitIntoClient functions at -Onone
2 parents 82c190a + 1e8ce52 commit 17e84c2

36 files changed

+300
-254
lines changed

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,7 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
31503150
case OpaqueSubstitutionKind::SubstituteNonResilientModule:
31513151
// Can't access types that are not public from a different module.
31523152
if (dc->getParentModule() == typeDecl->getDeclContext()->getParentModule())
3153-
return true;
3153+
return typeDecl->getEffectiveAccess() > AccessLevel::FilePrivate;
31543154

31553155
return typeDecl->getEffectiveAccess() > AccessLevel::Internal;
31563156
}

lib/IRGen/GenDecl.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,22 @@ static bool hasCodeCoverageInstrumentation(SILFunction &f, SILModule &m) {
10511051
return f.getProfiler() && m.getOptions().EmitProfileCoverageMapping;
10521052
}
10531053

1054+
// Eagerly emit functions that are externally visible. Functions with code
1055+
// coverage instrumentation must also be eagerly emitted. So must functions
1056+
// that are a dynamic replacement for another.
1057+
static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
1058+
if (f.isPossiblyUsedExternally())
1059+
return false;
1060+
1061+
if (f.getDynamicallyReplacedFunction())
1062+
return false;
1063+
1064+
if (hasCodeCoverageInstrumentation(f, m))
1065+
return false;
1066+
1067+
return true;
1068+
}
1069+
10541070
void IRGenerator::emitGlobalTopLevel(
10551071
const std::vector<std::string> &linkerDirectives) {
10561072
// Generate order numbers for the functions in the SIL module that
@@ -1082,13 +1098,9 @@ void IRGenerator::emitGlobalTopLevel(
10821098
}
10831099

10841100
// Emit SIL functions.
1085-
for (SILFunction &f : PrimaryIGM->getSILModule()) {
1086-
// Eagerly emit functions that are externally visible. Functions with code
1087-
// coverage instrumentation must also be eagerly emitted. So must functions
1088-
// that are a dynamic replacement for another.
1089-
if (!f.isPossiblyUsedExternally() &&
1090-
!f.getDynamicallyReplacedFunction() &&
1091-
!hasCodeCoverageInstrumentation(f, PrimaryIGM->getSILModule()))
1101+
auto &m = PrimaryIGM->getSILModule();
1102+
for (SILFunction &f : m) {
1103+
if (isLazilyEmittedFunction(f, m))
10921104
continue;
10931105

10941106
CurrentIGMPtr IGM = getGenModule(&f);
@@ -2937,8 +2949,8 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
29372949
}
29382950

29392951
// Otherwise, if we have a lazy definition for it, be sure to queue that up.
2940-
} else if (isDefinition && !forDefinition && !f->isPossiblyUsedExternally() &&
2941-
!hasCodeCoverageInstrumentation(*f, getSILModule())) {
2952+
} else if (isDefinition && !forDefinition &&
2953+
isLazilyEmittedFunction(*f, getSILModule())) {
29422954
IRGen.addLazyFunction(f);
29432955
}
29442956

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -451,21 +451,9 @@ class SerializeSILPass : public SILModuleTransform {
451451
!M.getOptions().CrossModuleOptimization)
452452
return;
453453

454-
// Mark all reachable functions as "anchors" so that they are not
455-
// removed later by the dead function elimination pass. This
456-
// is required, because clients may reference any of the
457-
// serialized functions or anything referenced from them. Therefore,
458-
// to avoid linker errors, the object file of the current module should
459-
// contain all the symbols which were alive at the time of serialization.
460454
LLVM_DEBUG(llvm::dbgs() << "Serializing SILModule in SerializeSILPass\n");
461455
M.serialize();
462456

463-
// If we are not optimizing, do not strip the [serialized] flag. We *could*
464-
// do this since after serializing [serialized] is irrelevent. But this
465-
// would incur an unnecessary compile time cost since if we are not
466-
// optimizing we are not going to perform any sort of DFE.
467-
if (!getOptions().shouldOptimize())
468-
return;
469457
removeSerializedFlagFromAllFunctions(M);
470458
}
471459
};

test/AutoDiff/SILOptimizer/differentiation_subset_parameters_thunk.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func genericInoutIndirectCaller<T: Differentiable, U: Differentiable>(
8181
return inoutIndirectCaller(x, y, z)
8282
}
8383

84-
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$sSdSfSdSfIegnrrr_TJSpSSSpSrSUSP : $@convention(thin) (@in_guaranteed Double, @guaranteed @callee_guaranteed (@in_guaranteed Double) -> (@out Float, @out Double, @out Float)) -> (@out Float, @out Float) {
84+
// CHECK-LABEL: sil shared [transparent] [thunk] @$sSdSfSdSfIegnrrr_TJSpSSSpSrSUSP : $@convention(thin) (@in_guaranteed Double, @guaranteed @callee_guaranteed (@in_guaranteed Double) -> (@out Float, @out Double, @out Float)) -> (@out Float, @out Float) {
8585
// CHECK: bb0(%0 : $*Float, %1 : $*Float, %2 : $*Double, %3 : $@callee_guaranteed (@in_guaranteed Double) -> (@out Float, @out Double, @out Float)):
8686
// CHECK: %4 = alloc_stack $Double
8787
// CHECK: %5 = apply %3(%0, %4, %1, %2) : $@callee_guaranteed (@in_guaranteed Double) -> (@out Float, @out Double, @out Float)
@@ -91,7 +91,7 @@ func genericInoutIndirectCaller<T: Differentiable, U: Differentiable>(
9191
// CHECK: return %8 : $()
9292
// CHECK: }
9393

94-
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$s13TangentVector16_Differentiation14DifferentiablePQy_AaDQzAaDQy0_Ieglrr_TJSpSSSpSrSSUP : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Differentiable, τ_0_1 : Differentiable, τ_0_2 : Differentiable> (@inout τ_0_1.TangentVector, @guaranteed @callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)) -> @out τ_0_0.TangentVector {
94+
// CHECK-LABEL: sil shared [transparent] [thunk] @$s13TangentVector16_Differentiation14DifferentiablePQy_AaDQzAaDQy0_Ieglrr_TJSpSSSpSrSSUP : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Differentiable, τ_0_1 : Differentiable, τ_0_2 : Differentiable> (@inout τ_0_1.TangentVector, @guaranteed @callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)) -> @out τ_0_0.TangentVector {
9595
// CHECK: bb0(%0 : $*τ_0_0.TangentVector, %1 : $*τ_0_1.TangentVector, %2 : $@callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)):
9696
// CHECK: %3 = alloc_stack $τ_0_2.TangentVector
9797
// CHECK: %4 = apply %2(%0, %3, %1) : $@callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)
@@ -101,7 +101,7 @@ func genericInoutIndirectCaller<T: Differentiable, U: Differentiable>(
101101
// CHECK: return %7 : $()
102102
// CHECK: }
103103

104-
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$s13TangentVector16_Differentiation14DifferentiablePQy_AaDQzAaDQy0_Ieglrr_TJSpSSSpSrUSUP : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Differentiable, τ_0_1 : Differentiable, τ_0_2 : Differentiable> (@inout τ_0_1.TangentVector, @guaranteed @callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)) -> () {
104+
// CHECK-LABEL: sil shared [transparent] [thunk] @$s13TangentVector16_Differentiation14DifferentiablePQy_AaDQzAaDQy0_Ieglrr_TJSpSSSpSrUSUP : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Differentiable, τ_0_1 : Differentiable, τ_0_2 : Differentiable> (@inout τ_0_1.TangentVector, @guaranteed @callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)) -> () {
105105
// CHECK: bb0(%0 : $*τ_0_1.TangentVector, %1 : $@callee_guaranteed (@inout τ_0_1.TangentVector) -> (@out τ_0_0.TangentVector, @out τ_0_2.TangentVector)):
106106
// CHECK: %2 = alloc_stack $τ_0_0.TangentVector
107107
// CHECK: %3 = alloc_stack $τ_0_2.TangentVector

test/ClangImporter/const_and_pure.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ func testit() {
88
normal_function()
99
}
1010

11-
// CHECK: sil [serializable] [readnone] [clang const_function] @const_function : $@convention(c) () -> ()
12-
// CHECK: sil [serializable] [readonly] [clang pure_function] @pure_function : $@convention(c) () -> ()
13-
// CHECK: sil [serializable] [clang normal_function] @normal_function : $@convention(c) () -> ()
11+
// CHECK: sil [readnone] [clang const_function] @const_function : $@convention(c) () -> ()
12+
// CHECK: sil [readonly] [clang pure_function] @pure_function : $@convention(c) () -> ()
13+
// CHECK: sil [clang normal_function] @normal_function : $@convention(c) () -> ()
1414

1515

test/ClangImporter/enum-error.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,30 +45,30 @@ func testError() {
4545
} catch {}
4646

4747
#elseif ASQEXPR
48-
// ASQEXPR: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
48+
// ASQEXPR: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
4949
let wasTestError = testErrorNSError as? TestError; wasTestError
5050

5151
#elseif ASBANGEXPR
52-
// ASBANGEXPR: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
52+
// ASBANGEXPR: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
5353
let terr2 = testErrorNSError as! TestError; terr2
5454

5555
#elseif ISEXPR
56-
// ISEXPR: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
56+
// ISEXPR: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
5757
if (testErrorNSError is TestError) {
5858
print("true")
5959
} else {
6060
print("false")
6161
}
6262

6363
#elseif CATCHIS
64-
// CATCHIS: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
64+
// CATCHIS: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
6565
do {
6666
throw TestError(.TETwo)
6767
} catch is TestError {
6868
} catch {}
6969

7070
#elseif CATCHAS
71-
// CATCHAS: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
71+
// CATCHAS: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
7272
do {
7373
throw TestError(.TETwo)
7474
} catch let err as TestError {
@@ -83,8 +83,8 @@ func testError() {
8383
let _ : TestError = dyncast(testErrorNSError)
8484

8585
#elseif EXHAUSTIVE
86-
// CHECK: sil_witness_table shared [serialized] TestError: _BridgedStoredNSError module __ObjC
87-
// CHECK: sil_witness_table shared [serialized] ExhaustiveError: _BridgedStoredNSError module __ObjC
86+
// CHECK: sil_witness_table shared TestError: _BridgedStoredNSError module __ObjC
87+
// CHECK: sil_witness_table shared ExhaustiveError: _BridgedStoredNSError module __ObjC
8888
let terr = getErr()
8989
switch (terr) { case .TENone, .TEOne, .TETwo: break }
9090
// EXHAUSTIVE: [[@LINE-1]]:{{.+}}: warning: switch covers known cases, but 'TestError.Code' may have additional unknown values

test/ClangImporter/static_inline.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// RUN: %FileCheck < %t/static_inline.sil %s
77
// RUN: %target-swift-frontend -parse-as-library -module-name=static_inline -O -emit-ir %t/static_inline.sil -enable-objc-interop -import-objc-header %S/Inputs/static_inline.h | %FileCheck --check-prefix=CHECK-IR %s
88

9-
// CHECK: sil shared [serializable] [clang c_inline_func] @c_inline_func : $@convention(c) (Int32) -> Int32
9+
// CHECK: sil shared [clang c_inline_func] @c_inline_func : $@convention(c) (Int32) -> Int32
1010

1111
// CHECK-IR-LABEL: define{{.*}} i32 @"$s13static_inline6testit1xs5Int32VAE_tF"(i32 %0)
1212
// CHECK-IR: = add {{.*}}, 27

test/IRGen/alwaysEmitIntoClient.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -O | %FileCheck %s --check-prefix=OPTIMIZED
2+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
3+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix=NEGATIVE
4+
// RUN: %target-swift-frontend -emit-ir -primary-file %s | %FileCheck %s --check-prefix=PRIMARY
5+
6+
// Make sure that @_alwaysEmitIntoClient functions are lazily
7+
// emitted in WMO builds.
8+
9+
// Both functions are eliminated in optimized builds; the first is inlined
10+
// into the caller, and the second is eliminated since it was never called.
11+
12+
// OPTIMIZED-NOT: define weak_odr hidden swiftcc void @"$s20alwaysEmitIntoClient18referencedFunctionyyF"() {{.*}} {
13+
// OPTIMIZED-NOT: define weak_odr hidden swiftcc void @"$s20alwaysEmitIntoClient20unreferencedFunctionyyF"() {{.*}} {
14+
15+
// The unreferenced function should be eliminated in an unoptimized WMO
16+
// build too, since it was never referenced from inside the module.
17+
18+
// CHECK-LABEL: define linkonce_odr hidden swiftcc void @"$s20alwaysEmitIntoClient18referencedFunctionyyF"() {{.*}} {
19+
// NEGATIVE-NOT: define linkonce_odr hidden swiftcc void @"$s20alwaysEmitIntoClient20unreferencedFunctionyyF"() {{.*}} {
20+
21+
// In non-WMO mode, both functions must be emitted since they could be
22+
// referenced from other translation units.
23+
24+
// PRIMARY-LABEL: define weak_odr hidden swiftcc void @"$s20alwaysEmitIntoClient18referencedFunctionyyF"() {{.*}} {
25+
// PRIMARY-LABEL: define weak_odr hidden swiftcc void @"$s20alwaysEmitIntoClient20unreferencedFunctionyyF"() {{.*}} {
26+
27+
@_alwaysEmitIntoClient public func referencedFunction() {}
28+
@_alwaysEmitIntoClient public func unreferencedFunction() {}
29+
30+
public func referencesFunction() {
31+
referencedFunction()
32+
}

test/IRGen/opaque_result_type_debug.swift

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,30 @@
1-
// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -g -emit-ir -enable-anonymous-context-mangled-names %s | %FileCheck %s
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -emit-module -emit-module-path %t/opaque_result_type_debug_other.swiftmodule -module-name opaque_result_type_debug_other -enable-anonymous-context-mangled-names %s -DLIBRARY
3+
// RUN: %target-swift-frontend -disable-availability-checking -g -emit-ir -enable-anonymous-context-mangled-names %s -DCLIENT -I %t | %FileCheck %s
4+
5+
#if LIBRARY
26

37
public protocol P {}
48
extension Int: P {}
59

6-
// CHECK: [[DEFINER_NAME:@.*]] = {{.*}}constant [{{[0-9]+}} x i8] c"$s24opaque_result_type_debug3fooQryF\00"
7-
// CHECK: @"$s24opaque_result_type_debug3fooQryFMXX" = {{.*}}constant{{.*}} [[DEFINER_NAME]]
8-
// CHECK: @"$s24opaque_result_type_debug3fooQryFQOMQ" = {{.*}}constant{{.*}} @"$s24opaque_result_type_debug3fooQryFMXX"
9-
1010
public func foo() -> some P {
1111
return 0
1212
}
1313

14-
// CHECK: [[DEFINER_NAME:@.*]] = {{.*}}constant [{{[0-9]+}} x i8] c"$s24opaque_result_type_debug4propQrvp\00"
15-
// CHECK: @"$s24opaque_result_type_debug4propQrvpMXX" = {{.*}}constant{{.*}} [[DEFINER_NAME]]
16-
// CHECK: @"$s24opaque_result_type_debug4propQrvpQOMQ" = {{.*}}constant{{.*}} @"$s24opaque_result_type_debug4propQrvpMXX"
17-
1814
public var prop: some P {
1915
return 0
2016
}
2117

22-
// CHECK: [[DEFINER_NAME:@.*]] = {{.*}}constant [{{[0-9]+}} x i8] c"$s24opaque_result_type_debug3FooVQrycip\00"
23-
// CHECK: @"$s24opaque_result_type_debug3FooVQrycipMXX" = {{.*}}constant{{.*}} [[DEFINER_NAME]]
24-
// CHECK: @"$s24opaque_result_type_debug3FooVQrycipQOMQ" = {{.*}}constant{{.*}} @"$s24opaque_result_type_debug3FooVQrycipMXX"
25-
2618
public struct Foo {
2719
public init() {}
2820
public subscript() -> some P {
2921
return 0
3022
}
3123
}
3224

33-
// CHECK: @"\01l_type_metadata_table" = {{.*}} @"$s24opaque_result_type_debug3fooQryFQOMQ"
25+
#else
26+
27+
import opaque_result_type_debug_other
3428

3529
@_silgen_name("use") public func use<T: P>(_: T)
3630

@@ -51,11 +45,13 @@ public func bar<T: P>(genericValue: T) {
5145
use(opaqueSubValue)
5246
}
5347

54-
// CHECK-DAG: ![[OPAQUE_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3fooQryFQOyQo_D"
48+
#endif
49+
50+
// CHECK-DAG: ![[OPAQUE_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s30opaque_result_type_debug_other3fooQryFQOyQo_D"
5551
// CHECK-DAG: ![[LET_OPAQUE_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_TYPE]])
56-
// CHECK-DAG: ![[OPAQUE_PROP_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug4propQrvpQOyQo_D"
52+
// CHECK-DAG: ![[OPAQUE_PROP_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s30opaque_result_type_debug_other4propQrvpQOyQo_D"
5753
// CHECK-DAG: ![[LET_OPAQUE_PROP_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_PROP_TYPE]])
58-
// CHECK-DAG: ![[OPAQUE_SUB_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3FooVQrycipQOy_Qo_D"
54+
// CHECK-DAG: ![[OPAQUE_SUB_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s30opaque_result_type_debug_other3FooVQrycipQOy_Qo_D"
5955
// CHECK-DAG: ![[LET_OPAQUE_SUB_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_SUB_TYPE]])
6056
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaqueValue",{{.*}} type: ![[LET_OPAQUE_TYPE]])
6157
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaquePropValue",{{.*}} type: ![[LET_OPAQUE_PROP_TYPE]])

0 commit comments

Comments
 (0)