blob: 390b6ab8ebd66bb460dc097c64255a5582886000 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -jumpthread-simplify-cfg | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
// CHECK-LABEL: sil @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
// CHECK: init_existential_addr
// CHECK: inject_enum_addr
// CHECK-NOT: select_enum_addr
// CHECK-NOT: bb1
// CHECK: unchecked_take_enum_data_addr
// CHECK: return
sil @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
bb0(%0 : $*Int, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $Int
%6 = load %0 : $*Int
store %6 to %5 : $*Int
unconditional_checked_cast_addr Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
dealloc_stack %5 : $*Int
%11 = integer_literal $Builtin.Int1, -1
%12 = integer_literal $Builtin.Int1, 0
%13 = select_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: %11, case #Optional.none!enumelt: %12 : $Builtin.Int1
cond_br %13, bb2, bb1
bb1:
%15 = tuple ()
dealloc_stack %3 : $*Optional<CustomStringConvertible>
dealloc_stack %2 : $*CustomStringConvertible
return %15 : $()
bb2:
%19 = unchecked_take_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
copy_addr [take] %19 to [initialization] %2 : $*CustomStringConvertible
br bb1
}
// CHECK-LABEL: sil @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
// CHECK: init_existential_addr
// CHECK: inject_enum_addr
// CHECK-NOT: switch_enum_addr
// CHECK-NOT: bb1
// CHECK: unchecked_take_enum_data_addr
// CHECK: return
sil @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
bb0(%0 : $*Int, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $Int
%6 = load %0 : $*Int
store %6 to %5 : $*Int
unconditional_checked_cast_addr Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
dealloc_stack %5 : $*Int
switch_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2
bb1:
%15 = tuple ()
dealloc_stack %3 : $*Optional<CustomStringConvertible>
dealloc_stack %2 : $*CustomStringConvertible
return %15 : $()
bb2:
br bb1
bb3:
%19 = unchecked_take_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
copy_addr [take] %19 to [initialization] %2 : $*CustomStringConvertible
br bb1
}
// Check that a checked_cast_addr_br converting a known type into a protocol type
// is performed at the compile-time if protocol conformances are statically known.
//
// CHECK-LABEL: sil @convert_checked_cast_addr_br_into_unconditional_checked_cast_addr_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
// CHECK: store
// CHECK-NOT: checked_cast_addr_br
// CHECK-NOT: bb1
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
// CHECK: dealloc_stack
// CHECK: return
sil @convert_checked_cast_addr_br_into_unconditional_checked_cast_addr_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
bb0(%0 : $*Int, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $Int
%6 = load %0 : $*Int
store %6 to %5 : $*Int
checked_cast_addr_br take_always Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
bb1:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
br bb2
bb2:
dealloc_stack %5 : $*Int
dealloc_stack %3 : $*Optional<CustomStringConvertible>
%12 = integer_literal $Builtin.Int1, -1
%13 = integer_literal $Builtin.Int1, 0
%26 = tuple ()
dealloc_stack %2 : $*CustomStringConvertible
return %26 : $()
bb22:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
br bb2
}
class A {
}
private final class B {
}
public class C {
}
// D cannot be extended elsewhere, but C can!
private class D : C {
}
// Check that a checked_cast_addr_br converting a known type into a protocol type
// is performed at the compile-time if protocol conformances are statically known.
// In a negative case, take care that check for internal types are not folded (unless
// a whole module optimization is used), because an extension implementing a conformance
// could be defined elsewhere.
//
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> ()
// CHECK: checked_cast_addr_br
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
// CHECK: dealloc_stack
// CHECK: return
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
// CHECK: }
sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> () {
bb0(%0 : $*A, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $A
%6 = load %0 : $*A
store %6 to %5 : $*A
checked_cast_addr_br take_always A in %5 : $*A to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
bb1:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
br bb2
bb2:
dealloc_stack %5 : $*A
dealloc_stack %3 : $*Optional<CustomStringConvertible>
%12 = integer_literal $Builtin.Int1, -1
%13 = integer_literal $Builtin.Int1, 0
%26 = tuple ()
dealloc_stack %2 : $*CustomStringConvertible
return %26 : $()
bb22:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
br bb2
}
// Check that a checked_cast_addr_br converting a known type into a protocol type
// is performed at the compile-time if protocol conformances are statically known.
// In a negative case, if the source type is private, it is safe to fold the check,
// because a conformance for this type cannot be defined elsewhere.
//
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_private_type : $@convention(thin) (@in B, @inout _Stdout) -> ()
// CHECK: store
// CHECK-NOT: checked_cast_addr_br
// CHECK-NOT: bb1
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
// CHECK: dealloc_stack
// CHECK: return
sil @convert_checked_cast_addr_br_with_private_type : $@convention(thin) (@in B, @inout _Stdout) -> () {
bb0(%0 : $*B, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $B
%6 = load %0 : $*B
store %6 to %5 : $*B
checked_cast_addr_br take_always B in %5 : $*B to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
bb1:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
br bb2
bb2:
dealloc_stack %5 : $*B
dealloc_stack %3 : $*Optional<CustomStringConvertible>
%12 = integer_literal $Builtin.Int1, -1
%13 = integer_literal $Builtin.Int1, 0
%26 = tuple ()
dealloc_stack %2 : $*CustomStringConvertible
return %26 : $()
bb22:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
br bb2
}
// Check that a checked_cast_addr_br converting a known type into a protocol type
// is performed at the compile-time if protocol conformances are statically known.
// In a negative case, take care that cast for private types are not folded if one
// of its superclasses could have a conformance extension defined elsewhere.
//
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> ()
// CHECK: checked_cast_addr_br
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
// CHECK: dealloc_stack
// CHECK: return
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
// CHECK: }
sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> () {
bb0(%0 : $*D, %1 : $*_Stdout):
%2 = alloc_stack $CustomStringConvertible
%3 = alloc_stack $Optional<CustomStringConvertible>
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
%5 = alloc_stack $D
%6 = load %0 : $*D
store %6 to %5 : $*D
checked_cast_addr_br take_always D in %5 : $*D to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
bb1:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
br bb2
bb2:
dealloc_stack %5 : $*D
dealloc_stack %3 : $*Optional<CustomStringConvertible>
%12 = integer_literal $Builtin.Int1, -1
%13 = integer_literal $Builtin.Int1, 0
%26 = tuple ()
dealloc_stack %2 : $*CustomStringConvertible
return %26 : $()
bb22:
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
br bb2
}