blob: 8d8d3499d1d3fc7b0c053076c87a2489c2139ca5 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer -inline | %FileCheck %s --check-prefix=CHECK-DEVIRT
// RUN: %target-sil-opt -enable-sil-verify-all %s -mandatory-inlining | %FileCheck %s --check-prefix=CHECK-MANDATORY-INLINING
sil_stage canonical
import Builtin
import Swift
import SwiftShims
public class Base {
@inline(never) func foo() throws -> Int32?
@inline(never) func boo1() throws -> Base
@inline(never) func boo2() throws -> Base?
deinit
init()
}
public class Derived1 : Base {
@inline(never) override func foo() throws -> Int32?
@inline(never) override func boo1() throws -> Derived1
@inline(never) override func boo2() throws -> Derived1?
deinit
override init()
}
public class Derived2 : Base {
@inline(never) override func foo() throws -> Int32
@inline(never) override func boo1() throws -> Derived2
@inline(never) override func boo2() throws -> Derived2
deinit
override init()
}
public protocol P {
func foo() throws -> Int32
}
public class CP1 : P {
public func foo() throws -> Int32
deinit
init()
}
public class CP2 : CP1 {
override public func foo() throws -> Int32
deinit
override init()
}
@inline(never) public func testTryApplyDevirt1(b: Base) -> Int32?
@inline(never) public func testTryApplyDevirt2(b: Base) -> Base?
@inline(never) public func testTryApplyDevirt3(b: Base) -> Base?
public func test1()
public func test2()
public func test3()
public func test4() -> Int32
public func test5() -> Int32
public func test6() -> Int32?
sil_global [serialized] @_TZvOs7Process5_argcVs5Int32 : $Int32
sil_global private_external [serialized] @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token5 : $Builtin.Word
sil_global [serialized] @_TZvOs7Process11_unsafeArgvGVs20UnsafeMutablePointerGS0_Vs4Int8__ : $UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<UnsafeMutablePointer<Int8>>):
%2 = global_addr @_TZvOs7Process5_argcVs5Int32 : $*Int32
store %0 to [trivial] %2 : $*Int32
%4 = global_addr @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token5 : $*Builtin.Word
%5 = address_to_pointer %4 : $*Builtin.Word to $Builtin.RawPointer
%6 = function_ref @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func5 : $@convention(thin) () -> ()
%7 = builtin "once"(%5 : $Builtin.RawPointer, %6 : $@convention(thin) () -> ()) : $()
%8 = global_addr @_TZvOs7Process11_unsafeArgvGVs20UnsafeMutablePointerGS0_Vs4Int8__ : $*UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
store %1 to [trivial] %8 : $*UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
%10 = tuple ()
%11 = integer_literal $Builtin.Int32, 0
%12 = struct $Int32 (%11 : $Builtin.Int32)
return %12 : $Int32
}
sil [transparent] [serialized] [ossa] @_TFs13_didEnterMainFTVs5Int324argvGVs20UnsafeMutablePointerGS0_Vs4Int8___T_ : $@convention(thin) (Int32, UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> ()
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Base) -> (Optional<Int32>, @error Error) {
bb0(%0 : @guaranteed $Base):
debug_value %0 : $Base
%2 = integer_literal $Builtin.Int32, 0
%3 = struct $Int32 (%2 : $Builtin.Int32)
%4 = enum $Optional<Int32>, #Optional.some!enumelt.1, %3 : $Int32
return %4 : $Optional<Int32>
}
sil [transparent] [serialized] [ossa] @_TFVs5Int32CfMS_FT22_builtinIntegerLiteralBI__S_ : $@convention(thin) (Builtin.IntLiteral, @thin Int32.Type) -> Int32
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error) {
bb0(%0 : @guaranteed $Base):
%1 = copy_value %0 : $Base
return %1 : $Base
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Base) -> (@owned Optional<Base>, @error Error) {
bb0(%0 : @guaranteed $Base):
%1 = copy_value %0 : $Base
%2 = enum $Optional<Base>, #Optional.some!enumelt.1, %1 : $Base
return %2 : $Optional<Base>
}
sil [ossa] @_TFC16devirt_try_apply4BaseD : $@convention(method) (@owned Base) -> () {
bb0(%0 : @owned $Base):
%2 = function_ref @_TFC16devirt_try_apply4Based : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
%3 = apply %2(%0) : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
end_lifetime %0 : $Base
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Base
dealloc_ref %4 : $Base
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TFC16devirt_try_apply4Based : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $Base):
%1 = unchecked_ref_cast %0 : $Base to $Builtin.NativeObject
%2 = unchecked_ownership_conversion %1 : $Builtin.NativeObject, @guaranteed to @owned
return %2 : $Builtin.NativeObject
}
sil hidden [ossa] @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ : $@convention(method) (@owned Base) -> @owned Base {
bb0(%0 : @owned $Base):
return %0 : $Base
}
sil hidden [ossa] @_TFC16devirt_try_apply4BaseCfMS0_FT_S0_ : $@convention(thin) (@thick Base.Type) -> @owned Base {
bb0(%0 : $@thick Base.Type):
%1 = alloc_ref $Base
%2 = function_ref @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ : $@convention(method) (@owned Base) -> @owned Base
%3 = apply %2(%1) : $@convention(method) (@owned Base) -> @owned Base
return %3 : $Base
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Derived1) -> (Optional<Int32>, @error Error) {
bb0(%0 : @guaranteed $Derived1):
%2 = integer_literal $Builtin.Int32, 1
%3 = struct $Int32 (%2 : $Builtin.Int32)
%4 = enum $Optional<Int32>, #Optional.some!enumelt.1, %3 : $Int32
return %4 : $Optional<Int32>
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived1) -> (@owned Derived1, @error Error) {
bb0(%0 : @guaranteed $Derived1):
%1 = copy_value %0 : $Derived1
return %1 : $Derived1
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Derived1) -> (@owned Optional<Derived1>, @error Error) {
bb0(%0 : @guaranteed $Derived1):
%1 = copy_value %0 : $Derived1
%2 = enum $Optional<Derived1>, #Optional.some!enumelt.1, %1 : $Derived1
return %2 : $Optional<Derived1>
}
sil [ossa] @_TFC16devirt_try_apply8Derived1D : $@convention(method) (@owned Derived1) -> () {
bb0(%0 : @owned $Derived1):
%2 = function_ref @_TFC16devirt_try_apply8Derived1d : $@convention(method) (@guaranteed Derived1) -> @owned Builtin.NativeObject
%3 = apply %2(%0) : $@convention(method) (@guaranteed Derived1) -> @owned Builtin.NativeObject
end_lifetime %0 : $Derived1
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Derived1
dealloc_ref %4 : $Derived1
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TFC16devirt_try_apply8Derived1d : $@convention(method) (@guaranteed Derived1) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $Derived1):
%2 = upcast %0 : $Derived1 to $Base
%3 = function_ref @_TFC16devirt_try_apply4Based : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
%4 = apply %3(%2) : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
return %4 : $Builtin.NativeObject
}
sil hidden [ossa] @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ : $@convention(method) (@owned Derived1) -> @owned Derived1 {
bb0(%0 : @owned $Derived1):
%1 = alloc_stack $Derived1
%2 = copy_value %0 : $Derived1
store %0 to [init] %1 : $*Derived1
%3 = upcast %2 : $Derived1 to $Base
%4 = function_ref @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ : $@convention(method) (@owned Base) -> @owned Base
%7 = apply %4(%3) : $@convention(method) (@owned Base) -> @owned Base
%8 = unchecked_ref_cast %7 : $Base to $Derived1
%9 = copy_value %8 : $Derived1
store %8 to [assign] %1 : $*Derived1
dealloc_stack %1 : $*Derived1
return %9 : $Derived1
}
sil hidden [ossa] @_TFC16devirt_try_apply8Derived1CfMS0_FT_S0_ : $@convention(thin) (@thick Derived1.Type) -> @owned Derived1 {
bb0(%0 : $@thick Derived1.Type):
%1 = alloc_ref $Derived1
%2 = function_ref @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ : $@convention(method) (@owned Derived1) -> @owned Derived1
%3 = apply %2(%1) : $@convention(method) (@owned Derived1) -> @owned Derived1
return %3 : $Derived1
}
sil private [ossa] @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Optional<Int32>, @error Error) {
bb0(%0 : @guaranteed $Derived2):
%1 = function_ref @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error)
try_apply %1(%0) : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error), normal bb1, error bb2
bb1(%3 : $Int32):
%4 = enum $Optional<Int32>, #Optional.some!enumelt.1, %3 : $Int32
return %4 : $Optional<Int32>
bb2(%6 : @owned $Error):
%7 = builtin "willThrow"(%6 : $Error) : $()
throw %6 : $Error
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error) {
bb0(%0 : @guaranteed $Derived2):
%2 = integer_literal $Builtin.Int32, 2
%3 = struct $Int32 (%2 : $Builtin.Int32)
return %3 : $Int32
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) {
bb0(%0 : @guaranteed $Derived2):
%1 = copy_value %0 : $Derived2
return %1 : $Derived2
}
sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) {
bb0(%0 : @guaranteed $Derived2):
%1 = copy_value %0 : $Derived2
return %1 : $Derived2
}
sil [ossa] @_TFC16devirt_try_apply8Derived2D : $@convention(method) (@owned Derived2) -> () {
bb0(%0 : @owned $Derived2):
%2 = function_ref @_TFC16devirt_try_apply8Derived2d : $@convention(method) (@guaranteed Derived2) -> @owned Builtin.NativeObject
%3 = apply %2(%0) : $@convention(method) (@guaranteed Derived2) -> @owned Builtin.NativeObject
end_lifetime %0 : $Derived2
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Derived2
dealloc_ref %4 : $Derived2
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TFC16devirt_try_apply8Derived2d : $@convention(method) (@guaranteed Derived2) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $Derived2):
%2 = upcast %0 : $Derived2 to $Base
%3 = function_ref @_TFC16devirt_try_apply4Based : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
%4 = apply %3(%2) : $@convention(method) (@guaranteed Base) -> @owned Builtin.NativeObject
return %4 : $Builtin.NativeObject
}
sil hidden [ossa] @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ : $@convention(method) (@owned Derived2) -> @owned Derived2 {
bb0(%0 : @owned $Derived2):
%1 = alloc_stack $Derived2
%2 = copy_value %0 : $Derived2
store %0 to [init] %1 : $*Derived2
%3 = upcast %2 : $Derived2 to $Base
%4 = function_ref @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ : $@convention(method) (@owned Base) -> @owned Base
%7 = apply %4(%3) : $@convention(method) (@owned Base) -> @owned Base
%8 = unchecked_ref_cast %7 : $Base to $Derived2
%9 = copy_value %8 : $Derived2
store %8 to [assign] %1 : $*Derived2
dealloc_stack %1 : $*Derived2
return %9 : $Derived2
}
sil [ossa] @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error) {
bb0(%0 : @guaranteed $CP1):
%2 = integer_literal $Builtin.Int32, 1
%3 = struct $Int32 (%2 : $Builtin.Int32)
return %3 : $Int32
}
sil [ossa] @_TFC16devirt_try_apply3CP1D : $@convention(method) (@owned CP1) -> () {
bb0(%0 : @owned $CP1):
%2 = function_ref @_TFC16devirt_try_apply3CP1d : $@convention(method) (@guaranteed CP1) -> @owned Builtin.NativeObject
%3 = apply %2(%0) : $@convention(method) (@guaranteed CP1) -> @owned Builtin.NativeObject
end_lifetime %0 : $CP1
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $CP1
dealloc_ref %4 : $CP1
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TFC16devirt_try_apply3CP1d : $@convention(method) (@guaranteed CP1) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $CP1):
%1 = unchecked_ref_cast %0 : $CP1 to $Builtin.NativeObject
%2 = unchecked_ownership_conversion %1 : $Builtin.NativeObject, @guaranteed to @owned
return %2 : $Builtin.NativeObject
}
sil hidden [ossa] @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_ : $@convention(method) (@owned CP1) -> @owned CP1 {
bb0(%0 : @owned $CP1):
return %0 : $CP1
}
sil hidden [ossa] @_TFC16devirt_try_apply3CP1CfMS0_FT_S0_ : $@convention(thin) (@thick CP1.Type) -> @owned CP1 {
bb0(%0 : $@thick CP1.Type):
%1 = alloc_ref $CP1
%2 = function_ref @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_ : $@convention(method) (@owned CP1) -> @owned CP1
%3 = apply %2(%1) : $@convention(method) (@owned CP1) -> @owned CP1
return %3 : $CP1
}
sil [transparent] [thunk] [ossa] @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32 : $@convention(witness_method: P) (@in_guaranteed CP1) -> (Int32, @error Error) {
bb0(%0 : $*CP1):
%1 = load [copy] %0 : $*CP1
%3 = class_method %1 : $CP1, #CP1.foo!1 : (CP1) -> () throws -> Int32, $@convention(method) (@guaranteed CP1) -> (Int32, @error Error)
try_apply %3(%1) : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error), normal bb1, error bb2
bb1(%5 : $Int32):
destroy_value %1 : $CP1
return %5 : $Int32
bb2(%8 : @owned $Error):
%9 = builtin "willThrow"(%8 : $Error) : $()
destroy_value %1 : $CP1
throw %8 : $Error
}
sil [ossa] @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) {
bb0(%0 : @guaranteed $CP2):
%2 = integer_literal $Builtin.Int32, 2
%3 = struct $Int32 (%2 : $Builtin.Int32)
return %3 : $Int32
}
sil [ossa] @_TFC16devirt_try_apply3CP2D : $@convention(method) (@owned CP2) -> () {
bb0(%0 : @owned $CP2):
%2 = function_ref @_TFC16devirt_try_apply3CP2d : $@convention(method) (@guaranteed CP2) -> @owned Builtin.NativeObject
%3 = apply %2(%0) : $@convention(method) (@guaranteed CP2) -> @owned Builtin.NativeObject
end_lifetime %0 : $CP2
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $CP2
dealloc_ref %4 : $CP2
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TFC16devirt_try_apply3CP2d : $@convention(method) (@guaranteed CP2) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $CP2):
%2 = upcast %0 : $CP2 to $CP1
%3 = function_ref @_TFC16devirt_try_apply3CP1d : $@convention(method) (@guaranteed CP1) -> @owned Builtin.NativeObject
%4 = apply %3(%2) : $@convention(method) (@guaranteed CP1) -> @owned Builtin.NativeObject
return %4 : $Builtin.NativeObject
}
sil hidden [ossa] @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ : $@convention(method) (@owned CP2) -> @owned CP2 {
bb0(%0 : @owned $CP2):
%1 = alloc_stack $CP2
%2 = copy_value %0 : $CP2
store %0 to [init] %1 : $*CP2
%3 = upcast %2 : $CP2 to $CP1
%4 = function_ref @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_ : $@convention(method) (@owned CP1) -> @owned CP1
%7 = apply %4(%3) : $@convention(method) (@owned CP1) -> @owned CP1
%8 = unchecked_ref_cast %7 : $CP1 to $CP2
%9 = copy_value %8 : $CP2
store %8 to [assign] %1 : $*CP2
dealloc_stack %1 : $*CP2
return %9 : $CP2
}
sil hidden [ossa] @_TFC16devirt_try_apply3CP2CfMS0_FT_S0_ : $@convention(thin) (@thick CP2.Type) -> @owned CP2 {
bb0(%0 : $@thick CP2.Type):
%1 = alloc_ref $CP2
%2 = function_ref @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ : $@convention(method) (@owned CP2) -> @owned CP2
%3 = apply %2(%1) : $@convention(method) (@owned CP2) -> @owned CP2
return %3 : $CP2
}
// Check that -specdevirt can devirtualize it
// CHECK-SPECDEVIRT-LABEL: sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt1FCS_4BaseGSqVs5Int32_
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt1FCS_4BaseGSqVs5Int32_ : $@convention(thin) (@owned Base) -> Optional<Int32> {
bb0(%0 : @owned $Base):
%1 = alloc_stack $Optional<Int32>
%3 = alloc_stack $Optional<Int32>
inject_enum_addr %3 : $*Optional<Int32>, #Optional.none!enumelt
%6 = load [trivial] %3 : $*Optional<Int32>
store %6 to [trivial] %1 : $*Optional<Int32>
dealloc_stack %3 : $*Optional<Int32>
%9 = class_method %0 : $Base, #Base.foo!1 : (Base) -> () throws -> Int32?, $@convention(method) (@guaranteed Base) -> (Optional<Int32>, @error Error)
try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (Optional<Int32>, @error Error), normal bb1, error bb4
bb1(%11 : $Optional<Int32>):
store %11 to [trivial] %1 : $*Optional<Int32>
br bb2
bb2:
%14 = load [trivial] %1 : $*Optional<Int32>
destroy_value %0 : $Base
dealloc_stack %1 : $*Optional<Int32>
return %14 : $Optional<Int32>
bb3:
destroy_value %20 : $Error
br bb2
bb4(%20 : @owned $Error):
br bb3
}
sil [transparent] [serialized] [ossa] @_TFSqCurfMGSqq__FT10nilLiteralT__GSqq__ : $@convention(thin) <T> (@thin Optional<T>.Type) -> @out Optional<T>
// Check that -specdevirt can devirtualize it
// CHECK-SPECDEVIRT-LABEL: sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt2FCS_4BaseGSqS0__
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt2FCS_4BaseGSqS0__ : $@convention(thin) (@owned Base) -> @owned Optional<Base> {
bb0(%0 : @owned $Base):
%1 = alloc_stack $Optional<Base>
%3 = alloc_stack $Optional<Base>
inject_enum_addr %3 : $*Optional<Base>, #Optional.none!enumelt
%6 = load [take] %3 : $*Optional<Base>
store %6 to [init] %1 : $*Optional<Base>
dealloc_stack %3 : $*Optional<Base>
%9 = class_method %0 : $Base, #Base.boo1!1 : (Base) -> () throws -> Base, $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error)
try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error), normal bb1, error bb4
bb1(%11 : @owned $Base):
%12 = enum $Optional<Base>, #Optional.some!enumelt.1, %11 : $Base
store %12 to [assign] %1 : $*Optional<Base>
br bb2
bb2:
%16 = load [copy] %1 : $*Optional<Base>
destroy_addr %1 : $*Optional<Base>
destroy_value %0 : $Base
dealloc_stack %1 : $*Optional<Base>
return %16 : $Optional<Base>
bb3:
destroy_value %24 : $Error
br bb2
bb4(%24 : @owned $Error):
br bb3
}
// Check that -specdevirt can devirtualize it
// CHECK-SPECDEVIRT-LABEL: sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt3FCS_4BaseGSqS0__
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
sil [noinline] [ossa] @_TF16devirt_try_apply19testTryApplyDevirt3FCS_4BaseGSqS0__ : $@convention(thin) (@owned Base) -> @owned Optional<Base> {
bb0(%0 : @owned $Base):
%1 = alloc_stack $Optional<Base>
%3 = alloc_stack $Optional<Base>
inject_enum_addr %3 : $*Optional<Base>, #Optional.none!enumelt
%6 = load [take] %3 : $*Optional<Base>
store %6 to [init] %1 : $*Optional<Base>
dealloc_stack %3 : $*Optional<Base>
%9 = class_method %0 : $Base, #Base.boo2!1 : (Base) -> () throws -> Base?, $@convention(method) (@guaranteed Base) -> (@owned Optional<Base>, @error Error)
try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Optional<Base>, @error Error), normal bb1, error bb4
bb1(%11 : @owned $Optional<Base>):
store %11 to [assign] %1 : $*Optional<Base>
br bb2
bb2:
%15 = load [copy] %1 : $*Optional<Base>
destroy_addr %1 : $*Optional<Base>
destroy_value %0 : $Base
dealloc_stack %1 : $*Optional<Base>
return %15 : $Optional<Base>
bb3:
destroy_value %23 : $Error
br bb2
bb4(%23 : @owned $Error):
br bb3
}
sil [ossa] @_TF16devirt_try_apply5test1FT_T_ : $@convention(thin) () -> () {
bb0:
%0 = function_ref @_TF16devirt_try_apply19testTryApplyDevirt1FCS_4BaseGSqVs5Int32_ : $@convention(thin) (@owned Base) -> Optional<Int32>
%1 = function_ref @_TFC16devirt_try_apply4BaseCfMS0_FT_S0_ : $@convention(thin) (@thick Base.Type) -> @owned Base
%2 = metatype $@thick Base.Type
%3 = apply %1(%2) : $@convention(thin) (@thick Base.Type) -> @owned Base
%4 = apply %0(%3) : $@convention(thin) (@owned Base) -> Optional<Int32>
%5 = tuple ()
return %5 : $()
}
sil [ossa] @_TF16devirt_try_apply5test2FT_T_ : $@convention(thin) () -> () {
bb0:
%0 = function_ref @_TF16devirt_try_apply19testTryApplyDevirt2FCS_4BaseGSqS0__ : $@convention(thin) (@owned Base) -> @owned Optional<Base>
%1 = function_ref @_TFC16devirt_try_apply4BaseCfMS0_FT_S0_ : $@convention(thin) (@thick Base.Type) -> @owned Base
%2 = metatype $@thick Base.Type
%3 = apply %1(%2) : $@convention(thin) (@thick Base.Type) -> @owned Base
%4 = apply %0(%3) : $@convention(thin) (@owned Base) -> @owned Optional<Base>
destroy_value %4 : $Optional<Base>
%6 = tuple ()
return %6 : $()
}
sil [ossa] @_TF16devirt_try_apply5test3FT_T_ : $@convention(thin) () -> () {
bb0:
%0 = function_ref @_TF16devirt_try_apply19testTryApplyDevirt3FCS_4BaseGSqS0__ : $@convention(thin) (@owned Base) -> @owned Optional<Base>
%1 = function_ref @_TFC16devirt_try_apply4BaseCfMS0_FT_S0_ : $@convention(thin) (@thick Base.Type) -> @owned Base
%2 = metatype $@thick Base.Type
%3 = apply %1(%2) : $@convention(thin) (@thick Base.Type) -> @owned Base
%4 = apply %0(%3) : $@convention(thin) (@owned Base) -> @owned Optional<Base>
destroy_value %4 : $Optional<Base>
%6 = tuple ()
return %6 : $()
}
// Check that -specdevirt can devirtualize it
// CHECK-SPECDEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test4FT_Vs5Int32
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
// CHECK-DEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test4FT_Vs5Int32
// CHECK-DEVIRT-NOT: checked_cast_br [exact]
// CHECK-DEVIRT-NOT: class_method
// CHECK-DEVIRT: }
sil [ossa] @_TF16devirt_try_apply5test4FT_Vs5Int32 : $@convention(thin) () -> Int32 {
bb0:
%0 = alloc_stack $Int32
%1 = function_ref @_TFC16devirt_try_apply3CP2CfMS0_FT_S0_ : $@convention(thin) (@thick CP2.Type) -> @owned CP2
%2 = metatype $@thick CP2.Type
%3 = apply %1(%2) : $@convention(thin) (@thick CP2.Type) -> @owned CP2
debug_value %3 : $CP2
%5 = integer_literal $Builtin.Int32, 0
%6 = struct $Int32 (%5 : $Builtin.Int32)
store %6 to [trivial] %0 : $*Int32
%8 = class_method %3 : $CP2, #CP2.foo!1 : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error)
try_apply %8(%3) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4
bb1(%10 : $Int32):
store %10 to [trivial] %0 : $*Int32
br bb2
bb2:
%13 = load [trivial] %0 : $*Int32
destroy_value %3 : $CP2
dealloc_stack %0 : $*Int32
return %13 : $Int32
bb3:
destroy_value %19 : $Error
br bb2
bb4(%19 : @owned $Error):
br bb3
}
// DISABLE THIS TEST CASE FOR NOW. AS RLE GETS BETTER. WILL RE-ENABLE.
//
// DISABLECHECK-DEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test5FT_Vs5Int32
// DISABLECHECK-DEVIRT-NOT: = witness_method
// DISABLECHECK-DEVIRT-NOT: = class_method
// DISABLECHECK-DEVIRT: }
sil [ossa] @_TF16devirt_try_apply5test5FT_Vs5Int32 : $@convention(thin) () -> Int32 {
bb0:
%0 = alloc_stack $Int32
%1 = alloc_stack $P
%2 = init_existential_addr %1 : $*P, $CP1
%3 = function_ref @_TFC16devirt_try_apply3CP1CfMS0_FT_S0_ : $@convention(thin) (@thick CP1.Type) -> @owned CP1
%4 = metatype $@thick CP1.Type
%5 = apply %3(%4) : $@convention(thin) (@thick CP1.Type) -> @owned CP1
store %5 to [init] %2 : $*CP1
%7 = integer_literal $Builtin.Int32, 0
%8 = struct $Int32 (%7 : $Builtin.Int32)
store %8 to [trivial] %0 : $*Int32
%10 = open_existential_addr immutable_access %1 : $*P to $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60") P
%11 = witness_method $@opened("3F4928FC-364E-11E5-9488-B8E856428C60") P, #P.foo!1, %10 : $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60") P : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> (Int32, @error Error)
try_apply %11<@opened("3F4928FC-364E-11E5-9488-B8E856428C60") P>(%10) : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> (Int32, @error Error), normal bb1, error bb4
bb1(%13 : $Int32):
store %13 to [trivial] %0 : $*Int32
br bb2
bb2:
%16 = load [trivial] %0 : $*Int32
destroy_addr %1 : $*P
dealloc_stack %1 : $*P
dealloc_stack %0 : $*Int32
return %16 : $Int32
bb3:
destroy_value %23 : $Error
br bb2
bb4(%23 : @owned $Error):
br bb3
}
// Check that devirtualization happens even at -inline, without an explicit invocation of the -devirtualize.
// CHECK-SPECDEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test6FT_GSqVs5Int32_
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
// CHECK-DEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test6FT_GSqVs5Int32_
// CHECK-DEVIRT-NOT: class_method
// CHECK-DEVIRT: }
sil [ossa] @_TF16devirt_try_apply5test6FT_GSqVs5Int32_ : $@convention(thin) () -> Optional<Int32> {
bb0:
%0 = alloc_stack $Optional<Int32>
%1 = function_ref @_TFC16devirt_try_apply8Derived1CfMS0_FT_S0_ : $@convention(thin) (@thick Derived1.Type) -> @owned Derived1
%2 = metatype $@thick Derived1.Type
%3 = apply %1(%2) : $@convention(thin) (@thick Derived1.Type) -> @owned Derived1
%5 = integer_literal $Builtin.Int32, 0
%6 = struct $Int32 (%5 : $Builtin.Int32)
%7 = enum $Optional<Int32>, #Optional.some!enumelt.1, %6 : $Int32
store %7 to [trivial] %0 : $*Optional<Int32>
%9 = class_method %3 : $Derived1, #Derived1.foo!1 : (Derived1) -> () throws -> Int32?, $@convention(method) (@guaranteed Derived1) -> (Optional<Int32>, @error Error)
try_apply %9(%3) : $@convention(method) (@guaranteed Derived1) -> (Optional<Int32>, @error Error), normal bb1, error bb4
bb1(%11 : $Optional<Int32>):
store %11 to [trivial] %0 : $*Optional<Int32>
br bb2
bb2:
%14 = load [trivial] %0 : $*Optional<Int32>
destroy_value %3 : $Derived1
dealloc_stack %0 : $*Optional<Int32>
return %14 : $Optional<Int32>
bb3:
destroy_value %20 : $Error
br bb2
bb4(%20 : @owned $Error):
br bb3
}
// Check that -specdevirt can devirtualize it
// CHECK-SPECDEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test7FT_Vs5Int32
// CHECK-SPECDEVIRT: checked_cast_br [exact]
// CHECK-SPECDEVIRT: }
// CHECK-DEVIRT-LABEL: sil [ossa] @_TF16devirt_try_apply5test7FT_Vs5Int32
// CHECK-DEVIRT-NOT: checked_cast_br [exact]
// CHECK-DEVIRT-NOT: class_method
// CHECK-DEVIRT: }
// CHECK-MANDATORY-INLINING-LABEL: sil [ossa] @_TF16devirt_try_apply5test7FT_Vs5Int32
// CHECK-MANDATORY-INLINING-NOT: checked_cast_br [exact]
// CHECK-MANDATORY-INLINING-NOT: class_method
// CHECK-MANDATORY-INLINING: }
sil [ossa] @_TF16devirt_try_apply5test7FT_Vs5Int32 : $@convention(thin) () -> Int32 {
bb0:
%0 = alloc_stack $Int32
%1 = alloc_ref $CP2
%5 = integer_literal $Builtin.Int32, 0
%6 = struct $Int32 (%5 : $Builtin.Int32)
store %6 to [trivial] %0 : $*Int32
%8 = class_method %1 : $CP2, #CP2.foo!1 : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error)
try_apply %8(%1) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4
bb1(%10 : $Int32):
store %10 to [trivial] %0 : $*Int32
br bb2
bb2:
%13 = load [trivial] %0 : $*Int32
destroy_value %1 : $CP2
dealloc_stack %0 : $*Int32
return %13 : $Int32
bb3:
destroy_value %19 : $Error
br bb2
bb4(%19 : @owned $Error):
br bb3
}
sil private_external [serialized] [ossa] @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func5 : $@convention(thin) () -> ()
public class A {
deinit
init()
}
class D1 {
func f1() throws -> A?
deinit
init()
}
class D3 : D1 {
override func f1() throws -> A
deinit
override init()
}
// devirt_try_apply.D1.f1 () throws -> Swift.Optional<devirt_try_apply.A>
sil [ossa] @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ : $@convention(method) (@guaranteed D1) -> (@owned Optional<A>, @error Error)
// devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A
sil [ossa] @_TFC16devirt_try_apply2D32f1fzT_CS_1A : $@convention(method) (@guaranteed D3) -> (@owned A, @error Error)
sil [ossa] @compute_something : $@convention(thin) () -> (@owned Optional<A>, @error Error)
// CHECK-MANDATORY-INLINING-LABEL: sil [ossa] @test_devirt_try_apply_at_Onone
// CHECK-MANDATORY-INLINING: bb0:
// CHECK-MANDATORY-INLINING-NOT: bb1:
// CHECK-MANDATORY-INLINING: try_apply {{.*}}, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]]
// Check that normal BB was reused and its argument was adjusted accordingly, i.e. its type is changed from Optional<A> to A
// CHECK-MANDATORY-INLINING: [[NORMAL]]({{%[0-9]+}} : @owned $A):
// CHECK-MANDATORY-INLINING: destroy_value
// CHECK-MANDATORY-INLINING: return
// Check that error BB was reused, because it only had a single predecessor and thus
// no critical edge would be created by this reuse.
// CHECK-MANDATORY-INLINING: [[ERROR]]({{%[0-9]+}} : @owned $Error):
// CHECK-MANDATORY-INLINING: destroy_value
// CHECK-MANDATORY-INLINING: throw
// CHECK-MANDATORY-INLINING-NOT: bb3
// CHECK-MANDATORY-INLINING: }
sil [ossa] @test_devirt_try_apply_at_Onone : $@convention(thin) () -> (@owned Optional<A>, @error Error) {
bb0:
%2 = alloc_ref $D3
%3 = upcast %2 : $D3 to $D1
%4 = class_method %3 : $D1, #D1.f1!1 : (D1) -> () throws -> Optional<A>, $@convention(method) (@guaranteed D1) -> (@owned Optional<A>, @error Error)
try_apply %4(%3) : $@convention(method) (@guaranteed D1) -> (@owned Optional<A>, @error Error), normal bb1, error bb2
bb1(%6 : @owned $Optional<A>):
destroy_value %3 : $D1
return %6 : $Optional<A>
bb2(%10 : @owned $Error):
destroy_value %3 : $D1
throw %10 : $Error
}
sil_vtable A {
}
sil_vtable D1 {
#D1.f1!1: @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_// devirt_try_apply.D1.f1 () throws -> Swift.Optional<devirt_try_apply.A>
}
sil_vtable D3 {
#D1.f1!1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A// devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A
}
sil_vtable Base {
#Base.foo!1: @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_
#Base.boo1!1: @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_
#Base.boo2!1: @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__
#Base.deinit!deallocator.1: @_TFC16devirt_try_apply4BaseD
#Base.init!initializer.1: @_TFC16devirt_try_apply4BasecfMS0_FT_S0_
}
sil_vtable Derived1 {
#Base.foo!1: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_
#Base.boo1!1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_
#Base.boo2!1: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__
#Base.init!initializer.1: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_
#Derived1.deinit!deallocator.1: @_TFC16devirt_try_apply8Derived1D
}
sil_vtable Derived2 {
#Base.foo!1: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32
#Base.boo1!1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_
#Base.boo2!1: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_
#Base.init!initializer.1: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_
#Derived2.deinit!deallocator.1: @_TFC16devirt_try_apply8Derived2D
}
sil_vtable CP1 {
#CP1.foo!1: @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32
#CP1.deinit!deallocator.1: @_TFC16devirt_try_apply3CP1D
#CP1.init!initializer.1: @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_
}
sil_vtable CP2 {
#CP1.foo!1: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32
#CP1.init!initializer.1: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_
#CP2.deinit!deallocator.1: @_TFC16devirt_try_apply3CP2D
}
sil_witness_table CP1: P module devirt_try_apply {
method #P.foo!1: @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32
}