forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdead_function_elimination.swift
230 lines (181 loc) · 4.66 KB
/
dead_function_elimination.swift
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck %s
// RUN: %target-swift-frontend %s -O -emit-sil -enable-testing | %FileCheck -check-prefix=CHECK-TESTING %s
// Check if cycles are removed.
@inline(never)
func inCycleA() {
inCycleB()
}
@inline(never)
func inCycleB() {
inCycleA()
}
// Check if unused vtable methods are removed.
class Base {
@inline(never)
func aliveMethod() {
}
@inline(never)
func DeadMethod() {
// introduces a cycle
testClasses(self)
}
// alive, because called with super
@inline(never)
func calledWithSuper() {
}
// dead, because only overridden method is called
@inline(never)
func baseNotCalled() {
}
// alive, because called for Derived but not overridden in Derived
@inline(never)
func notInDerived() {
}
// dead, because only overridden method is called
@inline(never)
func notInOther() {
}
}
class Derived : Base {
@inline(never)
override func aliveMethod() {
}
@inline(never)
override func DeadMethod() {
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
override func calledWithSuper() {
super.calledWithSuper()
}
@inline(never)
override func baseNotCalled() {
}
@inline(never)
override func notInOther() {
}
}
class Other : Derived {
@inline(never)
override func baseNotCalled() {
}
@inline(never)
override func notInDerived() {
}
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
func testClasses(_ b: Base) {
b.aliveMethod()
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
func testWithDerived(_ d: Derived) {
d.baseNotCalled()
d.notInDerived()
d.calledWithSuper()
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
func testWithOther(_ o: Other) {
o.notInOther()
}
// Check if dead methods of classes with higher visibility are removed.
public class PublicCl {
func publicClassMethod() {
}
}
// Check if unused witness table methods are removed.
protocol Prot {
func aliveWitness()
func DeadWitness()
func aliveDefaultWitness()
func DeadDefaultWitness()
}
extension Prot {
@inline(never)
func aliveDefaultWitness() {
}
@inline(never)
func DeadDefaultWitness() {
}
}
struct Adopt : Prot {
@inline(never)
func aliveWitness() {
}
@inline(never)
func DeadWitness() {
}
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
func testProtocols(_ p: Prot) {
p.aliveWitness()
}
@inline(never)
@_semantics("optimize.sil.never") // avoid devirtualization
func testDefaultWitnessMethods(_ p: Prot) {
p.aliveDefaultWitness()
}
@_semantics("optimize.sil.never") // avoid devirtualization
public func callTest() {
testClasses(Base())
testClasses(Derived())
testWithDerived(Derived())
testWithOther(Other())
testProtocols(Adopt())
}
@_semantics("optimize.sil.never") // make sure not eliminated
internal func donotEliminate() {
return
}
// CHECK-NOT: sil {{.*}}inCycleA
// CHECK-NOT: sil {{.*}}inCycleB
// CHECK-NOT: sil {{.*}}DeadMethod
// CHECK-NOT: sil {{.*}}DeadWitness
// CHECK-NOT: sil {{.*}}publicClassMethod
// CHECK-TESTING: sil {{.*}}inCycleA
// CHECK-TESTING: sil {{.*}}inCycleB
// CHECK-TESTING: sil {{.*}}DeadMethod
// CHECK-TESTING: sil {{.*}}publicClassMethod
// CHECK-TESTING: sil {{.*}}DeadWitness
// CHECK-LABEL: @_T025dead_function_elimination14donotEliminateyyF
// CHECK-LABEL: sil_vtable Base
// CHECK: aliveMethod
// CHECK: calledWithSuper
// CHECK-NOT: DeadMethod
// CHECK-NOT: baseNotCalled
// CHECK: notInDerived
// CHECK-NOT: notInOther
// CHECK-TESTING-LABEL: sil_vtable Base
// CHECK-TESTING: DeadMethod
// CHECK-LABEL: sil_vtable Derived
// CHECK: aliveMethod
// CHECK-NOT: DeadMethod
// CHECK: baseNotCalled
// CHECK: notInDerived
// CHECK: notInOther
// CHECK-TESTING-LABEL: sil_vtable Derived
// CHECK-TESTING: DeadMethod
// CHECK-LABEL: sil_vtable Other
// CHECK: aliveMethod
// CHECK-NOT: DeadMethod
// CHECK: baseNotCalled
// CHECK: notInDerived
// CHECK: notInOther
// CHECK-LABEL: sil_witness_table hidden Adopt: Prot
// CHECK: aliveWitness!1: {{.*}} : @{{.*}}aliveWitness
// CHECK: DeadWitness!1: {{.*}} : nil
// CHECK-TESTING-LABEL: sil_witness_table [serialized] Adopt: Prot
// CHECK-TESTING: DeadWitness{{.*}}: @{{.*}}DeadWitness
// CHECK-LABEL: sil_default_witness_table hidden Prot
// CHECK: no_default
// CHECK: no_default
// CHECK: method #Prot.aliveDefaultWitness!1: {{.*}} : @{{.*}}aliveDefaultWitness
// CHECK: no_default
// CHECK-TESTING-LABEL: sil_default_witness_table Prot
// CHECK-TESTING: no_default
// CHECK-TESTING: no_default
// CHECK-TESTING: method #Prot.aliveDefaultWitness!1: {{.*}} : @{{.*}}aliveDefaultWitness
// CHECK-TESTING: method #Prot.DeadDefaultWitness!1: {{.*}} : @{{.*}}DeadDefaultWitness