blob: 08b3ac39313fb7d805d2ac4d3086e2cbf831de55 [file] [log] [blame]
// RUN: %target-sil-opt -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(Void)
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
}