Files
swift-mirror/test/SILOptimizer/devirt_unbound_generic.swift
Erik Eckstein 65e4c10113 Optimizer: remove the obsolete SpeculativeDevirtualization pass
This pass has been disabled since a very long time (because it's terrible for code size).
It does not work for OSSA. Therefore it cannot be enabled anymore (as is) once we have OSSA throughout the pipeline.
So it's time to completely remove it.
2025-10-13 10:49:17 +02:00

209 lines
4.2 KiB
Swift

// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -Xllvm -sil-print-types -emit-sil -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
// This used to check speculative-devirtualization, which we don't have anymore.
// 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
// This used to check speculative-devirtualization, which we don't have anymore.
// CHECK: class_method
// CHECK: }
@inline(never)
private func test7<T: ProtocolWithAssocType>(_ c: CP<T>) -> Int32 {
return c.getCount()
}
public func doTest7() {
test7(CP2())
}