blob: 7fe097b68a7e433450488f603fa99ace8eb169df [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all -enable-loop-arc=0 -arc-sequence-opts %s -module-name Swift | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all -enable-loop-arc=1 -arc-sequence-opts %s -module-name Swift | %FileCheck %s
sil_stage canonical
import Builtin
// Utilities
sil @user : $@convention(thin) (Builtin.NativeObject) -> ()
struct S {
var x : Builtin.NativeObject
}
sil @S_user : $@convention(thin) (S) -> ()
struct S2 {
var x : Builtin.Int32
var y : Builtin.NativeObject
var z : Builtin.Int32
}
struct S3 {
var x : Builtin.Int32
var y : Builtin.NativeObject
var y1 : Builtin.NativeObject
var z : Builtin.Int32
}
class Cls {
var random : Builtin.Int32
init()
}
public enum FakeOptional<T> {
case none
case some(T)
}
public typealias AnyObject = Builtin.AnyObject
class C {
init()
var w : FakeOptional<Builtin.NativeObject>
}
struct SContainer {
var c : Cls
var z : Builtin.Int32
init()
}
struct SContainer2 {
var b : Cls
var c : Cls
init()
}
class RetainUser { }
sil @rawpointer_use: $@convention(thin) (Builtin.RawPointer) -> ()
sil @fakeoptional_user : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> ()
sil @cls_use : $@convention(thin) (@owned Cls) -> ()
enum Either<LTy, RTy> {
case Left(LTy)
case Right(RTy)
}
/// This type allows us to make sure we are skipping cases correctly when
/// stripping off ref count identical opts.
enum FakeCasesOptional<T> {
case none
case none1
case some(T)
case none2
case some2(T)
case none3
}
///////////
// Tests //
///////////
// CHECK-LABEL: sil @silargument_strip_single_payload_case_enum1 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK-NOT: retain
// CHECK-NOT: release
sil @silargument_strip_single_payload_case_enum1 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb3(%1 : $FakeOptional<Builtin.NativeObject>):
retain_value %1 : $FakeOptional<Builtin.NativeObject>
release_value %0 : $FakeOptional<Builtin.NativeObject>
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil @silargument_strip_single_payload_case_enum2 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK-NOT: retain
// CHECK-NOT: release
sil @silargument_strip_single_payload_case_enum2 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
retain_value %2 : $FakeOptional<Builtin.NativeObject>
release_value %0 : $FakeOptional<Builtin.NativeObject>
%3 = tuple()
return %3 : $()
}
// This is supposed to fail b/c %0 is not .none down bb1.
//
// CHECK-LABEL: sil @silargument_strip_single_payload_case_enum3 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK: retain
// CHECK: release
sil @silargument_strip_single_payload_case_enum3 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb2:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
retain_value %2 : $FakeOptional<Builtin.NativeObject>
release_value %0 : $FakeOptional<Builtin.NativeObject>
%3 = tuple()
return %3 : $()
}
// Make sure we do not do anything dumb when we have two enums without payloads.
// CHECK-LABEL: sil @silargument_strip_single_payload_case_enum4 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK: retain_value
// CHECK: release_value
sil @silargument_strip_single_payload_case_enum4 : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb2:
%2 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%2 : $FakeOptional<Builtin.NativeObject>)
bb3(%3 : $FakeOptional<Builtin.NativeObject>):
retain_value %3 : $FakeOptional<Builtin.NativeObject>
release_value %0 : $FakeOptional<Builtin.NativeObject>
%4 = tuple()
return %4 : $()
}
// Make sure that we can handle the multi payload case with interleaved empty
// payloads.
// CHECK-LABEL: sil @silargument_strip_multipayload_with_fake_nopayload_cases : $@convention(thin) (FakeCasesOptional<Builtin.NativeObject>) -> () {
// CHECK-NOT: retain
// CHECK-NOT: release
sil @silargument_strip_multipayload_with_fake_nopayload_cases : $@convention(thin) (FakeCasesOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeCasesOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeCasesOptional<Builtin.NativeObject>, case #FakeCasesOptional.none!enumelt: bb1, case #FakeCasesOptional.none1!enumelt: bb2, case #FakeCasesOptional.some!enumelt.1: bb3, case #FakeCasesOptional.none2!enumelt: bb4, case #FakeCasesOptional.some2!enumelt.1: bb5, case #FakeCasesOptional.none3!enumelt: bb6
bb1:
%1 = enum $FakeCasesOptional<Builtin.NativeObject>, #FakeCasesOptional.none!enumelt
br bb7(%1 : $FakeCasesOptional<Builtin.NativeObject>)
bb2:
%2 = enum $FakeCasesOptional<Builtin.NativeObject>, #FakeCasesOptional.none1!enumelt
br bb7(%2 : $FakeCasesOptional<Builtin.NativeObject>)
bb3:
br bb7(%0 : $FakeCasesOptional<Builtin.NativeObject>)
bb4:
%3 = enum $FakeCasesOptional<Builtin.NativeObject>, #FakeCasesOptional.none2!enumelt
br bb7(%3 : $FakeCasesOptional<Builtin.NativeObject>)
bb5:
br bb7(%0 : $FakeCasesOptional<Builtin.NativeObject>)
bb6:
%4 = enum $FakeCasesOptional<Builtin.NativeObject>, #FakeCasesOptional.none3!enumelt
br bb7(%4 : $FakeCasesOptional<Builtin.NativeObject>)
bb7(%5 : $FakeCasesOptional<Builtin.NativeObject>):
retain_value %5 : $FakeCasesOptional<Builtin.NativeObject>
release_value %0 : $FakeCasesOptional<Builtin.NativeObject>
%6 = tuple()
return %6 : $()
}
// This looks like we are reforming an enum, but we are not really. Make sure
// that we do not remove the retain, release in this case.
// CHECK-LABEL: sil @silargument_fake_enum_reform : $@convention(thin) (Builtin.NativeObject) -> () {
// CHECK: retain_value
// CHECK: release_value
sil @silargument_fake_enum_reform : $@convention(thin) (Builtin.NativeObject) -> () {
bb0(%0 : $Builtin.NativeObject):
cond_br undef, bb1, bb2
bb1:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb2:
%2 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.some!enumelt.1, %0 : $Builtin.NativeObject
br bb3(%2 : $FakeOptional<Builtin.NativeObject>)
bb3(%3 : $FakeOptional<Builtin.NativeObject>):
retain_value %0 : $Builtin.NativeObject
release_value %3 : $FakeOptional<Builtin.NativeObject>
%9999 = tuple()
return %9999 : $()
}
// Make sure that we can handle multiple-iterated enum args where the
// switch_enum or unchecked_enum_data is before the next diamond.
// CHECK-LABEL: sil @silargument_iterated_silargument_strips : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK-NOT: retain_value
// CHECK-NOT: release_value
sil @silargument_iterated_silargument_strips : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
switch_enum %2 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb4, case #FakeOptional.none!enumelt: bb5
bb4:
br bb6(%2 : $FakeOptional<Builtin.NativeObject>)
bb5:
%3 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb6(%3 : $FakeOptional<Builtin.NativeObject>)
bb6(%4 : $FakeOptional<Builtin.NativeObject>):
retain_value %0 : $FakeOptional<Builtin.NativeObject>
release_value %4 : $FakeOptional<Builtin.NativeObject>
%9999 = tuple()
return %9999 : $()
}
// Make sure that (for now) we do not look past %2 to see that %0 can be matched
// up with %0, %4.
//
// I think this is in general safe, but for now I want to be more than less
// conservative.
//
// CHECK-LABEL: sil @silargument_iterated_silargument_strips_too_far_up_domtree : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK: retain_value
// CHECK: release_value
sil @silargument_iterated_silargument_strips_too_far_up_domtree : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
cond_br undef, bb4, bb5
bb4:
br bb6(%2 : $FakeOptional<Builtin.NativeObject>)
bb5:
%3 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb6(%3 : $FakeOptional<Builtin.NativeObject>)
bb6(%4 : $FakeOptional<Builtin.NativeObject>):
retain_value %0 : $FakeOptional<Builtin.NativeObject>
release_value %4 : $FakeOptional<Builtin.NativeObject>
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @silargument_dont_strip_over_relevant_loop : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK: retain_value
// CHECK: release_value
sil @silargument_dont_strip_over_relevant_loop : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
cond_br undef, bb3(%2 : $FakeOptional<Builtin.NativeObject>), bb4
bb4:
retain_value %0 : $FakeOptional<Builtin.NativeObject>
release_value %2 : $FakeOptional<Builtin.NativeObject>
%9999 = tuple()
return %9999 : $()
}
// Make sure we are properly iterating up the domtree by checking if we properly
// look past the loop in bb4 and match up %0 and %2.
//
// CHECK-LABEL: sil @silargument_do_strip_over_irrelevant_loop : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
// CHECK-NOT: retain_value
// CHECK-NOT: release_value
sil @silargument_do_strip_over_irrelevant_loop : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
switch_enum %0 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
br bb3(%0 : $FakeOptional<Builtin.NativeObject>)
bb2:
%1 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb3(%2 : $FakeOptional<Builtin.NativeObject>):
cond_br undef, bb4, bb5
bb4:
cond_br undef, bb4, bb5
bb5:
retain_value %0 : $FakeOptional<Builtin.NativeObject>
release_value %2 : $FakeOptional<Builtin.NativeObject>
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @silargument_nondominated_strip : $@convention(thin) (@in FakeOptional<Builtin.NativeObject>) -> () {
// CHECK: retain_value
// CHECK: release_value
sil @silargument_nondominated_strip : $@convention(thin) (@in FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $*FakeOptional<Builtin.NativeObject>):
cond_br undef, bb1, bb2
bb1:
%1 = load %0 : $*FakeOptional<Builtin.NativeObject>
br bb3(%1 : $FakeOptional<Builtin.NativeObject>)
bb2:
%2 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
br bb3(%2 : $FakeOptional<Builtin.NativeObject>)
bb3(%3 : $FakeOptional<Builtin.NativeObject>):
%4 = function_ref @fakeoptional_user : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> ()
retain_value %3 : $FakeOptional<Builtin.NativeObject>
apply %4(%3) : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> ()
apply %4(%3) : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> ()
release_value %3 : $FakeOptional<Builtin.NativeObject>
%5 = tuple()
return %5 : $()
}
struct _SwiftEmptyArrayStorage {
}
sil_global [serialized] @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage
// CHECK-LABEL: sil @dont_strip_rawpointer_to_address
// CHECK: raw_pointer_to_ref
// CHECK: strong_retain
// CHECK: return
sil @dont_strip_rawpointer_to_address : $@convention(thin) (FakeOptional<Builtin.NativeObject>) -> () {
bb0(%0 : $FakeOptional<Builtin.NativeObject>):
%2 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
%3 = address_to_pointer %2 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
%4 = raw_pointer_to_ref %3 : $Builtin.RawPointer to $Builtin.NativeObject
strong_retain %4 : $Builtin.NativeObject
%5 = function_ref @user : $@convention(thin) (Builtin.NativeObject) -> ()
apply %5(%4) : $@convention(thin) (Builtin.NativeObject) -> ()
apply %5(%4) : $@convention(thin) (Builtin.NativeObject) -> ()
strong_release %4 : $Builtin.NativeObject
%6 = tuple()
return %6 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_1bb : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_1bb : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
%2 = alloc_ref $Cls
retain_value %2 : $Cls
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb2
bb2:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_multibb1 : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_multibb1 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
%2 = alloc_ref $Cls
retain_value %2 : $Cls
br bb2
bb2:
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
br bb3
bb3:
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb4
bb4:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_multibb2 : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_multibb2 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
br bb2
bb2:
%2 = alloc_ref $Cls
retain_value %2 : $Cls
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
br bb3
bb3:
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb4
bb4:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_multibb3 : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_multibb3 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
br bb2
bb2:
%2 = alloc_ref $Cls
retain_value %2 : $Cls
br bb3
bb3:
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb4
bb4:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_multibb4 : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_multibb4 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
br bb2
bb2:
br bb3
bb3:
%2 = alloc_ref $Cls
retain_value %2 : $Cls
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb4
bb4:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @dont_strip_phi_nodes_over_backedges_multibb5 : $@convention(thin) () -> () {
// CHECK: retain_value
// CHECK: release_value
sil @dont_strip_phi_nodes_over_backedges_multibb5 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Cls>, #FakeOptional.none!enumelt
br bb1(%0 : $FakeOptional<Cls>)
bb1(%1 : $FakeOptional<Cls>):
%2 = alloc_ref $Cls
retain_value %2 : $Cls
br bb2
bb2:
br bb3
bb3:
release_value %1 : $FakeOptional<Cls>
%3 = enum $FakeOptional<Cls>, #FakeOptional.some!enumelt.1, %2 : $Cls
cond_br undef, bb1(%3 : $FakeOptional<Cls>), bb4
bb4:
%4 = tuple()
return %4 : $()
}
// CHECK-LABEL: sil @strip_off_structs_tuples_tuple_extracts : $@convention(thin) (Builtin.NativeObject, (Builtin.Int32, Builtin.NativeObject, Builtin.Int32)) -> () {
// CHECK-NOT: retain_value
// CHECK-NOT: release_value
sil @strip_off_structs_tuples_tuple_extracts : $@convention(thin) (Builtin.NativeObject, (Builtin.Int32, Builtin.NativeObject, Builtin.Int32)) -> () {
bb0(%0 : $Builtin.NativeObject, %1 : $(Builtin.Int32, Builtin.NativeObject, Builtin.Int32)):
%2 = integer_literal $Builtin.Int32, 0
%3 = struct $S2(%2 : $Builtin.Int32, %0 : $Builtin.NativeObject, %2 : $Builtin.Int32)
retain_value %3 : $S2
%4 = tuple(%2 : $Builtin.Int32, %0 : $Builtin.NativeObject, %2 : $Builtin.Int32)
release_value %4 : $(Builtin.Int32, Builtin.NativeObject, Builtin.Int32)
retain_value %1 : $(Builtin.Int32, Builtin.NativeObject, Builtin.Int32)
%5 = tuple_extract %1 : $(Builtin.Int32, Builtin.NativeObject, Builtin.Int32), 1
release_value %5 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @strip_off_initopen_existential_ref : $@convention(thin) (C) -> () {
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
// CHECK-NOT: retain_value
// CHECK-NOT: release_value
sil @strip_off_initopen_existential_ref : $@convention(thin) (C) -> () {
bb0(%0 : $C):
%1 = init_existential_ref %0 : $C : $C, $AnyObject
%2 = open_existential_ref %1 : $AnyObject to $@opened("A2E21C52-6089-11E4-9866-3C0754723233") AnyObject
strong_retain %0 : $C
release_value %2 : $@opened("A2E21C52-6089-11E4-9866-3C0754723233") AnyObject
%3 = tuple()
return %3 : $()
}
// CHECK-LABEL: sil @strip_off_bridge_object
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
sil @strip_off_bridge_object : $@convention(thin) (Builtin.BridgeObject, C) -> () {
bb0(%0 : $Builtin.BridgeObject, %5 : $C):
%1 = bridge_object_to_ref %0 : $Builtin.BridgeObject to $C
strong_retain %1 : $C
strong_release %0 : $Builtin.BridgeObject
%4 = integer_literal $Builtin.Word, 0
%2 = ref_to_bridge_object %5 : $C, %4 : $Builtin.Word
strong_retain %5 : $C
strong_release %2 : $Builtin.BridgeObject
%3 = tuple()
return %3 : $()
}
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial_retain_outer
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
// CHECK: return
sil @retain_release_struct_with_single_nontrivial_retain_outer : $@convention(thin) (SContainer) -> () {
bb0(%0 : $SContainer):
retain_value %0 : $SContainer
%1 = struct_extract %0 : $SContainer, #SContainer.c
strong_release %1 : $Cls
%r = tuple()
return %r : $()
}
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial_retain_inner
// CHECK-NOT: retain_value
// CHECK-NOT: release_value
// CHECK: return
sil @retain_release_struct_with_single_nontrivial_retain_inner : $@convention(thin) (SContainer) -> () {
bb0(%0 : $SContainer):
%1 = struct_extract %0 : $SContainer, #SContainer.c
retain_value %1 : $Cls
release_value %0 : $SContainer
%r = tuple()
return %r : $()
}
// CHECK-LABEL: sil @retain_release_struct_with_multiple_nontrivials_retain_outer
// CHECK: retain_value
// CHECK: strong_release
// CHECK: return
sil @retain_release_struct_with_multiple_nontrivials_retain_outer : $@convention(thin) (SContainer2) -> () {
bb0(%0 : $SContainer2):
retain_value %0 : $SContainer2
%1 = struct_extract %0 : $SContainer2, #SContainer2.c
strong_release %1 : $Cls
%r = tuple()
return %r : $()
}
// CHECK-LABEL: sil @retain_release_struct_with_multiple_nontrivials_retain_inner
// CHECK: retain_value
// CHECK: release_value
// CHECK: return
sil @retain_release_struct_with_multiple_nontrivials_retain_inner : $@convention(thin) (SContainer2) -> () {
bb0(%0 : $SContainer2):
%1 = struct_extract %0 : $SContainer2, #SContainer2.c
retain_value %1 : $Cls
release_value %0 : $SContainer2
%r = tuple()
return %r : $()
}
// Make sure the RR pair is not removed here as a result of the decrement and use.
//
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement_retain_outer
// CHECK: retain_value
// CHECK: release_value
sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement_retain_outer : $@convention(thin) (SContainer) -> () {
bb0(%0 : $SContainer):
retain_value %0 : $SContainer
%1 = struct_extract %0 : $SContainer, #SContainer.c
%2 = function_ref @cls_use : $@convention(thin) (@owned Cls) -> ()
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
release_value %1 : $Cls
%r = tuple()
return %r : $()
}
// Make sure the RR pair is not removed here as a result of the decrement and use.
//
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement_retain_inner
// CHECK: retain_value
// CHECK: release_value
sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement_retain_inner : $@convention(thin) (SContainer) -> () {
bb0(%0 : $SContainer):
%1 = struct_extract %0 : $SContainer, #SContainer.c
retain_value %1 : $Cls
%2 = function_ref @cls_use : $@convention(thin) (@owned Cls) -> ()
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
release_value %0 : $SContainer
%r = tuple()
return %r : $()
}