mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1018 lines
36 KiB
Plaintext
1018 lines
36 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -module-name Swift -enable-sil-verify-all -semantic-arc-opts -sil-semantic-arc-peepholes-lifetime-joining %s | %FileCheck %s
|
|
|
|
// NOTE: Some of our tests here depend on borrow elimination /not/ running!
|
|
// Please do not add it to clean up the IR like we did in
|
|
// semanticarcopts-loadcopy-to-loadborrow!
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
|
|
//////////////////
|
|
// Declarations //
|
|
//////////////////
|
|
|
|
typealias AnyObject = Builtin.AnyObject
|
|
|
|
struct Bool {
|
|
var value : Builtin.Int1
|
|
}
|
|
|
|
sil @closureCapturesBool : $@convention(thin) (@guaranteed { var Bool }) -> ()
|
|
sil @closureArgumentEscapes : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> ()
|
|
|
|
enum MyNever {}
|
|
enum FakeOptional<T> {
|
|
case none
|
|
case some(T)
|
|
}
|
|
|
|
sil [ossa] @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
sil [ossa] @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
sil [ossa] @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
sil [ossa] @unreachable_guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> MyNever
|
|
sil [ossa] @inout_user : $@convention(thin) (@inout FakeOptional<NativeObjectPair>) -> ()
|
|
sil [ossa] @get_native_object : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
|
|
struct NativeObjectPair {
|
|
var obj1 : Builtin.NativeObject
|
|
var obj2 : Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] @get_object_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
|
|
struct FakeOptionalNativeObjectPairPair {
|
|
var pair1 : FakeOptional<NativeObjectPair>
|
|
var pair2 : FakeOptional<NativeObjectPair>
|
|
}
|
|
sil [ossa] @inout_user2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
|
|
sil [ossa] @get_nativeobject_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
sil [ossa] @consume_nativeobject_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
|
|
protocol MyFakeAnyObject : Klass {
|
|
func myFakeMethod()
|
|
}
|
|
|
|
final class Klass {
|
|
var base: Klass
|
|
let baseLet: Klass
|
|
}
|
|
|
|
extension Klass : MyFakeAnyObject {
|
|
func myFakeMethod()
|
|
}
|
|
sil [ossa] @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
sil [ossa] @guaranteed_fakeoptional_klass_user : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
|
|
sil [ossa] @guaranteed_fakeoptional_classlet_user : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> ()
|
|
|
|
struct MyInt {
|
|
var value: Builtin.Int32
|
|
}
|
|
|
|
struct StructWithDataAndOwner {
|
|
var data : Builtin.Int32
|
|
var owner : Klass
|
|
}
|
|
|
|
struct StructMemberTest {
|
|
var c : Klass
|
|
var s : StructWithDataAndOwner
|
|
var t : (Builtin.Int32, StructWithDataAndOwner)
|
|
}
|
|
|
|
class ClassLet {
|
|
@_hasStorage let aLet: Klass
|
|
@_hasStorage var aVar: Klass
|
|
@_hasStorage let aLetTuple: (Klass, Klass)
|
|
@_hasStorage let anOptionalLet: FakeOptional<Klass>
|
|
|
|
@_hasStorage let anotherLet: ClassLet
|
|
}
|
|
|
|
class SubclassLet: ClassLet {}
|
|
|
|
sil_global [let] @a_let_global : $Klass
|
|
sil_global @a_var_global : $Klass
|
|
|
|
enum EnumWithIndirectCase {
|
|
case first
|
|
indirect case second(Builtin.NativeObject)
|
|
}
|
|
|
|
struct StructWithEnumWithIndirectCaseField {
|
|
var i: Builtin.Int23
|
|
var field : EnumWithIndirectCase
|
|
}
|
|
|
|
sil [ossa] @get_fakeoptional_nativeobject : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
|
|
|
|
struct NativeObjectWrapper {
|
|
var innerWrapper : Builtin.NativeObject
|
|
}
|
|
|
|
sil @owned_user_object_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
|
|
class X {}
|
|
struct S {}
|
|
|
|
sil @getX : $@convention(thin) () -> @owned X
|
|
sil @getS : $@convention(thin) (@owned X) -> @out S
|
|
sil @loadWeakX_from : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
|
|
|
|
///////////
|
|
// Tests //
|
|
///////////
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_in_same_block_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_in_same_block_1'
|
|
sil [ossa] @join_liveranges_in_same_block_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_in_same_block_2'
|
|
sil [ossa] @join_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_in_same_block_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_in_same_block_3'
|
|
sil [ossa] @join_liveranges_in_same_block_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_in_same_block_4 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_in_same_block_4'
|
|
sil [ossa] @join_liveranges_in_same_block_4 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%f = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
%f2 = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f2(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_in_same_block_5 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-LABEL: } // end sil function 'join_liveranges_in_same_block_5'
|
|
sil [ossa] @join_liveranges_in_same_block_5 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Forwarding case.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @donot_join_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'donot_join_liveranges_in_same_block_2'
|
|
sil [ossa] @donot_join_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $Builtin.NativeObject
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%2) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Forwarding case. We need LiveRanges for this.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @donot_join_liveranges_in_same_block_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'donot_join_liveranges_in_same_block_3'
|
|
sil [ossa] @donot_join_liveranges_in_same_block_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = unchecked_ref_cast %0 : $Builtin.NativeObject to $Builtin.NativeObject
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Now test cases where we find our consumer is in the return block or is a
|
|
// return itself.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_not_same_block_with_consuming_return : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_not_same_block_with_consuming_return'
|
|
sil [ossa] @join_liveranges_not_same_block_with_consuming_return : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liveranges_not_same_block_consumed_in_return_block : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_liveranges_not_same_block_consumed_in_return_block'
|
|
sil [ossa] @join_liveranges_not_same_block_consumed_in_return_block : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @donot_join_liveranges_not_same_block_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'donot_join_liveranges_not_same_block_1'
|
|
sil [ossa] @donot_join_liveranges_not_same_block_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @donot_join_liveranges_not_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'donot_join_liveranges_not_same_block_2'
|
|
sil [ossa] @donot_join_liveranges_not_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%f = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liverange_multiple_destroy_value : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'join_liverange_multiple_destroy_value'
|
|
sil [ossa] @join_liverange_multiple_destroy_value : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%constructingUse = function_ref @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%obj2 = copy_value %obj : $Builtin.NativeObject
|
|
destroy_value %obj : $Builtin.NativeObject
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
apply %consumingUse(%obj2) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb1b:
|
|
apply %consumingUse(%obj2) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
apply %consumingUse(%obj) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liverange_forwarding_chain_1 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'join_liverange_forwarding_chain_1'
|
|
sil [ossa] @join_liverange_forwarding_chain_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%constructingUse = function_ref @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
|
|
%obj2 = copy_value %obj : $Builtin.NativeObject
|
|
destroy_value %obj : $Builtin.NativeObject
|
|
%obj3 = unchecked_ref_cast %obj2 : $Builtin.NativeObject to $Builtin.NativeObject
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_1 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'join_liverange_multiple_destroy_value_forwarding_chain_1'
|
|
sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%constructingUse = function_ref @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%obj2 = copy_value %obj : $Builtin.NativeObject
|
|
destroy_value %obj : $Builtin.NativeObject
|
|
%obj3 = unchecked_ref_cast %obj2 : $Builtin.NativeObject to $Builtin.NativeObject
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb1b:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
apply %consumingUse(%obj) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_2 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'join_liverange_multiple_destroy_value_forwarding_chain_2'
|
|
sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%constructingUse = function_ref @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%obj2 = copy_value %obj : $Builtin.NativeObject
|
|
%obj3 = unchecked_ref_cast %obj2 : $Builtin.NativeObject to $Builtin.NativeObject
|
|
destroy_value %obj : $Builtin.NativeObject
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb1b:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
apply %consumingUse(%obj) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We do not support destructures and other multiple value instructions yet...
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_3 : $@convention(thin) () -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: destroy_value
|
|
// CHECK: } // end sil function 'join_liverange_multiple_destroy_value_forwarding_chain_3'
|
|
sil [ossa] @join_liverange_multiple_destroy_value_forwarding_chain_3 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%constructingUse = function_ref @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%obj2 = copy_value %obj : $Builtin.NativeObject
|
|
%obj2a = struct $NativeObjectWrapper(%obj2 : $Builtin.NativeObject)
|
|
(%obj3) = destructure_struct %obj2a : $NativeObjectWrapper
|
|
destroy_value %obj : $Builtin.NativeObject
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb1b:
|
|
apply %consumingUse(%obj3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
apply %consumingUse(%obj) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// This case succeeds since our borrow scope does not overlap with our
|
|
// forwarding region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_succeed_1 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_succeed_1'
|
|
sil [ossa] @join_live_range_with_borrowscopes_succeed_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user_object_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
%constructingUse = function_ref @get_object_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned NativeObjectPair
|
|
%borrowedObj = begin_borrow %obj : $NativeObjectPair
|
|
%obj1 = struct_extract %borrowedObj : $NativeObjectPair, #NativeObjectPair.obj1
|
|
%guaranteedUse = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %guaranteedUse(%obj1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_borrow %borrowedObj : $NativeObjectPair
|
|
%2 = copy_value %obj : $NativeObjectPair
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %obj : $NativeObjectPair
|
|
apply %consumingUse(%2) : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// In this case, we validate that we can perform the optimization with
|
|
// forwarding insts.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_succeed_2 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_succeed_2'
|
|
sil [ossa] @join_live_range_with_borrowscopes_succeed_2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
end_borrow %borrowedObj : $Klass
|
|
%2 = copy_value %obj : $Klass
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Here we succeed even though %2's lifetime ends at the unchecked_ref_cast, we
|
|
// are able to know that
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_succeed_3 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_succeed_3'
|
|
sil [ossa] @join_live_range_with_borrowscopes_succeed_3 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
end_borrow %borrowedObj : $Klass
|
|
%2 = copy_value %obj : $Klass
|
|
br bb1
|
|
|
|
bb1:
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// In this case we fail since we don't want to have to deal with splitting the
|
|
// scope of %borrowedObj at %3.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_fail_1 : $@convention(thin) () -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_fail_1'
|
|
sil [ossa] @join_live_range_with_borrowscopes_fail_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
%2 = copy_value %obj : $Klass
|
|
br bb1
|
|
|
|
bb1:
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
end_borrow %borrowedObj : $Klass
|
|
destroy_value %obj : $Klass
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb2
|
|
|
|
bb2:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// This case succeeds since our borrow scope does not overlap with our
|
|
// forwarding region.
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%consumingUse = function_ref @owned_user_object_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
%constructingUse = function_ref @get_object_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
%obj = apply %constructingUse() : $@convention(thin) () -> @owned NativeObjectPair
|
|
%borrowedObj = begin_borrow %obj : $NativeObjectPair
|
|
%obj1 = struct_extract %borrowedObj : $NativeObjectPair, #NativeObjectPair.obj1
|
|
%guaranteedUse = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %guaranteedUse(%obj1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_borrow %borrowedObj : $NativeObjectPair
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $NativeObjectPair
|
|
destroy_value %obj : $NativeObjectPair
|
|
apply %consumingUse(%2) : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $NativeObjectPair
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// In this case, we validate that we can perform the optimization with
|
|
// forwarding insts.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_2 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_2'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
// We cheat and use end_borrow so we don't optimize this borrow.
|
|
end_borrow %borrowedObj : $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
destroy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_3 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_3'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_3 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
end_borrow %borrowedObj : $Klass
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
end_borrow %borrowedObj : $Klass
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_4 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_4'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_4 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
end_borrow %borrowedObj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
end_borrow %borrowedObj : $Klass
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_5 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_5'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_5 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Klass
|
|
%5 = unchecked_ref_cast %4 : $Klass to $Builtin.NativeObject
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%5) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_6 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_6'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_6 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
br bb1a
|
|
|
|
bb1a:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_7 : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_7'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_7 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
destroy_value %obj : $Klass
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb1c
|
|
|
|
bb1b:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb1c
|
|
|
|
bb1c:
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// TODO: check why the copy cannot be eliminated here
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_8 : $@convention(thin) () -> () {
|
|
// xCHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_succeed_8'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_succeed_8 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// In this case we fail since we don't want to have to deal with splitting the
|
|
// scope of %borrowedObj at %3.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_fail_1 : $@convention(thin) () -> () {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'join_live_range_with_borrowscopes_multipledestroys_fail_1'
|
|
sil [ossa] @join_live_range_with_borrowscopes_multipledestroys_fail_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%obj = alloc_ref $Klass
|
|
%borrowedObj = begin_borrow %obj : $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = copy_value %obj : $Klass
|
|
%3 = unchecked_ref_cast %2 : $Klass to $Builtin.NativeObject
|
|
end_borrow %borrowedObj : $Klass
|
|
destroy_value %obj : $Klass
|
|
%consumingUse = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %consumingUse(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
end_borrow %borrowedObj : $Klass
|
|
destroy_value %obj : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure we leave only one copy in bb2 and no destroys
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @join_test_with_forwarding_inst : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject> {
|
|
// CHECK: bb2:
|
|
// CHECK: copy_value
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: br bb3(
|
|
// CHECK: } // end sil function 'join_test_with_forwarding_inst'
|
|
sil [ossa] @join_test_with_forwarding_inst : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject> {
|
|
bb0:
|
|
%allocStack = alloc_stack $Builtin.NativeObject
|
|
%0 = function_ref @get_fakeoptional_nativeobject : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
|
|
%1 = apply %0() : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_value %1 : $FakeOptional<Builtin.NativeObject>
|
|
%2 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
|
|
br bb3(%2 : $FakeOptional<Builtin.NativeObject>)
|
|
|
|
bb2:
|
|
%3 = unchecked_enum_data %1 : $FakeOptional<Builtin.NativeObject>, #FakeOptional.some!enumelt
|
|
%4 = copy_value %3 : $Builtin.NativeObject
|
|
store %3 to [init] %allocStack : $*Builtin.NativeObject
|
|
%4c = copy_value %4 : $Builtin.NativeObject
|
|
destroy_value %4 : $Builtin.NativeObject
|
|
%5 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.some!enumelt, %4c : $Builtin.NativeObject
|
|
destroy_addr %allocStack : $*Builtin.NativeObject
|
|
br bb3(%5 : $FakeOptional<Builtin.NativeObject>)
|
|
|
|
bb3(%result : @owned $FakeOptional<Builtin.NativeObject>):
|
|
dealloc_stack %allocStack : $*Builtin.NativeObject
|
|
return %result : $FakeOptional<Builtin.NativeObject>
|
|
}
|
|
|
|
// Don't do this optimization:
|
|
// Eliminate borrowed copy with useless lifetime:
|
|
// %5 = copy_value %0 : ${ var Bool }
|
|
//
|
|
// CHECK: sil hidden [ossa] @testCapturedSingleDestroyCopy : $@convention(thin) () -> Bool {
|
|
// CHECK: load [trivial] %{{.*}} : $*Bool
|
|
// CHECK: destroy_value %0 : ${ var Bool }
|
|
sil hidden [ossa] @testCapturedSingleDestroyCopy : $@convention(thin) () -> Bool {
|
|
bb0:
|
|
// var test = false
|
|
%0 = alloc_box ${ var Bool }, var, name "test"
|
|
%1 = project_box %0 : ${ var Bool }, 0
|
|
%2 = integer_literal $Builtin.Int1, 0
|
|
%3 = struct $Bool (%2 : $Builtin.Int1)
|
|
store %3 to [trivial] %1 : $*Bool
|
|
|
|
// capture test in an escaping closure
|
|
%5 = copy_value %0 : ${ var Bool }
|
|
%6 = function_ref @closureCapturesBool : $@convention(thin) (@guaranteed { var Bool }) -> ()
|
|
%7 = partial_apply [callee_guaranteed] %6(%5) : $@convention(thin) (@guaranteed { var Bool }) -> ()
|
|
%8 = function_ref @closureArgumentEscapes : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> ()
|
|
%9 = apply %8(%7) : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> ()
|
|
|
|
// return test
|
|
%10 = begin_access [read] [dynamic] %1 : $*Bool
|
|
%11 = load [trivial] %10 : $*Bool
|
|
end_access %10 : $*Bool
|
|
destroy_value %0 : ${ var Bool }
|
|
return %11 : $Bool
|
|
}
|
|
|
|
// Don't do this optimization:
|
|
// Eliminate copy of lexical value which ends after lifetime of copy IF there
|
|
// may be deinit barriers between the final consume and the copy.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @testDestroyedLexicalValue : {{.*}} {
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getX
|
|
// CHECK: [[X:%[^,]+]] = apply [[GET]]()
|
|
// CHECK: [[MX:%[^,]+]] = move_value [lexical] [[X]]
|
|
// CHECK: destroy_value [[MX]] : $X
|
|
// CHECK-LABEL: } // end sil function 'testDestroyedLexicalValue'
|
|
sil [ossa] @testDestroyedLexicalValue : $@convention(thin) () -> @owned FakeOptional<X> {
|
|
bb0:
|
|
%getX = function_ref @getX : $@convention(thin) () -> @owned X
|
|
%x = apply %getX() : $@convention(thin) () -> @owned X
|
|
%mx = move_value [lexical] %x : $X
|
|
%a = alloc_stack [lexical] $S, let, name "s"
|
|
%c = copy_value %mx : $X
|
|
%getS = function_ref @getS : $@convention(thin) (@owned X) -> @out S
|
|
%s = apply %getS(%a, %c) : $@convention(thin) (@owned X) -> @out S
|
|
%loadWeakX_from = function_ref @loadWeakX_from : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
|
|
%o = apply %loadWeakX_from(%a) : $@convention(thin) (@in_guaranteed S) -> @owned FakeOptional<X>
|
|
// ^^^^^ Deinit barrier
|
|
destroy_addr %a : $*S
|
|
dealloc_stack %a : $*S
|
|
destroy_value %mx : $X
|
|
return %o : $FakeOptional<X>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testDestroyedLexicalValueNoBarriers : {{.*}} {
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK-LABEL: } // end sil function 'testDestroyedLexicalValueNoBarriers'
|
|
sil [ossa] @testDestroyedLexicalValueNoBarriers : $@convention(thin) () -> () {
|
|
bb0:
|
|
%getX = function_ref @getX : $@convention(thin) () -> @owned X
|
|
%x = apply %getX() : $@convention(thin) () -> @owned X
|
|
%mx = move_value [lexical] %x : $X
|
|
%a = alloc_stack [lexical] $S, let, name "s"
|
|
%c = copy_value %mx : $X
|
|
%getS = function_ref @getS : $@convention(thin) (@owned X) -> @out S
|
|
%s = apply %getS(%a, %c) : $@convention(thin) (@owned X) -> @out S
|
|
destroy_addr %a : $*S
|
|
dealloc_stack %a : $*S
|
|
destroy_value %mx : $X
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @consume_and_borrow : $@convention(thin) (@owned Klass, @guaranteed Klass) -> ()
|
|
sil @borrow : $@convention(thin) (@guaranteed Klass) -> ()
|
|
sil @consume : $@convention(thin) (@owned Klass) -> ()
|
|
sil @get_klass : $@convention(thin) () -> @owned Klass
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @borrow_and_consume_copyable_test1 :
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-LABEL: } // end sil function 'borrow_and_consume_copyable_test1'
|
|
sil hidden [ossa] @borrow_and_consume_copyable_test1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @get_klass : $@convention(thin) () -> @owned Klass
|
|
%1 = apply %0() : $@convention(thin) () -> @owned Klass
|
|
%2 = move_value [var_decl] %1
|
|
%3 = copy_value %2
|
|
%4 = function_ref @borrow : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%5 = apply %4(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%6 = function_ref @consume : $@convention(thin) (@owned Klass) -> ()
|
|
%7 = apply %6(%3) : $@convention(thin) (@owned Klass) -> ()
|
|
destroy_value %2
|
|
%9 = tuple ()
|
|
return %9
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @borrow_and_consume_copyable_test2 :
|
|
// CHECK: copy_value
|
|
// CHECK-LABEL: } // end sil function 'borrow_and_consume_copyable_test2'
|
|
sil hidden [ossa] @borrow_and_consume_copyable_test2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @get_klass : $@convention(thin) () -> @owned Klass
|
|
%1 = apply %0() : $@convention(thin) () -> @owned Klass
|
|
%2 = move_value [var_decl] %1
|
|
%3 = copy_value %2
|
|
%4 = function_ref @consume_and_borrow : $@convention(thin) (@owned Klass, @guaranteed Klass) -> ()
|
|
%5 = apply %4(%3, %2) : $@convention(thin) (@owned Klass, @guaranteed Klass) -> ()
|
|
destroy_value %2
|
|
%7 = tuple ()
|
|
return %7
|
|
}
|
|
|