File: devirtualize_protocol_composition.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (140 lines) | stat: -rw-r--r-- 2,753 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// RUN: %target-swift-frontend -parse-as-library -O -wmo -emit-sil  %s | %FileCheck %s
// RUN: %target-swift-frontend -parse-as-library -Osize -wmo -emit-sil  %s | %FileCheck %s

// REQUIRES: objc_interop

// This is an end-to-end test to ensure that the optimizer devirtualizes
// calls to a protocol composition type.

public class ClassA<T> { }

protocol ProtocolA {
  func foo() -> Int
}

protocol ProtocolB {
  func bar() -> Int
}

public class ClassB: ClassA<String> {
  func foo() -> Int {
    return 10
  }
}

extension ClassB: ProtocolA { }

public class ClassC<T>: ClassA<T> {
  func foo() -> Int {
    return 10
  }
}

extension ClassC: ProtocolA { }

public class ClassD { }
public class ClassE : ClassD {
  func foo() -> Int {
    return 10
  }
}

extension ClassE: ProtocolA { }

public class ClassF {
  func foo() -> Int {
    return 10
  }
  
  func bar() -> Int {
    return 10
  }
}

extension ClassF: ProtocolA, ProtocolB { }

public class ClassG <T> {
  func foo() -> Int {
    return 10
  }
  
  func bar() -> Int {
    return 10
  }
}

extension ClassG: ProtocolA, ProtocolB { }

public class ClassH {
  typealias type = ClassD
}

func shouldOptimize1<T>(_ x: ClassA<T> & ProtocolA) -> Int {
  return x.foo()
}

func shouldOptimize2(_ x: ClassD & ProtocolA) -> Int {
  return x.foo()
}

func shouldOptimize3(_ x: ProtocolA & ProtocolB) -> Int {
  return x.foo() + x.bar()
}

func shouldOptimize4(_ x: ProtocolA & ProtocolB) -> Int {
  return x.foo() + x.bar()
}

func shouldOptimize5(_ x: ClassH.type & ProtocolA) -> Int {
  return x.foo()
}

//CHECK: entryPoint1
//CHECK-NOT: init_existential_ref
//CHECK-NOT: open_existential_ref
//CHECK-NOT: witness_method
//CHECK: return
public func entryPoint1(c: ClassB) -> Int {
  return shouldOptimize1(c)
}

// TODO: create SR -- this causes a crash on master too
//public func entryPoint2<T>(c: ClassC<T>) -> Int {
//  return shouldOptimize1(c)
//}

//CHECK: entryPoint3
//CHECK-NOT: init_existential_ref
//CHECK-NOT: open_existential_ref
//CHECK-NOT: witness_method
//CHECK: return
public func entryPoint3(c: ClassE) -> Int {
  return shouldOptimize2(c)
}

//CHECK: entryPoint4
//CHECK-NOT: init_existential_ref
//CHECK-NOT: open_existential_ref
//CHECK-NOT: witness_method
//CHECK: return
public func entryPoint4(c: ClassF) -> Int {
  return shouldOptimize3(c)
}

//CHECK: entryPoint5
//CHECK-NOT: init_existential_ref
//CHECK-NOT: open_existential_ref
//CHECK-NOT: witness_method
//CHECK: return
public func entryPoint5<T>(c: ClassG<T>) -> Int {
  return shouldOptimize4(c)
}

//CHECK: entryPoint6
//CHECK-NOT: init_existential_ref
//CHECK-NOT: open_existential_ref
//CHECK-NOT: witness_method
//CHECK: return
public func entryPoint6(c: ClassE) -> Int {
  return shouldOptimize5(c)
}