blob: cc530a3167dee8693b9d00bd90890823a8ea4646 [file] [log] [blame]
// RUN: %target-sil-opt -enforce-exclusivity=none -enable-sil-verify-all -sroa-bb-args %s | %FileCheck %s
// Declare this SIL to be canonical because some tests break raw SIL
// conventions. e.g. address-type block args. -enforce-exclusivity=none is also
// required to allow address-type block args in canonical SIL.
sil_stage canonical
import Builtin
///////////
// Types //
///////////
enum FakeOptional<T> {
case none
case some(T)
}
struct S1 {
var x : Builtin.Int1
var y : Builtin.Int32
var z : Builtin.Int64
}
struct S1_B {
var x : Builtin.Int1
var y : Builtin.NativeObject
var z : Builtin.Int64
}
struct S1_C {
var x : Builtin.Int1
var y : Builtin.NativeObject
var z : Builtin.NativeObject
}
struct S2 {
var s1 : S1_B
var s2 : (Builtin.NativeObject, Builtin.NativeObject)
var s5 : FakeOptional<(Builtin.Int32, Builtin.Int64)>
}
struct S3 {
var s1 : S2
var s2 : S2
var s3 : Builtin.NativeObject
var s4 : S2
var s5 : FakeOptional<S2>
}
///////////
// Tests //
///////////
// CHECK-LABEL: sil @do_not_split_struct_with_only_trivial_fields : $@convention(thin) (Builtin.NativeObject, S1, Builtin.NativeObject, @in S1, Builtin.NativeObject) -> Builtin.Int32 {
// CHECK: bb2({{.*}} : $Builtin.NativeObject, {{.*}} : $S1, {{.*}} : $Builtin.NativeObject, {{.*}} : $*S1, {{.*}} : $Builtin.NativeObject):
sil @do_not_split_struct_with_only_trivial_fields : $@convention(thin) (Builtin.NativeObject, S1, Builtin.NativeObject, @in S1, Builtin.NativeObject) -> Builtin.Int32 {
bb0(%0 : $Builtin.NativeObject, %1 : $S1, %2 : $Builtin.NativeObject, %3 : $*S1, %4 : $Builtin.NativeObject):
cond_br undef, bb1, bb2(%0 : $Builtin.NativeObject, %1 : $S1, %2 : $Builtin.NativeObject, %3 : $*S1, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1, %2 : $Builtin.NativeObject, %3 : $*S1, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1, %7 : $Builtin.NativeObject, %8 : $*S1, %9 : $Builtin.NativeObject):
%10 = struct_extract %6 : $S1, #S1.y
return %10 : $Builtin.Int32
}
// CHECK-LABEL: sil @do_not_split_struct_with_only_one_non_trivial_field : $@convention(thin) (Builtin.NativeObject, S1_B, Builtin.NativeObject, @in S1_B, Builtin.NativeObject) -> Builtin.NativeObject {
// CHECK: bb2({{.*}} : $Builtin.NativeObject, {{.*}} : $S1_B, {{.*}} : $Builtin.NativeObject, {{.*}} : $*S1_B, {{.*}} : $Builtin.NativeObject):
sil @do_not_split_struct_with_only_one_non_trivial_field : $@convention(thin) (Builtin.NativeObject, S1_B, Builtin.NativeObject, @in S1_B, Builtin.NativeObject) -> Builtin.NativeObject {
bb0(%0 : $Builtin.NativeObject, %1 : $S1_B, %2 : $Builtin.NativeObject, %3 : $*S1_B, %4 : $Builtin.NativeObject):
cond_br undef, bb1, bb2(%0 : $Builtin.NativeObject, %1 : $S1_B, %2 : $Builtin.NativeObject, %3 : $*S1_B, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1_B, %2 : $Builtin.NativeObject, %3 : $*S1_B, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1_B, %7 : $Builtin.NativeObject, %8 : $*S1_B, %9 : $Builtin.NativeObject):
%10 = struct_extract %6 : $S1_B, #S1_B.y
return %10 : $Builtin.NativeObject
}
// CHECK-LABEL: sil @split_struct_with_multiple_non_trivial_fields : $@convention(thin) (Builtin.NativeObject, S1_C, Builtin.NativeObject, @in S1_C, Builtin.NativeObject) -> (Builtin.NativeObject, Builtin.NativeObject) {
// CHECK: bb2({{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $*S1_C, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject):
sil @split_struct_with_multiple_non_trivial_fields : $@convention(thin) (Builtin.NativeObject, S1_C, Builtin.NativeObject, @in S1_C, Builtin.NativeObject) -> (Builtin.NativeObject, Builtin.NativeObject) {
bb0(%0 : $Builtin.NativeObject, %1 : $S1_C, %2 : $Builtin.NativeObject, %3 : $*S1_C, %4 : $Builtin.NativeObject):
cond_br undef, bb1, bb2(%0 : $Builtin.NativeObject, %1 : $S1_C, %2 : $Builtin.NativeObject, %3 : $*S1_C, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1_C, %2 : $Builtin.NativeObject, %3 : $*S1_C, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1_C, %7 : $Builtin.NativeObject, %8 : $*S1_C, %9 : $Builtin.NativeObject):
%10 = struct_extract %6 : $S1_C, #S1_C.y
%11 = struct_extract %6 : $S1_C, #S1_C.z
%12 = tuple(%10 : $Builtin.NativeObject, %11 : $Builtin.NativeObject)
return %12 : $(Builtin.NativeObject, Builtin.NativeObject)
}
// Make sure our rules apply nicely at multiple levels. We split S2 into an S1_B and a native object
// CHECK-LABEL: sil @two_level_struct_with_differing_levels_of_splitting : $@convention(thin) (Builtin.NativeObject, S2, Builtin.NativeObject, @in S2, Builtin.NativeObject) -> (Builtin.Int1, Builtin.NativeObject) {
// CHECK: bb2({{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $*S2, {{.*}} : $Builtin.NativeObject, {{.*}} : $S1_B, {{.*}} : $Builtin.NativeObject):
sil @two_level_struct_with_differing_levels_of_splitting : $@convention(thin) (Builtin.NativeObject, S2, Builtin.NativeObject, @in S2, Builtin.NativeObject) -> (Builtin.Int1, Builtin.NativeObject) {
bb0(%0 : $Builtin.NativeObject, %1 : $S2, %2 : $Builtin.NativeObject, %3 : $*S2, %4 : $Builtin.NativeObject):
cond_br undef, bb1, bb2(%0 : $Builtin.NativeObject, %1 : $S2, %2 : $Builtin.NativeObject, %3 : $*S2, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S2, %2 : $Builtin.NativeObject, %3 : $*S2, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S2, %7 : $Builtin.NativeObject, %8 : $*S2, %9 : $Builtin.NativeObject):
%10 = struct_extract %6 : $S2, #S2.s2
%11 = tuple_extract %10 : $(Builtin.NativeObject, Builtin.NativeObject), 1
%12 = struct_extract %6 : $S2, #S2.s1
%13 = struct_extract %12 : $S1_B, #S1_B.x
%14 = tuple(%13 : $Builtin.Int1, %11 : $Builtin.NativeObject)
return %14 : $(Builtin.Int1, Builtin.NativeObject)
}
// CHECK-LABEL: sil @large_struct_split : $@convention(thin) (Builtin.NativeObject, S3, Builtin.NativeObject, @in S3, Builtin.NativeObject) -> S3 {
// CHECK: bb2({{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $*S3, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $FakeOptional<S2>, {{.*}} : $S1_B, {{.*}} : $FakeOptional<(Builtin.Int32, Builtin.Int64)>, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $S1_B, {{.*}} : $FakeOptional<(Builtin.Int32, Builtin.Int64)>, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject, {{.*}} : $S1_B, {{.*}} : $FakeOptional<(Builtin.Int32, Builtin.Int64)>, {{.*}} : $Builtin.NativeObject, {{.*}} : $Builtin.NativeObject):
sil @large_struct_split : $@convention(thin) (Builtin.NativeObject, S3, Builtin.NativeObject, @in S3, Builtin.NativeObject) -> S3 {
bb0(%0 : $Builtin.NativeObject, %1 : $S3, %2 : $Builtin.NativeObject, %3 : $*S3, %4 : $Builtin.NativeObject):
cond_br undef, bb1, bb2(%0 : $Builtin.NativeObject, %1 : $S3, %2 : $Builtin.NativeObject, %3 : $*S3, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S3, %2 : $Builtin.NativeObject, %3 : $*S3, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S3, %7 : $Builtin.NativeObject, %8 : $*S3, %9 : $Builtin.NativeObject):
return %6 : $S3
}
sil @bb_arg_dont_process_switch_enum : $@convention(thin) (FakeOptional<S1>) -> () {
bb0(%0 : $FakeOptional<S1>):
switch_enum %0 : $FakeOptional<S1>, case #FakeOptional.none!enumelt: bb2, case #FakeOptional.some!enumelt.1: bb1
bb1(%1 : $S1):
unreachable
bb2:
%9999 = tuple()
return %9999 : $()
}