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)
}
|