| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -enable-expand-all %s -lower-aggregate-instrs | %FileCheck %s |
| |
| // This file makes sure that the mechanics of expanding aggregate instructions |
| // work. With that in mind, we expand all structs here ignoring code-size |
| // trade-offs. |
| |
| sil_stage canonical |
| |
| import Swift |
| import Builtin |
| |
| class C1 { |
| var data : Builtin.Int64 |
| init() |
| } |
| |
| class C2 { |
| var data : Builtin.FPIEEE32 |
| init() |
| } |
| |
| class C3 { |
| var data : Builtin.FPIEEE64 |
| init() |
| } |
| |
| struct S2 { |
| var cls1 : C1 |
| var cls2 : C2 |
| var trivial : Builtin.FPIEEE32 |
| } |
| |
| struct S { |
| var trivial : Builtin.Int64 |
| var cls : C3 |
| var inner_struct : S2 |
| } |
| |
| enum E { |
| case NoElement() |
| case TrivialElement(Builtin.Int64) |
| case ReferenceElement(C1) |
| case StructNonTrivialElt(S) |
| case TupleNonTrivialElt((Builtin.Int64, S, C3)) |
| } |
| |
| // A struct for testing that aggregate rebuilding works. |
| struct S3 { |
| var trivial1 : Builtin.Int64 |
| var cls : S |
| var trivial2 : Builtin.Int64 |
| var e : E |
| var trivial3 : Builtin.Int64 |
| } |
| |
| ////////////////// |
| // Destroy Addr // |
| ////////////////// |
| |
| // CHECK-LABEL: sil @expand_destroy_addr_trivial |
| // CHECK: bb0 |
| // CHECK: tuple () |
| // CHECK: return |
| sil @expand_destroy_addr_trivial : $@convention(thin) (@inout Builtin.Int64) -> () { |
| bb0(%0 : $*Builtin.Int64): |
| destroy_addr %0 : $*Builtin.Int64 |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_destroy_addr_aggstructnontrivial |
| // CHECK: bb0([[INPTR:%[0-9]+]] : $*S): |
| // CHECK: [[IN:%[0-9]+]] = load [[INPTR]] : $*S |
| // CHECK: [[cls:%[0-9]+]] = struct_extract [[IN]] : $S, #S.cls |
| // CHECK: strong_release [[cls]] : $C3 |
| // CHECK: [[innerstruct:%[0-9]+]] = struct_extract [[IN]] : $S, #S.inner_struct |
| // CHECK: [[innerstruct_cls1:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[innerstruct_cls1]] : $C1 |
| // CHECK: [[innerstruct_cls2:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[innerstruct_cls2]] : $C2 |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_destroy_addr_aggstructnontrivial : $@convention(thin) (@inout S) -> () { |
| bb0(%0 : $*S): |
| destroy_addr %0 : $*S |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_destroy_addr_aggtuplenontrivial |
| // CHECK: bb0([[INPTR:%[0-9]+]] : $*(S, S2, C1)): |
| // CHECK: [[IN:%[0-9]+]] = load [[INPTR]] : $*(S, S2, C1) |
| // CHECK: [[ELT0:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1), 0 |
| // CHECK: [[ELT0cls:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.cls |
| // CHECK: strong_release [[ELT0cls]] : $C3 |
| // CHECK: [[ELT0innerstruct:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.inner_struct |
| // CHECK: [[ELT0innerstructcls1:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[ELT0innerstructcls1]] : $C1 |
| // CHECK: [[ELT0innerstructcls2:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[ELT0innerstructcls2]] |
| // CHECK: [[ELT1:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1), 1 |
| // CHECK: [[ELT1cls1:%[0-9]+]] = struct_extract [[ELT1]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[ELT1cls1]] : $C1 |
| // CHECK: [[ELT1cls2:%[0-9]+]] = struct_extract [[ELT1]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[ELT1cls2]] : $C2 |
| // CHECK: [[ELT2:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1), 2 |
| // CHECK: strong_release [[ELT2]] |
| // CHECK: tuple () |
| // CHECK: return |
| sil @expand_destroy_addr_aggtuplenontrivial : $@convention(thin) (@inout (S, S2, C1)) -> () { |
| bb0(%0 : $*(S, S2, C1)): |
| destroy_addr %0 : $*(S, S2, C1) |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // Do not do anything. |
| /* |
| sil @expand_destroy_addr_addressonly : $@convention(thin) <T> (@inout T) -> () { |
| bb0(%0 : $*T): |
| destroy_addr %0 : $*T |
| %1 = tuple() |
| return %1 : $() |
| } |
| */ |
| |
| // CHECK-LABEL: sil @expand_destroy_addr_reference |
| // CHECK: bb0 |
| // CHECK: load |
| // CHECK: strong_release |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_destroy_addr_reference : $@convention(thin) (@inout C1) -> () { |
| bb0(%0 : $*C1): |
| destroy_addr %0 : $*C1 |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_destroy_addr_enum |
| // CHECK: bb0 |
| // CHECK: load |
| // CHECK: release_value |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_destroy_addr_enum : $@convention(thin) (@inout E) -> () { |
| bb0(%0 : $*E): |
| destroy_addr %0 : $*E |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| /////////////// |
| // Copy Addr // |
| /////////////// |
| |
| // CHECK-LABEL: sil @expand_copy_addr_takeinit |
| // CHECK: bb0([[IN1:%[0-9]+]] : $*S, [[IN2:%[0-9]+]] : $*S): |
| // CHECK: [[LOAD1:%[0-9]+]] = load [[IN1]] : $*S |
| // CHECK: store [[LOAD1]] to [[IN2]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_takeinit : $@convention(thin) (@inout S, @inout S) -> () { |
| bb0(%0 : $*S, %1 : $*S): |
| copy_addr [take] %0 to [initialization] %1 : $*S |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_copy_addr_init |
| // CHECK: bb0([[IN1PTR:%[0-9]+]] : $*S, [[IN2PTR:%[0-9]+]] : $*S): |
| // CHECK: [[IN1:%[0-9]+]] = load [[IN1PTR]] : $*S |
| // CHECK: [[IN1trivial:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.trivial |
| // CHECK: [[IN1cls:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.cls |
| // CHECK: strong_retain [[IN1cls]] : $C3 |
| // CHECK: [[innerstruct:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.inner_struct |
| // CHECK: [[innerstructIN11:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[innerstructIN11]] : $C1 |
| // CHECK: [[innerstructIN12:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[innerstructIN12]] : $C2 |
| // CHECK: [[innerstructtrivial:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.trivial |
| // CHECK: store [[IN1]] to [[IN2PTR]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_init : $@convention(thin) (@inout S, @inout S) -> () { |
| bb0(%0 : $*S, %1 : $*S): |
| copy_addr %0 to [initialization] %1 : $*S |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_copy_addr_take |
| // CHECK: bb0([[IN1PTR:%[0-9]+]] : $*S, [[IN2PTR:%[0-9]+]] : $*S): |
| // CHECK: [[IN1:%[0-9]+]] = load [[IN1PTR]] : $*S |
| // CHECK: [[IN2:%[0-9]+]] = load [[IN2PTR]] : $*S |
| // CHECK: [[cls:%[0-9]+]] = struct_extract [[IN2]] : $S, #S.cls |
| // CHECK: strong_release [[cls]] : $C3 |
| // CHECK: [[innerstruct:%[0-9]+]] = struct_extract [[IN2]] : $S, #S.inner_struct |
| // CHECK: [[innerstructcls1:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[innerstructcls1]] : $C1 |
| // CHECK: [[innerstructcls2:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[innerstructcls2]] |
| // CHECK: store [[IN1]] to [[IN2PTR]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_take : $@convention(thin) (@inout S, @inout S) -> () { |
| bb0(%0 : $*S, %1 : $*S): |
| copy_addr [take] %0 to %1 : $*S |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // Test expansions for various types (these will become more |
| // interesting when I introduce the actual chopping work). |
| |
| // CHECK-LABEL: sil @expand_copy_addr_trivial |
| // CHECK: bb0 |
| // CHECK: load |
| // CHECK: store |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_trivial : $@convention(thin) (@inout Builtin.Int64, @inout Builtin.Int64) -> () { |
| bb0(%0 : $*Builtin.Int64, %1 : $*Builtin.Int64): |
| copy_addr %0 to %1 : $*Builtin.Int64 |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_copy_addr_aggstructnontrivial |
| // CHECK: bb0([[IN1PTR:%[0-9]+]] : $*S, [[IN2PTR:%[0-9]+]] : $*S): |
| // CHECK: [[IN1:%[0-9]+]] = load [[IN1PTR]] : $*S |
| // CHECK: [[IN2:%[0-9]+]] = load [[IN2PTR]] : $*S |
| // CHECK: [[IN1trivial:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.trivial |
| // CHECK: [[IN1cls:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.cls |
| // CHECK: strong_retain [[IN1cls]] : $C3 |
| // CHECK: [[IN1innerstruct:%[0-9]+]] = struct_extract [[IN1]] : $S, #S.inner_struct |
| // CHECK: [[IN1innerstructcls1:%[0-9]+]] = struct_extract [[IN1innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[IN1innerstructcls1]] : $C1 |
| // CHECK: [[IN1innerstructcls2:%[0-9]+]] = struct_extract [[IN1innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[IN1innerstructcls2]] : $C2 |
| // CHECK: [[IN1innerstructtrivial:%[0-9]+]] = struct_extract [[IN1innerstruct]] : $S2, #S2.trivial |
| // CHECK: [[IN2cls:%[0-9]+]] = struct_extract [[IN2]] : $S, #S.cls |
| // CHECK: strong_release [[IN2cls]] : $C3 |
| // CHECK: [[IN2innerstruct:%[0-9]+]] = struct_extract [[IN2]] : $S, #S.inner_struct |
| // CHECK: [[IN2innerstructcls1:%[0-9]+]] = struct_extract [[IN2innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[IN2innerstructcls1]] : $C1 |
| // CHECK: [[IN2innerstructcls2:%[0-9]+]] = struct_extract [[IN2innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[IN2innerstructcls2]] |
| // CHECK: store [[IN1]] to [[IN2PTR]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_aggstructnontrivial : $@convention(thin) (@inout S, @inout S) -> () { |
| bb0(%0 : $*S, %1 : $*S): |
| copy_addr %0 to %1 : $*S |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_copy_addr_aggtuplenontrivial |
| // CHECK: bb0([[IN1PTR:%[0-9]+]] : $*(S, S2, C1, E), [[IN2PTR:%[0-9]+]] : $*(S, S2, C1, E)): |
| // CHECK: [[IN1:%[0-9]+]] = load [[IN1PTR]] : $*(S, S2, C1, E) |
| // CHECK: [[IN2:%[0-9]+]] = load [[IN2PTR]] : $*(S, S2, C1, E) |
| // CHECK: [[IN1ELT0:%[0-9]+]] = tuple_extract [[IN1]] : $(S, S2, C1, E), 0 |
| // CHECK: [[IN1ELT0trivial:%[0-9]+]] = struct_extract [[IN1ELT0]] : $S, #S.trivial |
| // CHECK: [[IN1ELT0cls:%[0-9]+]] = struct_extract [[IN1ELT0]] : $S, #S.cls |
| // CHECK: strong_retain [[IN1ELT0cls]] : $C3 |
| // CHECK: [[IN1ELT0innerstruct:%[0-9]+]] = struct_extract [[IN1ELT0]] : $S, #S.inner_struct |
| // CHECK: [[IN1ELT0innerstructcls1:%[0-9]+]] = struct_extract [[IN1ELT0innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[IN1ELT0innerstructcls1]] : $C1 |
| // CHECK: [[IN1ELT0innerstructcls2:%[0-9]+]] = struct_extract [[IN1ELT0innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[IN1ELT0innerstructcls2]] |
| // CHECK: [[IN1ELT0innerstructtrivial:%[0-9]+]] = struct_extract [[IN1ELT0innerstruct]] : $S2, #S2.trivial |
| // CHECK: [[IN1ELT1:%[0-9]+]] = tuple_extract [[IN1]] : $(S, S2, C1, E), 1 |
| // CHECK: [[IN1ELT1cls1:%[0-9]+]] = struct_extract [[IN1ELT1]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[IN1ELT1cls1]] : $C1 |
| // CHECK: [[IN1ELT1cls2:%[0-9]+]] = struct_extract [[IN1ELT1]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[IN1ELT1cls2]] : $C2 |
| // CHECK: [[IN1ELT1trivial:%[0-9]+]] = struct_extract [[IN1ELT1]] : $S2, #S2.trivial |
| // CHECK: [[IN1ELT2:%[0-9]+]] = tuple_extract [[IN1]] : $(S, S2, C1, E), 2 |
| // CHECK: strong_retain [[IN1ELT2]] |
| // CHECK: [[IN1ELT3:%[0-9]+]] = tuple_extract [[IN1]] : $(S, S2, C1, E), 3 |
| // CHECK: retain_value [[IN1ELT3]] : $E |
| // CHECK: [[IN2ELT0:%[0-9]+]] = tuple_extract [[IN2]] : $(S, S2, C1, E), 0 |
| // CHECK: [[IN2ELT0cls:%[0-9]+]] = struct_extract [[IN2ELT0]] : $S, #S.cls |
| // CHECK: strong_release [[IN2ELT0cls]] : $C3 |
| // CHECK: [[IN2ELT0innerstruct:%[0-9]+]] = struct_extract [[IN2ELT0]] : $S, #S.inner_struct |
| // CHECK: [[IN2ELT0innerstructcls1:%[0-9]+]] = struct_extract [[IN2ELT0innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[IN2ELT0innerstructcls1]] : $C1 |
| // CHECK: [[IN2ELT0innerstructcls2:%[0-9]+]] = struct_extract [[IN2ELT0innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[IN2ELT0innerstructcls2]] |
| // CHECK: [[IN2ELT1:%[0-9]+]] = tuple_extract [[IN2]] : $(S, S2, C1, E), 1 |
| // CHECK: [[IN2ELT1cls1:%[0-9]+]] = struct_extract [[IN2ELT1]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[IN2ELT1cls1]] : $C1 |
| // CHECK: [[IN2ELT1cls2:%[0-9]+]] = struct_extract [[IN2ELT1]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[IN2ELT1cls2]] : $C2 |
| // CHECK: [[IN2ELT2:%[0-9]+]] = tuple_extract [[IN2]] : $(S, S2, C1, E), 2 |
| // CHECK: strong_release [[IN2ELT2]] |
| // CHECK: [[IN2ELT3:%[0-9]+]] = tuple_extract [[IN2]] : $(S, S2, C1, E), 3 |
| // CHECK: release_value [[IN2ELT3]] : $E |
| // CHECK: store [[IN1]] to [[IN2PTR]] : $*(S, S2, C1, E) |
| // CHECK: tuple () |
| // CHECK: return |
| |
| |
| sil @expand_copy_addr_aggtuplenontrivial : $@convention(thin) (@inout (S, S2, C1, E), @inout (S, S2, C1, E)) -> () { |
| bb0(%0 : $*(S, S2, C1, E), %1 : $*(S, S2, C1, E)): |
| copy_addr %0 to %1 : $*(S, S2, C1, E) |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // Do not do anything. |
| /* |
| sil @expand_copy_addr_addressonly : $@convention(thin) <T> (@inout T) -> () { |
| bb0(%0 : $*T): |
| copy_addr %0 : $*T |
| %1 = tuple() |
| return %1 : $() |
| } |
| */ |
| |
| // Just turn into a load + strong_release. |
| // CHECK-LABEL: sil @expand_copy_addr_reference |
| // CHECK: bb0([[IN1:%[0-9]+]] : $*C1, [[IN2:%[0-9]+]] : $*C1): |
| // CHECK: [[LOAD1:%[0-9]+]] = load [[IN1]] : $*C1 |
| // CHECK: [[LOAD2:%[0-9]+]] = load [[IN2]] : $*C1 |
| // CHECK: strong_retain [[LOAD1]] |
| // CHECK: strong_release [[LOAD2]] |
| // CHECK: store [[LOAD1]] to [[IN2]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_reference : $@convention(thin) (@inout C1, @inout C1) -> () { |
| bb0(%0 : $*C1, %1 : $*C1): |
| copy_addr %0 to %1 : $*C1 |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_copy_addr_enum |
| // CHECK: bb0([[IN1:%[0-9]+]] : $*E, [[IN2:%[0-9]+]] : $*E): |
| // CHECK: [[LOAD1:%[0-9]+]] = load [[IN1]] : $*E |
| // CHECK: [[LOAD2:%[0-9]+]] = load [[IN2]] : $*E |
| // CHECK: retain_value [[LOAD1]] |
| // CHECK: release_value [[LOAD2]] |
| // CHECK: store [[LOAD1]] to [[IN2]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_copy_addr_enum : $@convention(thin) (@inout E, @inout E) -> () { |
| bb0(%0 : $*E, %1 : $*E): |
| copy_addr %0 to %1 : $*E |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| /////////////////// |
| // Destroy Value // |
| /////////////////// |
| |
| // Test expansions for various types (these will become more |
| // interesting when I introduce the actual chopping work). |
| |
| // CHECK-LABEL: sil @expand_release_value_trivial |
| // CHECK: bb0 |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_release_value_trivial : $@convention(thin) (Builtin.Int64) -> () { |
| bb0(%0 : $Builtin.Int64): |
| release_value %0 : $Builtin.Int64 |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_release_value_aggstructnontrivial |
| // CHECK: bb0([[IN:%[0-9]+]] : $S): |
| // CHECK: [[cls:%[0-9]+]] = struct_extract [[IN]] : $S, #S.cls |
| // CHECK: strong_release [[cls]] : $C3 |
| // CHECK: [[innerstruct:%[0-9]+]] = struct_extract [[IN]] : $S, #S.inner_struct |
| // CHECK: [[innerstructcls1:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[innerstructcls1]] : $C1 |
| // CHECK: [[innerstructcls2:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[innerstructcls2]] |
| sil @expand_release_value_aggstructnontrivial : $@convention(thin) (S) -> () { |
| bb0(%0 : $S): |
| release_value %0 : $S |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_release_value_aggtuplenontrivial |
| // CHECK: bb0([[IN:%[0-9]+]] : $(S, S2, C1, E)): |
| // CHECK: [[ELT0:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1, E), 0 |
| // CHECK: [[ELT0cls:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.cls |
| // CHECK: strong_release [[ELT0cls]] : $C3 |
| // CHECK: [[ELT0innerstruct:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.inner_struct |
| // CHECK: [[ELT0innerstructcls1:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[ELT0innerstructcls1]] : $C1 |
| // CHECK: [[ELT0innerstructcls2:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[ELT0innerstructcls2]] |
| // CHECK: [[ELT1:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1, E), 1 |
| // CHECK: [[ELT1cls1:%[0-9]+]] = struct_extract [[ELT1]] : $S2, #S2.cls1 |
| // CHECK: strong_release [[ELT1cls1]] : $C1 |
| // CHECK: [[ELT1cls2:%[0-9]+]] = struct_extract [[ELT1]] : $S2, #S2.cls2 |
| // CHECK: strong_release [[ELT1cls2]] : $C2 |
| // CHECK: [[ELT2:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1, E), 2 |
| // CHECK: strong_release [[ELT2]] |
| // CHECK: [[ELT3:%[0-9]+]] = tuple_extract [[IN]] : $(S, S2, C1, E), 3 |
| // CHECK: release_value [[ELT3]] : $E |
| // CHECK: tuple () |
| // CHECK: return |
| sil @expand_release_value_aggtuplenontrivial : $@convention(thin) ((S, S2, C1, E)) -> () { |
| bb0(%0 : $(S, S2, C1, E)): |
| release_value %0 : $(S, S2, C1, E) |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // Just turn into a load + strong_release. |
| // CHECK-LABEL: sil @expand_release_value_reference |
| // CHECK: bb0([[IN:%[0-9]+]] : $C1): |
| // CHECK: strong_release [[IN]] |
| // CHECK: tuple |
| // CHECK: return |
| sil @expand_release_value_reference : $@convention(thin) (C1) -> () { |
| bb0(%0 : $C1): |
| release_value %0 : $C1 |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| // CHECK-LABEL: sil @expand_release_value_enum |
| // CHECK: bb0([[IN1:%[0-9]+]] : $E): |
| // CHECK: release_value |
| // CHECK: tuple () |
| // CHECK: return |
| sil @expand_release_value_enum : $@convention(thin) (E) -> () { |
| bb0(%0 : $E): |
| release_value %0 : $E |
| %1 = tuple() |
| return %1 : $() |
| } |
| |
| |
| //////////////// |
| // Copy Value // |
| //////////////// |
| |
| // Test expansions for various types (these will become more |
| // interesting when I introduce the actual chopping work). |
| |
| // CHECK-LABEL: sil @expand_retain_value_trivial |
| // CHECK: bb0 |
| // CHECK: return |
| sil @expand_retain_value_trivial : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64) { |
| bb0(%0 : $Builtin.Int64): |
| retain_value %0 : $Builtin.Int64 |
| return %0 : $Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: sil @expand_retain_value_aggstructnontrivial |
| // CHECK: bb0([[IN:%[0-9]+]] : $S3): |
| // CHECK: [[trivial:%[0-9]+]] = struct_extract [[IN]] : $S3, #S3.trivial1 |
| // CHECK: [[cls:%[0-9]+]] = struct_extract [[IN]] : $S3, #S3.cls |
| // CHECK: [[clstrivial:%[0-9]+]] = struct_extract [[cls]] : $S, #S.trivial |
| // CHECK: [[clscls:%[0-9]+]] = struct_extract [[cls]] : $S, #S.cls |
| // CHECK: strong_retain [[clscls]] : $C3 |
| // CHECK: [[innerstruct:%[0-9]+]] = struct_extract [[cls]] : $S, #S.inner_struct |
| // CHECK: [[innerstructcls1:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[innerstructcls1]] : $C1 |
| // CHECK: [[innerstructcls2:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[innerstructcls2]] : $C2 |
| // CHECK: [[innerstructtrivial:%[0-9]+]] = struct_extract [[innerstruct]] : $S2, #S2.trivial |
| // CHECK: [[trivial2:%[0-9]+]] = struct_extract [[IN]] : $S3, #S3.trivial2 |
| // CHECK: [[enum:%[0-9]+]] = struct_extract [[IN]] : $S3, #S3.e |
| // CHECK: retain_value [[enum]] : $E |
| // CHECK: [[trivial3:%[0-9]+]] = struct_extract [[IN]] : $S3, #S3.trivial3 |
| // CHECK: return [[IN]] : $S3 |
| sil @expand_retain_value_aggstructnontrivial : $@convention(thin) (S3) -> (S3) { |
| bb0(%0 : $S3): |
| retain_value %0 : $S3 |
| return %0 : $S3 |
| } |
| |
| // CHECK-LABEL: sil @expand_retain_value_aggtuplenontrivial |
| // CHECK: bb0([[IN:%[0-9]+]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)): |
| // CHECK: [[ELT0:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 0 |
| // CHECK: [[ELT0trivial:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.trivial |
| // CHECK: [[ELT0cls:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.cls |
| // CHECK: strong_retain [[ELT0cls]] : $C3 |
| // CHECK: [[ELT0innerstruct:%[0-9]+]] = struct_extract [[ELT0]] : $S, #S.inner_struct |
| // CHECK: [[ELT0innerstructcls1:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[ELT0innerstructcls1]] : $C1 |
| // CHECK: [[ELT0innerstructcls2:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[ELT0innerstructcls2]] |
| // CHECK: [[ELT0innerstructtrivial:%[0-9]+]] = struct_extract [[ELT0innerstruct]] : $S2, #S2.trivial |
| // CHECK: [[ELT1:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 1 |
| // CHECK: [[ELT2:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 2 |
| // CHECK: [[ELT2cls1:%[0-9]+]] = struct_extract [[ELT2]] : $S2, #S2.cls1 |
| // CHECK: strong_retain [[ELT2cls1]] : $C1 |
| // CHECK: [[ELT2cls2:%[0-9]+]] = struct_extract [[ELT2]] : $S2, #S2.cls2 |
| // CHECK: strong_retain [[ELT2cls2]] : $C2 |
| // CHECK: [[ELT2trivial:%[0-9]+]] = struct_extract [[ELT2]] : $S2, #S2.trivial |
| // CHECK: [[ELT3:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 3 |
| // CHECK: strong_retain [[ELT3]] |
| // CHECK: [[ELT4:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 4 |
| // CHECK: [[ELT5:%[0-9]+]] = tuple_extract [[IN]] : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E), 5 |
| // CHECK: retain_value [[ELT5]] : $E |
| // CHECK: return [[IN]] |
| |
| sil @expand_retain_value_aggtuplenontrivial : $@convention(thin) ((S, Builtin.Int64, S2, C1, Builtin.Int64, E)) -> ((S, Builtin.Int64, S2, C1, Builtin.Int64, E)) { |
| bb0(%0 : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)): |
| retain_value %0 : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E) |
| return %0 : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E) |
| } |
| |
| // CHECK-LABEL: sil @expand_retain_value_reference |
| // CHECK: bb0([[IN:%[0-9]+]] : $C1): |
| // CHECK: strong_retain [[IN]] |
| // CHECK: return |
| sil @expand_retain_value_reference : $@convention(thin) (C1) -> (C1) { |
| bb0(%0 : $C1): |
| retain_value %0 : $C1 |
| return %0 : $C1 |
| } |
| |
| // CHECK-LABEL: sil @expand_retain_value_enum |
| // CHECK: bb0([[IN1:%[0-9]+]] : $E): |
| // CHECK: retain_value |
| // CHECK: return |
| sil @expand_retain_value_enum : $@convention(thin) (E) -> (E) { |
| bb0(%0 : $E): |
| retain_value %0 : $E |
| return %0 : $E |
| } |
| |