File: devirt_unbound_generic.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 (209 lines) | stat: -rw-r--r-- 4,299 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
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
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -enable-spec-devirt -O %s | %FileCheck %s

// We used to crash on this when trying to devirtualize t.boo(a, 1),
// because it is an "apply" with replacement types that contain
// archetypes, and the devirtualizer was not able to handle that
// case correctly.
//
// rdar://19912272

protocol P {
  associatedtype Node
}

class C<T:P> {
  typealias Node = T.Node

  func foo(_ n:Node) {
  }

  func boo<S>(_ n:Node, s:S) {
  }
}

func test1<T>(_ t:C<T>, a: T.Node) {
   t.boo(a, s:1)
}


class Base<T> {
  func foo() {
  }

  class func boo() {
  }
}

class Derived<T> : Base<T> {
  override func foo() {
  }
  
  override class func boo() {
  }
}

// Check that testDevirt is specialized and uses speculative devirtualization.
// CHECK-LABEL: sil shared [noinline] @{{.*}}testDevirt
// CHECK: checked_cast_br [exact] CC<Int32> in %{{.*}} : $CC<Int32> to CC<Int32>
// CHECK: class_method
// CHECK: }
@inline(never)
public func testDevirt<T>(_ c: CC<T>) -> T? {
  return c.next()
}


// Check that the instance method Derived<T>.foo can be devirtualized, because Derived.foo is an internal function,
// Derived has no subclasses and it is a WMO compilation.
// CHECK-LABEL: sil shared [noinline] @$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n
// CHECK-NOT: class_method
// CHECK-NOT: witness_method
// CHECK-NOT: apply
// CHECK: return
// CHECK: end sil function '$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n'
@inline(never)
func test2<T>(_ d: Derived<T>) {
   d.foo()
}

public func doTest2<T>(_ t:T) {
  test2(Derived<T>())
}

// Check that the class method Derived<T>.boo can be devirtualized, because Derived.boo is an internal function,
// Derived has no subclasses and it is a WMO compilation.
// CHECK: sil shared [noinline] @$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n
// CHECK-NOT: class_method
// CHECK-NOT: witness_method
// CHECK-NOT: apply
// CHECK: return
// CHECK: end sil function '$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n'
@inline(never)
func test3<T>(_ d: Derived<T>) {
   type(of: d).boo()
}

public func doTest3<T>(_ t:T) {
  test3(Derived<T>())
}


public protocol ProtocolWithAssocType {
  associatedtype Element
}

private class CP<Base: ProtocolWithAssocType> {
   var value: Base.Element
   init(_ v: Base.Element) {
     value = v
   }

   func getCount() -> Int32 {
     return 1
   }
}

private class Base1: ProtocolWithAssocType {
   typealias Element = Int32
}


private class Base2<T>: ProtocolWithAssocType {
   typealias Element = Int32
}

private class CP2: CP<Base2<Int>> {
  init() {
    super.init(1)
  }

  override func getCount() -> Int32 {
    return 2
  }
}

private class CP3: CP<Base2<Int>> {
  init() {
    super.init(1)
  }

  override func getCount() -> Int32 {
    return 3
  }
}

public class CC<CT> {
   func next() -> CT? {
     return nil
   }
}

public protocol QQ {
  associatedtype Base: PP
}

public protocol PP {
  associatedtype Element
}

internal class D<DT: QQ> : CC<DT.Base.Element> {
  override func next() -> DT.Base.Element? {
    return nil
  }
}

public struct S: PP {
  public typealias Element = Int32
}

final public class E: QQ {
  public typealias Base = S
}

// Check that c.next() inside test4 gets completely devirtualized.
// CHECK-LABEL: sil @{{.*}}test4{{.*}}
// CHECK-NOT: class_method
// CHECK: return
public func test4() -> Int32? {
  let c: CC<Int32> = D<E>();
  return c.next()
}

public func test5() -> Int32? {
  return testDevirt(D<E>())
}

// The compiler used to crash on this code, because of
// generic types involved in the devirtualization.
//
// rdar://25891588
//
// CHECK-LABEL: sil private [noinline] {{.*}}@{{.*}}test6
// CHECK-NOT: class_method
// CHECK-NOT: checked_cast_br
// CHECK-NOT: class_method
// CHECK: }
@inline(never)
private func test6<T: ProtocolWithAssocType>(_ c: CP<T>) -> T.Element {
  return c.value
}

public func doTest6() {
  test6(CP<Base1>(1))
}

// CHECK-LABEL: sil private [noinline] @{{.*}}test7
// CHECK-NOT: class_method
// CHECK: checked_cast_br
// CHECK-NOT: class_method
// CHECK: }
@inline(never)
private func test7<T: ProtocolWithAssocType>(_ c: CP<T>) -> Int32 {
  return c.getCount()
}

public func doTest7() {
  test7(CP2())
}