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 141 142
|
// 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, {{.*}} : $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, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1, %2 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1, %7 : $Builtin.NativeObject, %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, {{.*}} : $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, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1_B, %2 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1_B, %7 : $Builtin.NativeObject, %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, {{.*}} : $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, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S1_C, %2 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S1_C, %7 : $Builtin.NativeObject, %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, {{.*}} : $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, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S2, %2 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S2, %7 : $Builtin.NativeObject, %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, {{.*}} : $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, %4 : $Builtin.NativeObject)
bb1:
br bb2(%0 : $Builtin.NativeObject, %1 : $S3, %2 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb2(%5 : $Builtin.NativeObject, %6 : $S3, %7 : $Builtin.NativeObject, %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: bb1
bb1(%1 : $S1):
unreachable
bb2:
%9999 = tuple()
return %9999 : $()
}
|