Skip to content

Commit 4191543

Browse files
eecksteinaschwaighofer
authored andcommitted
MandatoryPerformanceOptimizations: specialize witness tables for general existentials
1 parent 1486d00 commit 4191543

File tree

2 files changed

+308
-0
lines changed

2 files changed

+308
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
143143
}
144144
}
145145

146+
case let initExAddr as InitExistentialAddrInst:
147+
if context.options.enableEmbeddedSwift {
148+
for c in initExAddr.conformances where c.isConcrete && !c.protocol.isMarkerProtocol {
149+
specializeWitnessTable(for: c, moduleContext)
150+
worklist.addWitnessMethods(of: c, moduleContext)
151+
}
152+
}
153+
146154
case let bi as BuiltinInst:
147155
switch bi.id {
148156
case .BuildOrdinaryTaskExecutorRef,
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -enable-experimental-feature EmbeddedExistentials -parse-as-library -wmo) | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -enable-experimental-feature EmbeddedExistentials -parse-as-library -wmo -O) | %FileCheck %s
3+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -enable-experimental-feature EmbeddedExistentials -parse-as-library -wmo -Osize) | %FileCheck %s
4+
5+
// REQUIRES: swift_in_compiler
6+
// REQUIRES: executable_test
7+
// REQUIRES: optimized_stdlib
8+
// REQUIRES: swift_feature_Embedded
9+
// REQUIRES: swift_feature_EmbeddedExistentials
10+
11+
protocol P {
12+
func foo()
13+
func bar()
14+
func predicate() -> Bool
15+
}
16+
17+
extension P {
18+
public func predicate() -> Bool { true }
19+
}
20+
21+
struct MyStruct : P {
22+
var i: Int
23+
24+
func foo() { print("MyStruct.foo: \(i)") }
25+
func bar() { print("MyStruct.bar: \(i)") }
26+
}
27+
28+
struct LargeStruct : P {
29+
var a: Int
30+
var b: Int
31+
var c: Int
32+
var d: Int
33+
34+
func foo() { print("LargeStruct.foo: \(a), \(b), \(c), \(d)") }
35+
func bar() { print("LargeStruct.bar: \(a), \(b), \(c), \(d)") }
36+
}
37+
38+
struct GenericStruct<T: BinaryInteger> : P {
39+
var t: T
40+
41+
func foo() { print("GenericStruct.foo: \(t)") }
42+
func bar() { print("GenericStruct.bar: \(t)") }
43+
}
44+
45+
func test(existential: any P) {
46+
existential.foo()
47+
existential.bar()
48+
}
49+
50+
/*
51+
public protocol ProtoWithAssocType<T> {
52+
associatedtype T
53+
func foo(t: T)
54+
}
55+
56+
final public class GenClass<T: BinaryInteger>: ProtoWithAssocType {
57+
public func foo(t: T) {
58+
print(t)
59+
}
60+
}
61+
62+
public func createExWithAssocType() -> any ProtoWithAssocType<Int> {
63+
return GenClass<Int>()
64+
}
65+
66+
public func callExWithAssocType(_ p: any ProtoWithAssocType<Int>) {
67+
p.foo(t: 27)
68+
}
69+
70+
public protocol Q {
71+
func bar()
72+
}
73+
74+
public protocol ProtoWithAssocConf {
75+
associatedtype A: Q
76+
func foo() -> A
77+
}
78+
79+
public class GenClass2<T>: Q {
80+
final var t: T
81+
82+
init(t : T) { self.t = t }
83+
84+
public func bar() {
85+
print("bar")
86+
}
87+
}
88+
89+
public class DerivedFromGenClass2: GenClass2<Int> {
90+
init() { super.init(t: 42) }
91+
92+
public override func bar() {
93+
print("derived-bar")
94+
}
95+
}
96+
97+
final public class GenClass3<V>: ProtoWithAssocConf {
98+
public func foo() -> GenClass2<Int> {
99+
print("foo")
100+
return GenClass2(t: 27)
101+
}
102+
}
103+
104+
final public class OtherClass: ProtoWithAssocConf {
105+
public func foo() -> GenClass2<Int> {
106+
print("other-foo")
107+
return DerivedFromGenClass2()
108+
}
109+
}
110+
111+
112+
public func createExWithAssocConf() -> any ProtoWithAssocConf {
113+
return GenClass3<Int>()
114+
}
115+
116+
public func callExWithAssocConf(_ p: any ProtoWithAssocConf) {
117+
let x = p.foo()
118+
x.bar()
119+
}
120+
121+
public class Base<T>: P {
122+
public func foo() { print("Base.foo()") }
123+
public func bar() { print("Base.bar()") }
124+
}
125+
126+
public class Derived1: Base<Int> {
127+
public override func foo() { print("Derived1.foo()") }
128+
public override func bar() { print("Derived1.bar()") }
129+
}
130+
131+
public class Derived2<T>: Base<T> {
132+
public override func foo() { print("Derived2.foo()") }
133+
public override func bar() { print("Derived2.bar()") }
134+
}
135+
136+
public func takes_p1(_ p: P1) {
137+
p.normal()
138+
}
139+
140+
public protocol P1 {
141+
func normal()
142+
}
143+
144+
public protocol P2 {
145+
func foo()
146+
}
147+
148+
public class ConditionalConformanceBase<A> {
149+
final var a: A
150+
151+
init(a: A) { self.a = a }
152+
}
153+
154+
extension ConditionalConformanceBase: P1 where A: P2 {
155+
public func normal() {
156+
a.foo()
157+
}
158+
}
159+
160+
public class ConditionalConformanceDerived<T>: ConditionalConformanceBase<T> {
161+
init(t: T) { super.init(a: t) }
162+
}
163+
164+
165+
public func testConditionalConformance<T: P2>(t: T) {
166+
takes_p1(ConditionalConformanceDerived(t: t))
167+
}
168+
169+
170+
struct S: P2 {
171+
var i: Int
172+
173+
func foo() {
174+
print(i)
175+
}
176+
}
177+
178+
protocol Q3 {
179+
func bar()
180+
}
181+
182+
protocol P3<T> {
183+
associatedtype T: Q3
184+
185+
var t: T { get }
186+
187+
func foo()
188+
}
189+
190+
extension P3 {
191+
func foo() {
192+
t.bar()
193+
}
194+
}
195+
196+
struct C3<T: Q3>: P3 {
197+
var t: T
198+
199+
200+
init(t: T) { self.t = t }
201+
}
202+
203+
struct S3<I: BinaryInteger>: Q3 {
204+
var x: I
205+
206+
func bar() {
207+
print(x)
208+
}
209+
}
210+
211+
@inline(never)
212+
func testP3() -> any P3 {
213+
return C3(t: S3(x: 102))
214+
}
215+
216+
protocol P4<T> {
217+
associatedtype T: Q
218+
219+
var t: T { get }
220+
221+
func foo()
222+
}
223+
224+
extension P4 {
225+
func foo() {
226+
t.bar()
227+
}
228+
}
229+
230+
struct C4<T: Q>: P4 {
231+
var t: T
232+
233+
234+
init(t: T) { self.t = t }
235+
}
236+
237+
struct K4<I: BinaryInteger>: Q {
238+
var x: I
239+
240+
init(x: I) { self.x = x }
241+
242+
func bar() {
243+
print(x)
244+
}
245+
}
246+
247+
@inline(never)
248+
func testP4() -> any P4 {
249+
return C4(t: K4(x: 437))
250+
}
251+
*/
252+
253+
@main
254+
struct Main {
255+
static func main() {
256+
test(existential: MyStruct(i: 27))
257+
// CHECK: MyStruct.foo: 27
258+
// CHECK: MyStruct.bar: 27
259+
260+
test(existential: LargeStruct(a: 10, b: 11, c: 12, d: 13))
261+
// CHECK: LargeStruct.foo: 10, 11, 12, 13
262+
// CHECK: LargeStruct.bar: 10, 11, 12, 13
263+
264+
test(existential: GenericStruct(t: 28))
265+
// CHECK: GenericStruct.foo: 28
266+
// CHECK: GenericStruct.bar: 28
267+
268+
/*
269+
callExWithAssocType(createExWithAssocType())
270+
// xCHECK: 27
271+
272+
callExWithAssocConf(createExWithAssocConf())
273+
// xCHECK: foo
274+
// xCHECK: bar
275+
276+
callExWithAssocConf(OtherClass())
277+
// xCHECK: other-foo
278+
// xCHECK: derived-bar
279+
280+
test(existential: Derived1())
281+
// xCHECK: Derived1.foo()
282+
// xCHECK: Derived1.bar()
283+
284+
test(existential: Derived2<Bool>())
285+
// xCHECK: Derived2.foo()
286+
// xCHECK: Derived2.bar()
287+
288+
testConditionalConformance(t: S(i: 27))
289+
// xCHECK: 27
290+
291+
testP3().foo()
292+
// xCHECK: 102
293+
294+
testP4().foo()
295+
// xCHECK: 437
296+
*/
297+
}
298+
}
299+
300+

0 commit comments

Comments
 (0)