| // RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer -dce | %FileCheck %s |
| |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| |
| class Bar { |
| init() |
| func ping() |
| } |
| |
| class Foo : Bar { |
| override init() |
| override func ping() |
| } |
| |
| sil_global @x : $Bar |
| |
| // CHECK-LABEL: sil [ossa] @function_with_cm_with_cast |
| // CHECK: [[SELF:%.*]] = alloc_ref $Foo |
| // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] |
| // CHECK: [[CAST_1_SELF:%.*]] = upcast [[SELF_COPY]] |
| // CHECK: [[CAST_2_SELF:%.*]] = unconditional_checked_cast [[CAST_1_SELF]] |
| // CHECK: destroy_value [[SELF]] |
| // CHECK: [[CAST_3_SELF:%.*]] = upcast [[CAST_2_SELF]] |
| // CHECK-NOT: class_method |
| // CHECK: [[REF:%.*]] = function_ref @_TFC4main3Foo4pingfS0_FT_T_ |
| // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[CAST_3_SELF]] |
| // CHECK: [[SELF:%.*]] = unchecked_ref_cast [[BORROWED_SELF]] |
| // CHECK: apply [[REF]]([[SELF]]) |
| // CHECK: return |
| sil [ossa] @function_with_cm_with_cast : $@convention(thin) () -> () { |
| bb0: |
| %0 = global_addr @x : $*Bar // users: %7, %8 |
| %1 = alloc_ref $Foo // users: %5, %3, %2 |
| %2 = copy_value %1 : $Foo // id: %2 |
| %3 = upcast %2 : $Foo to $Bar // user: %4 |
| %4 = unconditional_checked_cast %3 : $Bar to $Foo // user: %6 |
| destroy_value %1 : $Foo // id: %5 |
| %6 = upcast %4 : $Foo to $Bar // user: %7 |
| %10 = class_method %6 : $Bar, #Bar.ping!1 : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %11 |
| %11 = apply %10(%6) : $@convention(method) (@guaranteed Bar) -> () |
| destroy_value %6 : $Bar |
| %12 = tuple () // user: %13 |
| return %12 : $() // id: %13 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @function_with_cm_with_dynamic_type_known_from_checked_cast_br : |
| // CHECK-NOT: class_method |
| // CHECK: bb4([[SELF:%.*]] : @owned $Bar): |
| // CHECK: [[REF:%.*]] = function_ref @_TFC4main3Bar4pingfS0_FT_T_ |
| // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]] |
| // CHECK: apply [[REF]]([[BORROWED_SELF]]) |
| // CHECK: } // end sil function 'function_with_cm_with_dynamic_type_known_from_checked_cast_br' |
| sil [ossa] @function_with_cm_with_dynamic_type_known_from_checked_cast_br : $@convention(thin) (@owned Bar) -> () { |
| bb0(%0 : @owned $Bar): |
| checked_cast_br [exact] %0 : $Bar to $Bar, bb1, bb5 |
| |
| bb1(%1 : @owned $Bar): |
| br bb2(%1 : $Bar) |
| |
| bb2(%2 : @owned $Bar): |
| br bb3(%2 : $Bar) |
| |
| bb3(%3 : @owned $Bar): |
| br bb4(%3 : $Bar) |
| |
| bb4(%4 : @owned $Bar): |
| // Devirtualizer should be able to figure out that the exact dynamic type of %1 is Bar. |
| %5 = class_method %4 : $Bar, #Bar.ping!1 : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () |
| %6 = apply %5(%4) : $@convention(method) (@guaranteed Bar) -> () |
| destroy_value %4 : $Bar |
| br bb6 |
| |
| bb5(%7 : @owned $Bar): |
| destroy_value %7 : $Bar |
| br bb6 |
| |
| bb6: |
| %8 = tuple () |
| return %8 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @function_with_cm_with_dynamic_type_known_from_incoming_bb_args : |
| // CHECK-NOT: class_method |
| // CHECK: bb3([[SELF:%.*]] : @owned $Bar): |
| // CHECK: [[REF:%.*]] = function_ref @_TFC4main3Bar4pingfS0_FT_T_ |
| // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]] |
| // CHECK: apply [[REF]]([[BORROWED_SELF]]) |
| // CHECK: } // end sil function 'function_with_cm_with_dynamic_type_known_from_incoming_bb_args' |
| sil [ossa] @function_with_cm_with_dynamic_type_known_from_incoming_bb_args : $@convention(thin) (Builtin.Int1) -> () { |
| bb0(%0 : $Builtin.Int1): |
| cond_br %0, bb1, bb2 |
| |
| bb1: |
| %1 = alloc_ref $Bar |
| br bb3(%1 : $Bar) |
| |
| bb2: |
| %2 = alloc_ref $Bar |
| br bb3(%2 : $Bar) |
| |
| bb3(%4 : @owned $Bar): |
| // Devirtualizer should be able to figure out that the exact dynamic type of %4 is Bar. |
| %5 = class_method %4 : $Bar, #Bar.ping!1 : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () |
| %6 = apply %5(%4) : $@convention(method) (@guaranteed Bar) -> () |
| br bb4 |
| |
| bb4: |
| destroy_value %4 : $Bar |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| |
| sil @_TFC4main3Bar4pingfS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> () |
| sil @_TFC4main3Foo4pingfS0_FT_T_ : $@convention(method) (@guaranteed Foo) -> () |
| |
| sil_vtable Bar { |
| #Bar.ping!1: @_TFC4main3Bar4pingfS0_FT_T_ |
| } |
| |
| sil_vtable Foo { |
| #Bar.ping!1: @_TFC4main3Foo4pingfS0_FT_T_ |
| } |
| |
| |
| |