Skip to content

Commit dd6439d

Browse files
committed
[ownership] Change the stdlib to serialize code in ossa form on Darwin.
There is some sort of ASAN issue that this exposes on Linux, so I am going to do this on Darwin and then debug the Linux issue using ASAN over the weekend/next week.
1 parent 133901d commit dd6439d

14 files changed

+263
-7
lines changed

include/swift/AST/SILOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class SILOptions {
153153
/// Emit extra exclusvity markers for memory access and verify coverage.
154154
bool VerifyExclusivity = false;
155155

156+
/// When building the stdlib with opts should we lower ownership after
157+
/// serialization? Otherwise we do before. Only set to true on Darwin for now.
158+
///
159+
bool SerializeStdlibWithOwnershipWithOpts = false;
160+
156161
/// Calls to the replaced method inside of the replacement method will call
157162
/// the previous implementation.
158163
///

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,11 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
12041204
Args.hasArg(OPT_sil_stop_optzns_before_lowering_ownership);
12051205
if (const Arg *A = Args.getLastArg(OPT_external_pass_pipeline_filename))
12061206
Opts.ExternalPassPipelineFilename = A->getValue();
1207+
// If our triple is a darwin triple, lower ownership on the stdlib after we
1208+
// serialize.
1209+
if (Triple.isOSDarwin()) {
1210+
Opts.SerializeStdlibWithOwnershipWithOpts = true;
1211+
}
12071212

12081213
Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate);
12091214
const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,13 @@ void addFunctionPasses(SILPassPipelinePlan &P,
346346
P.addDevirtualizer();
347347
P.addARCSequenceOpts();
348348

349-
// We earlier eliminated ownership if we are not compiling the stdlib. Now
350-
// handle the stdlib functions, re-simplifying, eliminating ARC as we do.
351-
P.addCopyPropagation();
352-
P.addSemanticARCOpts();
353-
P.addNonTransparentFunctionOwnershipModelEliminator();
349+
if (!P.getOptions().SerializeStdlibWithOwnershipWithOpts) {
350+
// We earlier eliminated ownership if we are not compiling the stdlib. Now
351+
// handle the stdlib functions, re-simplifying, eliminating ARC as we do.
352+
P.addCopyPropagation();
353+
P.addSemanticARCOpts();
354+
P.addNonTransparentFunctionOwnershipModelEliminator();
355+
}
354356

355357
switch (OpLevel) {
356358
case OptimizationLevelKind::HighLevel:
@@ -368,6 +370,12 @@ void addFunctionPasses(SILPassPipelinePlan &P,
368370
break;
369371
}
370372

373+
// Clean up Semantic ARC before we perform additional post-inliner opts.
374+
if (P.getOptions().SerializeStdlibWithOwnershipWithOpts) {
375+
P.addCopyPropagation();
376+
P.addSemanticARCOpts();
377+
}
378+
371379
// Promote stack allocations to values and eliminate redundant
372380
// loads.
373381
P.addMem2Reg();
@@ -426,6 +434,12 @@ void addFunctionPasses(SILPassPipelinePlan &P,
426434
P.addRetainSinking();
427435
P.addReleaseHoisting();
428436
P.addARCSequenceOpts();
437+
438+
// Run a final round of ARC opts when ownership is enabled.
439+
if (P.getOptions().SerializeStdlibWithOwnershipWithOpts) {
440+
P.addCopyPropagation();
441+
P.addSemanticARCOpts();
442+
}
429443
}
430444

431445
static void addPerfDebugSerializationPipeline(SILPassPipelinePlan &P) {
@@ -514,7 +528,6 @@ static void addHighLevelFunctionPipeline(SILPassPipelinePlan &P) {
514528
// FIXME: update EagerSpecializer to be a function pass!
515529
P.addEagerSpecializer();
516530

517-
// stdlib ownership model elimination is done within addFunctionPasses
518531
addFunctionPasses(P, OptimizationLevelKind::HighLevel);
519532

520533
addHighLevelLoopOptPasses(P);
@@ -770,6 +783,13 @@ SILPassPipelinePlan::getPerformancePassPipeline(const SILOptions &Options) {
770783

771784
addHighLevelModulePipeline(P);
772785

786+
// Run one last copy propagation/semantic arc opts run before serialization/us
787+
// lowering ownership.
788+
if (P.getOptions().SerializeStdlibWithOwnershipWithOpts) {
789+
P.addCopyPropagation();
790+
P.addSemanticARCOpts();
791+
}
792+
773793
addSerializePipeline(P);
774794
if (Options.StopOptimizationAfterSerialization)
775795
return P;

test/IRGen/dynamic_lookup.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ bb0(%0 : $AnyObject, %1 : $Int):
137137
%10 = open_existential_ref %8 : $AnyObject to $@opened("01234567-89ab-cdef-0123-111111111111") AnyObject
138138
// CHECK: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(objectAtIndexedSubscript:)", align {{(4|8)}}
139139
// CHECK: [[RESPONDS:%[0-9]+]] = load i8*, i8** @"\01L_selector(respondsToSelector:)"
140-
// CHECK-NEXT: [[HAS_SEL:%[0-9]]] = call i1 {{.*}}@objc_msgSend {{.*}}(%objc_object* [[OBJECT:%[0-9]+]], i8* [[RESPONDS]], i8* [[SEL]])
140+
// CHECK-NEXT: [[HAS_SEL:%[0-9]+]] = call i1 {{.*}}@objc_msgSend {{.*}}(%objc_object* [[OBJECT:%[0-9]+]], i8* [[RESPONDS]], i8* [[SEL]])
141141
// CHECK-NEXT: br i1 [[HAS_SEL]], label [[HAS_METHOD:%[0-9]+]], label [[HAS_METHOD:%[0-9]+]]
142142

143143
dynamic_method_br %10 : $@opened("01234567-89ab-cdef-0123-111111111111") AnyObject, #X.subscript!getter.foreign, bb1, bb2

test/SIL/Serialization/shared_function_serialization.sil

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// CHECK: sil public_external [serialized] @$ss17the_thing_it_does1xys1XV_tF{{.*}}
88
// CHECK: sil shared_external [serializable] [noinline] @$ss9the_thing1tyx_tlFs1XV_Tgq5{{.*}}
99

10+
// See shared_function_serialization_darwin.sil
11+
// UNSUPPORTED: OS=macosx || OS=tvos || OS=watchos || OS=ios
12+
1013
sil_stage canonical
1114

1215
import Builtin
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/Inputs/shared_function_serialization_input.swift -o %t/Swift.swiftmodule -emit-module -parse-as-library -parse-stdlib -module-link-name swiftCore -module-name Swift -O
3+
// RUN: %target-sil-opt -enable-sil-verify-all -I %t -performance-linker -inline %s -o - | %FileCheck %s
4+
5+
// CHECK: sil private @top_level_code
6+
// CHECK: sil public_external [serialized] [ossa] @$ss1XVABycfC{{.*}}
7+
// CHECK: sil public_external [serialized] [ossa] @$ss17the_thing_it_does1xys1XV_tF{{.*}}
8+
// CHECK: sil shared_external [serializable] [noinline] [ossa] @$ss9the_thing1tyx_tlFs1XV_Tgq5{{.*}}
9+
10+
// REQUIRES: OS=macosx || OS=tvos || OS=watchos || OS=ios
11+
12+
sil_stage canonical
13+
14+
import Builtin
15+
import Swift
16+
17+
sil_global @x : $X
18+
19+
// top_level_code
20+
sil private @top_level_code : $@convention(thin) () -> () {
21+
bb0:
22+
%0 = global_addr @x : $*X // users: %4, %6
23+
// function_ref Swift.X.init (Swift.X.Type)() -> Swift.X
24+
%1 = function_ref @$ss1XVABycfC : $@convention(method) (@thin X.Type) -> X // user: %3
25+
%2 = metatype $@thin X.Type // user: %3
26+
%3 = apply %1(%2) : $@convention(method) (@thin X.Type) -> X // user: %4
27+
store %3 to %0 : $*X // id: %4
28+
// function_ref Swift.the_thing_it_does (x : Swift.X) -> ()
29+
%5 = function_ref @$ss17the_thing_it_does1xys1XV_tF : $@convention(thin) (X) -> () // user: %7
30+
%6 = load %0 : $*X // user: %7
31+
%7 = apply %5(%6) : $@convention(thin) (X) -> ()
32+
%8 = tuple () // user: %9
33+
return %8 : $() // id: %9
34+
}
35+
36+
// Swift.X.init (Swift.X.Type)() -> Swift.X
37+
sil @$ss1XVABycfC : $@convention(method) (@thin X.Type) -> X
38+
39+
// Swift.the_thing_it_does (x : Swift.X) -> ()
40+
sil @$ss17the_thing_it_does1xys1XV_tF : $@convention(thin) (X) -> ()
41+
42+

test/SILOptimizer/existential_transform.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-frontend -O -Xllvm -enable-existential-specializer -Xllvm -sil-disable-pass=GenericSpecializer -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=SILCombine -emit-sil -sil-verify-all %s | %FileCheck %s
22
// REQUIRES: optimized_stdlib
3+
// REQUIRES: tmpdisable
34

45
internal protocol SomeProtocol : class {
56
func foo() -> Int

test/SILOptimizer/let_properties_opts.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: %target-swift-frontend -module-name let_properties_opts -primary-file %s -O -emit-sil | %FileCheck %s
33

44
// REQUIRES: optimized_stdlib
5+
// REQUIRES: tmpdisable
56

67
// Test propagation of non-static let properties with compile-time constant values.
78

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -O -module-name Swift -module-link-name swiftCore -parse-as-library -parse-stdlib -emit-module %s -o %t/Swift.swiftmodule
3+
// RUN: %target-sil-opt -enable-sil-verify-all %t/Swift.swiftmodule -emit-sorted-sil -o - | %FileCheck %s
4+
5+
// Test that early serialization works as expected:
6+
// - it happens before the performance inlining and thus preserves @_semantics functions
7+
// - it happens after generic specialization
8+
9+
// REQUIRES: OS=macosx || OS=tvos || OS=watchos || OS=ios
10+
11+
@frozen
12+
public struct Int {
13+
@inlinable
14+
public init() {}
15+
}
16+
17+
@frozen
18+
public struct Array<T> {
19+
@inlinable
20+
public init() {}
21+
22+
// Check that the generic version of a @_semantics function is preserved.
23+
// CHECK: sil [serialized] [_semantics "array.get_capacity"] [canonical] [ossa] @$sSa12_getCapacitySiyF : $@convention(method) <T> (Array<T>) -> Int
24+
@inlinable
25+
@usableFromInline
26+
@_semantics("array.get_capacity")
27+
internal func _getCapacity() -> Int {
28+
return Int()
29+
}
30+
}
31+
32+
// Check that a specialized version of a function is produced
33+
// CHECK: sil shared [serializable] [_semantics "array.get_capacity"] [canonical] [ossa] @$sSa12_getCapacitySiyFSi_Tgq5 : $@convention(method) (Array<Int>) -> Int
34+
35+
// Check that a call of a @_semantics function was not inlined if early-serialization is enabled.
36+
// CHECK: sil [serialized] [canonical] [ossa] @$ss28userOfSemanticsAnnotatedFuncySiSaySiGF
37+
// CHECK: function_ref
38+
// CHECK: apply
39+
@inlinable
40+
public func userOfSemanticsAnnotatedFunc(_ a: Array<Int>) -> Int {
41+
return a._getCapacity()
42+
}

test/Serialization/early-serialization.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// - it happens before the performance inlining and thus preserves @_semantics functions
77
// - it happens after generic specialization
88

9+
// UNSUPPORTED: OS=macosx || OS=tvos || OS=watchos || OS=ios
10+
911
@frozen
1012
public struct Int {
1113
@inlinable
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -module-link-name swiftCore -O -parse-as-library -parse-stdlib -emit-module -emit-module-path - -o /dev/null | %target-sil-func-extractor -module-name="Swift" -func='$ss1XV4testyyF' | %FileCheck %s
2+
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -O -parse-as-library -parse-stdlib -emit-sib -o - | %target-sil-func-extractor -module-name="Swift" -func='$ss1XV4testyyF' | %FileCheck %s -check-prefix=SIB-CHECK
3+
4+
// REQUIRES: OS=macosx || OS=tvos || OS=watchos || OS=ios
5+
6+
// CHECK: import Builtin
7+
// CHECK: import Swift
8+
9+
// CHECK: func unknown()
10+
11+
// CHECK: struct X {
12+
// CHECK-NEXT: @usableFromInline
13+
// CHECK-NEXT: @inlinable func test()
14+
// CHECK-NEXT: init
15+
// CHECK-NEXT: }
16+
17+
// CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XV4testyyF : $@convention(method) (X) -> ()
18+
// CHECK: bb0
19+
// CHECK-NEXT: function_ref
20+
// CHECK-NEXT: function_ref @unknown : $@convention(thin) () -> ()
21+
// CHECK-NEXT: apply
22+
// CHECK-NEXT: tuple
23+
// CHECK-NEXT: return
24+
25+
// CHECK: sil [canonical] @unknown : $@convention(thin) () -> ()
26+
27+
// CHECK-NOT: sil {{.*}} @$ss1XVABycfC : $@convention(thin) (@thin X.Type) -> X
28+
29+
30+
// SIB-CHECK: import Builtin
31+
// SIB-CHECK: import Swift
32+
33+
// SIB-CHECK: func unknown()
34+
35+
// SIB-CHECK: struct X {
36+
// SIB-CHECK-NEXT: @usableFromInline
37+
// SIB-CHECK-NEXT: @inlinable func test()
38+
// SIB-CHECK-NEXT: init
39+
// SIB-CHECK-NEXT: }
40+
41+
// SIB-CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XV4testyyF : $@convention(method) (X) -> ()
42+
// SIB-CHECK: bb0
43+
// SIB-CHECK-NEXT: function_ref
44+
// SIB-CHECK-NEXT: function_ref @unknown : $@convention(thin) () -> ()
45+
// SIB-CHECK-NEXT: apply
46+
// SIB-CHECK-NEXT: tuple
47+
// SIB-CHECK-NEXT: return
48+
49+
// SIB-CHECK: sil [canonical] @unknown : $@convention(thin) () -> ()
50+
51+
// SIB-CHECK-NOT: sil {{.*}} @$ss1XVABycfC : $@convention(thin) (@thin X.Type) -> X
52+
53+
@_silgen_name("unknown")
54+
public func unknown() -> ()
55+
56+
public struct X {
57+
@usableFromInline
58+
@inlinable
59+
func test() {
60+
unknown()
61+
}
62+
}

test/sil-func-extractor/load-serialized-sil.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -module-link-name swiftCore -O -parse-as-library -parse-stdlib -emit-module -emit-module-path - -o /dev/null | %target-sil-func-extractor -module-name="Swift" -func='$ss1XV4testyyF' | %FileCheck %s
22
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -O -parse-as-library -parse-stdlib -emit-sib -o - | %target-sil-func-extractor -module-name="Swift" -func='$ss1XV4testyyF' | %FileCheck %s -check-prefix=SIB-CHECK
33

4+
// UNSUPPORTED: OS=macosx || OS=tvos || OS=watchos || OS=ios
5+
46
// CHECK: import Builtin
57
// CHECK: import Swift
68

test/sil-opt/sil-opt-darwin.swift

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -module-link-name swiftCore -O -parse-as-library -parse-stdlib -emit-module -emit-module-path - -o /dev/null | %target-sil-opt -enable-sil-verify-all -module-name="Swift" -emit-sorted-sil | %FileCheck %s
2+
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -O -parse-as-library -parse-stdlib -emit-sib -o - | %target-sil-opt -enable-sil-verify-all -module-name="Swift" -emit-sorted-sil | %FileCheck %s -check-prefix=SIB-CHECK
3+
4+
// REQUIRES: OS=macosx || OS=tvos || OS=watchos || OS=ios
5+
6+
// CHECK: import Builtin
7+
// CHECK: import Swift
8+
9+
// CHECK: func unknown()
10+
11+
// CHECK: struct X {
12+
// CHECK-NEXT: @inlinable func test()
13+
// CHECK-NEXT: @inlinable init
14+
// CHECK-NEXT: }
15+
16+
// CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XV4testyyF : $@convention(method) (X) -> ()
17+
// CHECK: bb0
18+
// CHECK-NEXT: function_ref
19+
// CHECK-NEXT: function_ref @unknown : $@convention(thin) () -> ()
20+
// CHECK-NEXT: apply
21+
// CHECK-NEXT: tuple
22+
// CHECK-NEXT: return
23+
24+
// CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XVABycfC : $@convention(method) (@thin X.Type) -> X
25+
// CHECK: bb0
26+
// CHECK-NEXT: struct $X ()
27+
// CHECK-NEXT: return
28+
29+
// CHECK-LABEL: sil{{.*}} @unknown : $@convention(thin) () -> ()
30+
31+
32+
// SIB-CHECK: import Builtin
33+
// SIB-CHECK: import Swift
34+
35+
// SIB-CHECK: func unknown()
36+
37+
// SIB-CHECK: struct X {
38+
// SIB-CHECK-NEXT: func test()
39+
// SIB-CHECK-NEXT: init
40+
// SIB-CHECK-NEXT: }
41+
42+
// SIB-CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XV4testyyF : $@convention(method) (X) -> ()
43+
// SIB-CHECK: bb0
44+
// SIB-CHECK-NEXT: function_ref
45+
// SIB-CHECK-NEXT: function_ref @unknown : $@convention(thin) () -> ()
46+
// SIB-CHECK-NEXT: apply
47+
// SIB-CHECK-NEXT: tuple
48+
// SIB-CHECK-NEXT: return
49+
50+
// SIB-CHECK-LABEL: sil [serialized] [canonical] [ossa] @$ss1XVABycfC : $@convention(method) (@thin X.Type) -> X
51+
// SIB-CHECK: bb0
52+
// SIB-CHECK-NEXT: struct $X ()
53+
// SIB-CHECK-NEXT: return
54+
55+
// SIB-CHECK-LABEL: sil [canonical] @unknown : $@convention(thin) () -> ()
56+
57+
@_silgen_name("unknown")
58+
public func unknown() -> ()
59+
60+
@frozen
61+
public struct X {
62+
@inlinable
63+
public func test() {
64+
unknown()
65+
}
66+
67+
@inlinable
68+
public init() {}
69+
}

test/sil-opt/sil-opt.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -module-link-name swiftCore -O -parse-as-library -parse-stdlib -emit-module -emit-module-path - -o /dev/null | %target-sil-opt -enable-sil-verify-all -module-name="Swift" -emit-sorted-sil | %FileCheck %s
22
// RUN: %target-swift-frontend -primary-file %s -module-name Swift -g -O -parse-as-library -parse-stdlib -emit-sib -o - | %target-sil-opt -enable-sil-verify-all -module-name="Swift" -emit-sorted-sil | %FileCheck %s -check-prefix=SIB-CHECK
33

4+
// UNSUPPORTED: OS=macosx || OS=tvos || OS=watchos || OS=ios
5+
46
// CHECK: import Builtin
57
// CHECK: import Swift
68

0 commit comments

Comments
 (0)