mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
2263 lines
84 KiB
Plaintext
2263 lines
84 KiB
Plaintext
// RUN: %target-sil-opt -copy-to-borrow-optimization %s | %FileCheck %s
|
|
// REQUIRES: macosx
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
//////////////////
|
|
// Declarations //
|
|
//////////////////
|
|
|
|
enum MyNever {}
|
|
enum FakeOptional<T> {
|
|
case none
|
|
case some(T)
|
|
}
|
|
|
|
sil @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
sil @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
sil @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
sil @unreachable_guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> MyNever
|
|
sil @inout_user : $@convention(thin) (@inout FakeOptional<NativeObjectPair>) -> ()
|
|
sil @get_native_object : $@convention(thin) () -> @owned Builtin.NativeObject
|
|
sil [ossa] @get_enum : $@convention(thin) () -> @owned EnumA
|
|
|
|
struct NativeObjectPair {
|
|
var obj1 : Builtin.NativeObject
|
|
var obj2 : Builtin.NativeObject
|
|
}
|
|
|
|
sil @get_object_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
|
|
struct FakeOptionalNativeObjectPairPair {
|
|
var pair1 : FakeOptional<NativeObjectPair>
|
|
var pair2 : FakeOptional<NativeObjectPair>
|
|
}
|
|
sil @inout_user2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
|
|
sil @get_nativeobject_pair : $@convention(thin) () -> @owned NativeObjectPair
|
|
sil @consume_nativeobject_pair : $@convention(thin) (@owned NativeObjectPair) -> ()
|
|
|
|
protocol MyFakeAnyObject : Klass {
|
|
func myFakeMethod()
|
|
}
|
|
|
|
final class Klass {
|
|
var base: Klass
|
|
let baseLet: Klass
|
|
}
|
|
|
|
class C {}
|
|
|
|
class Base {
|
|
@_hasStorage var c: C
|
|
}
|
|
|
|
class Derived : Base {
|
|
}
|
|
|
|
class Container {
|
|
@_hasStorage var b: Base
|
|
}
|
|
|
|
struct OptionalAndClass {
|
|
var o: FakeOptional<C>
|
|
var c: C
|
|
}
|
|
|
|
enum MultiPayload {
|
|
case a(Klass)
|
|
case b(MyInt)
|
|
}
|
|
|
|
sil @getC : $@convention(thin) () -> (@owned C)
|
|
|
|
extension Klass : MyFakeAnyObject {
|
|
func myFakeMethod()
|
|
}
|
|
|
|
struct NonTrivialStruct {
|
|
var val: Klass
|
|
}
|
|
|
|
sil @getKlass : $@convention(thin) () -> @owned Klass
|
|
sil @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
sil @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
sil @guaranteed_fakeoptional_klass_user : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
|
|
sil @guaranteed_fakeoptional_classlet_user : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> ()
|
|
sil @closure : $@convention(thin) (@inout_aliasable Klass) -> ()
|
|
sil @lendC : $@yield_once_2 @convention(thin) () -> @yields @guaranteed C
|
|
sil @useC : $@convention(thin) (@guaranteed C) -> () {
|
|
[global:]
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
struct TrivialStruct {
|
|
}
|
|
|
|
enum EnumA {
|
|
case none
|
|
case sometrivial(TrivialStruct)
|
|
case somenontrivial(NonTrivialStruct)
|
|
}
|
|
|
|
struct StructWithEnum {
|
|
var val: EnumA
|
|
}
|
|
sil @get_fakeoptional_nativeobject : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
|
|
sil @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
///////////
|
|
// Tests //
|
|
///////////
|
|
|
|
// Simple in_guaranteed argument load_copy.
|
|
// CHECK-LABEL: sil [ossa] @load_copy_from_in_guaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: load_borrow
|
|
// CHECK: load_borrow
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'load_copy_from_in_guaranteed'
|
|
sil [ossa] @load_copy_from_in_guaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*Builtin.NativeObject):
|
|
%g = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
// Simple same bb.
|
|
%1 = load [copy] %0 : $*Builtin.NativeObject
|
|
apply %g(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
|
|
// Diamond.
|
|
%2 = load [copy] %0 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
apply %g(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
// Consuming use blocks.
|
|
%3 = load [copy] %0 : $*Builtin.NativeObject
|
|
%4 = function_ref @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %4(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_base :
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dont_copy_let_properties_with_guaranteed_base'
|
|
sil [ossa] @dont_copy_let_properties_with_guaranteed_base : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%x : @guaranteed $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = ref_element_addr [immutable] %x : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%b = begin_borrow %v : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b : $Klass
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses :
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses'
|
|
sil [ossa] @dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%x : @guaranteed $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = ref_element_addr [immutable] %x : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%c = unchecked_ref_cast %v : $Klass to $Klass
|
|
%b = begin_borrow %c : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b : $Klass
|
|
destroy_value %c : $Klass
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_upcast_base :
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dont_copy_let_properties_with_guaranteed_upcast_base'
|
|
sil [ossa] @dont_copy_let_properties_with_guaranteed_upcast_base : $@convention(thin) (@guaranteed SubclassLet) -> () {
|
|
bb0(%x : @guaranteed $SubclassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%u = upcast %x : $SubclassLet to $ClassLet
|
|
%p = ref_element_addr [immutable] %u : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%b = begin_borrow %v : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b : $Klass
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_global :
|
|
// CHECK: global_addr
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: return
|
|
// CHECK-NEXT: } // end sil function 'dont_copy_let_global'
|
|
sil [ossa] @dont_copy_let_global : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = global_addr @a_let_global : $*Klass
|
|
%v = load [copy] %p : $*Klass
|
|
%b = begin_borrow %v : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b : $Klass
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_base_structural
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @dont_copy_let_properties_with_guaranteed_base_structural : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%x : @guaranteed $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = ref_element_addr [immutable] %x : $ClassLet, #ClassLet.aLetTuple
|
|
%q = tuple_element_addr %p : $*(Klass, Klass), 1
|
|
%v = load [copy] %q : $*Klass
|
|
%b = begin_borrow %v : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b : $Klass
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_copy_var_properties_with_guaranteed_base
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @do_copy_var_properties_with_guaranteed_base : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%x : @guaranteed $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = ref_element_addr %x : $ClassLet, #ClassLet.aVar
|
|
%v = load [copy] %p : $*Klass
|
|
apply %f(%v) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_copy_var_properties_with_guaranteed_base_unreachable :
|
|
// CHECK: ref_element_addr
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: unreachable
|
|
sil [ossa] @do_copy_var_properties_with_guaranteed_base_unreachable : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%x : @guaranteed $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = ref_element_addr %x : $ClassLet, #ClassLet.aVar
|
|
%v = load [copy] %p : $*Klass
|
|
apply %f(%v) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_copy_var_global
|
|
// CHECK: global_addr
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @do_copy_var_global : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%p = global_addr @a_var_global : $*Klass
|
|
%v = load [copy] %p : $*Klass
|
|
apply %f(%v) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates
|
|
// CHECK: [[OUTER:%.*]] = begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: [[INNER:%.*]] = load_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow [[INNER]]
|
|
// CHECK-NEXT: end_borrow [[OUTER]]
|
|
// CHECK-NEXT: destroy_value
|
|
sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
apply %f(%v) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %v : $Klass
|
|
|
|
end_borrow %a : $ClassLet
|
|
destroy_value %x : $ClassLet
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase :
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase'
|
|
sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLetTuple
|
|
%v = load [copy] %p : $*(Klass, Klass)
|
|
(%v1, %v2) = destructure_tuple %v : $(Klass, Klass)
|
|
apply %f(%v1) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%v2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %v1 : $Klass
|
|
destroy_value %v2 : $Klass
|
|
end_borrow %a : $ClassLet
|
|
destroy_value %x : $ClassLet
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase_2 :
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase_2'
|
|
sil [ossa] @dont_copy_let_properties_with_borrowed_base_that_dominates_projtestcase_2 : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%v_cast = unchecked_ref_cast %v : $Klass to $Builtin.NativeObject
|
|
apply %f(%v_cast) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %v_cast : $Builtin.NativeObject
|
|
end_borrow %a : $ClassLet
|
|
destroy_value %x : $ClassLet
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_multi_borrowed_base_that_dominates
|
|
// CHECK: [[OUTER:%.*]] = begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: [[INNER:%.*]] = load_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow [[INNER]]
|
|
// CHECK-NEXT: end_borrow [[OUTER]]
|
|
// CHECK-NEXT: [[OUTER:%.*]] = begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: [[INNER:%.*]] = load_borrow
|
|
// CHECK-NEXT: [[INNER2:%.*]] = begin_borrow [[INNER]]
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow [[INNER2]]
|
|
// CHECK-NEXT: end_borrow [[INNER]]
|
|
// CHECK-NEXT: end_borrow [[OUTER]]
|
|
// CHECK-NEXT: destroy_value
|
|
sil [ossa] @dont_copy_let_properties_with_multi_borrowed_base_that_dominates : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
apply %f(%v) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %v : $Klass
|
|
end_borrow %a : $ClassLet
|
|
|
|
%b = begin_borrow %x : $ClassLet
|
|
%q = ref_element_addr [immutable] %b : $ClassLet, #ClassLet.aLet
|
|
%w = load [copy] %q : $*Klass
|
|
%b2 = begin_borrow %w : $Klass
|
|
apply %f(%b2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %b2 : $Klass
|
|
destroy_value %w : $Klass
|
|
end_borrow %b : $ClassLet
|
|
|
|
destroy_value %x : $ClassLet
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_copy_let_properties_with_borrowed_base_that_does_not_dominate
|
|
// CHECK: begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: destroy_value
|
|
sil [ossa] @do_copy_let_properties_with_borrowed_base_that_does_not_dominate : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%b = begin_borrow %v : $Klass
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
// End the lifetime of the base object first...
|
|
end_borrow %a : $ClassLet
|
|
destroy_value %x : $ClassLet
|
|
|
|
// ...then end the lifetime of the copy.
|
|
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
end_borrow %b : $Klass
|
|
destroy_value %v : $Klass
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_or_dont_copy_let_properties_with_multi_borrowed_base_when_it_dominates_2 :
|
|
// CHECK: [[OUTER:%.*]] = begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: [[INNER:%.*]] = load_borrow
|
|
// CHECK-NEXT: [[INNER2:%.*]] = begin_borrow [[INNER]]
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow [[INNER2]]
|
|
// CHECK-NEXT: end_borrow [[INNER]]
|
|
// CHECK-NEXT: end_borrow [[OUTER]]
|
|
// CHECK-NEXT: begin_borrow
|
|
// CHECK-NEXT: ref_element_addr
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: enum
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK: } // end sil function 'do_or_dont_copy_let_properties_with_multi_borrowed_base_when_it_dominates_2'
|
|
sil [ossa] @do_or_dont_copy_let_properties_with_multi_borrowed_base_when_it_dominates_2 : $@convention(thin) (@owned ClassLet) -> () {
|
|
bb0(%x : @owned $ClassLet):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
%a = begin_borrow %x : $ClassLet
|
|
%p = ref_element_addr [immutable] %a : $ClassLet, #ClassLet.aLet
|
|
%v = load [copy] %p : $*Klass
|
|
%c = begin_borrow %v : $Klass
|
|
apply %f(%c) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %c : $Klass
|
|
destroy_value %v : $Klass
|
|
end_borrow %a : $ClassLet
|
|
|
|
%b = begin_borrow %x : $ClassLet
|
|
%q = ref_element_addr %b : $ClassLet, #ClassLet.aLet
|
|
%w = load [copy] %q : $*Klass
|
|
|
|
// End the lifetime of the base object first...
|
|
end_borrow %b : $ClassLet
|
|
destroy_value %x : $ClassLet
|
|
|
|
// ...then end the lifetime of the copy.
|
|
%f2 = function_ref @guaranteed_fakeoptional_klass_user : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
|
|
%w2 = enum $FakeOptional<Klass>, #FakeOptional.some!enumelt, %w : $Klass
|
|
apply %f2(%w2) : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
|
|
|
|
destroy_value %w2 : $FakeOptional<Klass>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// Make sure that we put the end_borrow on the load_borrow, not LHS or RHS.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @destructure_load_copy_to_load_borrow : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: [[INTERIOR_POINTER:%.*]] = ref_element_addr [immutable] [[ARG]]
|
|
// CHECK: [[BORROWED_VAL:%.*]] = load_borrow [[INTERIOR_POINTER]]
|
|
// CHECK: ([[LHS:%.*]], [[RHS:%.*]]) = destructure_tuple [[BORROWED_VAL]]
|
|
// CHECK: apply {{%.*}}([[LHS]])
|
|
// CHECK: apply {{%.*}}([[RHS]])
|
|
// CHECK: end_borrow [[BORROWED_VAL]]
|
|
// CHECK: } // end sil function 'destructure_load_copy_to_load_borrow'
|
|
sil [ossa] @destructure_load_copy_to_load_borrow : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr [immutable] %0 : $ClassLet, #ClassLet.aLetTuple
|
|
%2 = load [copy] %1 : $*(Klass, Klass)
|
|
(%3, %4) = destructure_tuple %2 : $(Klass, Klass)
|
|
%5 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%6 = apply %5(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%7 = apply %5(%4) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
destroy_value %4 : $Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @single_init_allocstack : $@convention(thin) (@owned Klass) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'single_init_allocstack'
|
|
sil [ossa] @single_init_allocstack : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Klass
|
|
%2 = load [copy] %1 : $*Klass
|
|
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
destroy_value %2 : $Klass
|
|
destroy_addr %1 : $*Klass
|
|
dealloc_stack %1 : $*Klass
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @multiple_init_allocstack : $@convention(thin) (@owned Klass) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'multiple_init_allocstack'
|
|
sil [ossa] @multiple_init_allocstack : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%0a = copy_value %0 : $Klass
|
|
%1 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Klass
|
|
%2 = load [copy] %1 : $*Klass
|
|
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
destroy_value %2 : $Klass
|
|
destroy_addr %1 : $*Klass
|
|
|
|
store %0a to [init] %1 : $*Klass
|
|
destroy_addr %1 : $*Klass
|
|
dealloc_stack %1 : $*Klass
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @single_init_different_block : $@convention(thin) (@owned Klass) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'single_init_different_block'
|
|
sil [ossa] @single_init_different_block : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = alloc_stack $Klass
|
|
br bb1
|
|
|
|
bb1:
|
|
store %0 to [init] %1 : $*Klass
|
|
%2 = load [copy] %1 : $*Klass
|
|
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
destroy_value %2 : $Klass
|
|
destroy_addr %1 : $*Klass
|
|
dealloc_stack %1 : $*Klass
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @single_init_loadtake : $@convention(thin) (@owned Klass) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: load [take]
|
|
// CHECK: } // end sil function 'single_init_loadtake'
|
|
sil [ossa] @single_init_loadtake : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Klass
|
|
%2 = load [copy] %1 : $*Klass
|
|
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
destroy_value %2 : $Klass
|
|
|
|
%4 = load [take] %1 : $*Klass
|
|
destroy_value %4 : $Klass
|
|
dealloc_stack %1 : $*Klass
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_1 : $@convention(thin) (@inout NativeObjectPair) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_1'
|
|
sil [ossa] @inout_argument_never_written_to_1 : $@convention(thin) (@inout NativeObjectPair) -> () {
|
|
bb0(%0 : $*NativeObjectPair):
|
|
%2 = load [copy] %0 : $*NativeObjectPair
|
|
(%3, %4) = destructure_struct %2 : $NativeObjectPair
|
|
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
destroy_value %4 : $Builtin.NativeObject
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_2 : $@convention(thin) (@inout NativeObjectPair) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_2'
|
|
sil [ossa] @inout_argument_never_written_to_2 : $@convention(thin) (@inout NativeObjectPair) -> () {
|
|
bb0(%0 : $*NativeObjectPair):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_3 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_3'
|
|
sil [ossa] @inout_argument_never_written_to_3 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We cannot handle this since the store is inside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_4 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_4'
|
|
sil [ossa] @inout_argument_never_written_to_4 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We cannot handle this since the store is inside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_4a : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_4a'
|
|
sil [ossa] @inout_argument_never_written_to_4a : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_5 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_5'
|
|
sil [ossa] @inout_argument_never_written_to_5 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_6 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_6'
|
|
sil [ossa] @inout_argument_never_written_to_6 : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_6a : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_6a'
|
|
sil [ossa] @inout_argument_never_written_to_6a : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
br bb0a
|
|
|
|
bb0a:
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_6b : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_6b'
|
|
sil [ossa] @inout_argument_never_written_to_6b : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
br bb0a
|
|
|
|
bb0a:
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We can handle this since the store is outside of our region.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_6c : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_6c'
|
|
sil [ossa] @inout_argument_never_written_to_6c : $@convention(thin) (@inout NativeObjectPair, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @owned $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%1a = copy_value %1 : $Builtin.NativeObject
|
|
store %1 to [assign] %2 : $*Builtin.NativeObject
|
|
br bb0a
|
|
|
|
bb0a:
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
store %1a to [assign] %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_1 : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_1'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_1 : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
%3 = load [copy] %2a : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
end_access %2a : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_1a : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_1a'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_1a : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_access %2a : $*Builtin.NativeObject
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_1b : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_1b'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_1b : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_access %2a : $*Builtin.NativeObject
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_1c : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_1c'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_1c : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
end_access %2a : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_2a : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_2a'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_2a : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
end_access %2a : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_2b : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_2b'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_2b : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%3 = load [copy] %2 : $*Builtin.NativeObject
|
|
br bb0a
|
|
|
|
bb0a:
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
end_access %2a : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_argument_never_written_to_begin_access_2c : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: bb2:
|
|
// CHECK: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK: } // end sil function 'inout_argument_never_written_to_begin_access_2c'
|
|
sil [ossa] @inout_argument_never_written_to_begin_access_2c : $@convention(thin) (@inout NativeObjectPair, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = struct_element_addr %0 : $*NativeObjectPair, #NativeObjectPair.obj1
|
|
%2a = begin_access [modify] [static] %2 : $*Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%3 = load [copy] %2a : $*Builtin.NativeObject
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb4
|
|
|
|
bb3:
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
br bb4
|
|
|
|
bb4:
|
|
end_access %2a : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_enum_test_loadcopy_no_default : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'switch_enum_test_loadcopy_no_default'
|
|
sil [ossa] @switch_enum_test_loadcopy_no_default : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
|
|
%0a = alloc_stack $FakeOptional<Builtin.NativeObject>
|
|
store %0 to [init] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%1 = load [copy] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
switch_enum %1 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%2 : @owned $Builtin.NativeObject):
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %0a : $*FakeOptional<Builtin.NativeObject>
|
|
dealloc_stack %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_enum_multi_payload :
|
|
// CHECK: %1 = load_borrow %0
|
|
// CHECK: bb1(%3 : @guaranteed $Klass):
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: bb2(%6 : $MyInt):
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: } // end sil function 'switch_enum_multi_payload'
|
|
sil [ossa] @switch_enum_multi_payload : $@convention(thin) (@inout MultiPayload) -> () {
|
|
bb0(%0 : $*MultiPayload):
|
|
%1 = load [copy] %0 : $*MultiPayload
|
|
switch_enum %1 : $MultiPayload, case #MultiPayload.a!enumelt: bb1, case #MultiPayload.b!enumelt: bb2
|
|
|
|
bb1(%3 : @owned $Klass):
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2(%6 : $MyInt):
|
|
br bb3
|
|
|
|
bb3:
|
|
%8 = tuple()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_enum_test_loadcopy_with_default : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'switch_enum_test_loadcopy_with_default'
|
|
sil [ossa] @switch_enum_test_loadcopy_with_default : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
|
|
%0a = alloc_stack $FakeOptional<Builtin.NativeObject>
|
|
store %0 to [init] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%1 = load [copy] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
switch_enum %1 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt: bb1, default bb2
|
|
|
|
bb1(%2 : @owned $Builtin.NativeObject):
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %0a : $*FakeOptional<Builtin.NativeObject>
|
|
dealloc_stack %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_enum_test_loadcopy_with_leaked_enum_case : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'switch_enum_test_loadcopy_with_leaked_enum_case'
|
|
sil [ossa] @switch_enum_test_loadcopy_with_leaked_enum_case : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
|
|
%0a = alloc_stack $FakeOptional<Builtin.NativeObject>
|
|
store %0 to [init] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%1 = load [copy] %0a : $*FakeOptional<Builtin.NativeObject>
|
|
switch_enum %1 : $FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%2 : @owned $Builtin.NativeObject):
|
|
destroy_value [dead_end] %2 : $Builtin.NativeObject
|
|
unreachable
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %0a : $*FakeOptional<Builtin.NativeObject>
|
|
dealloc_stack %0a : $*FakeOptional<Builtin.NativeObject>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_functionarg : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'convert_load_copy_to_load_borrow_despite_switch_enum_functionarg'
|
|
sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_functionarg : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> () {
|
|
bb0(%0 : @guaranteed $FakeOptional<ClassLet>):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
switch_enum %0 : $FakeOptional<ClassLet>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%1 : @guaranteed $ClassLet):
|
|
%2 = ref_element_addr [immutable] %1 : $ClassLet, #ClassLet.aLet
|
|
%3 = load [copy] %2 : $*Klass
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_beginborrow : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'convert_load_copy_to_load_borrow_despite_switch_enum_beginborrow'
|
|
sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_beginborrow : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<ClassLet>):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%0a = begin_borrow %0 : $FakeOptional<ClassLet>
|
|
switch_enum %0a : $FakeOptional<ClassLet>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%1 : @guaranteed $ClassLet):
|
|
%2 = ref_element_addr [immutable] %1 : $ClassLet, #ClassLet.aLet
|
|
%3 = load [copy] %2 : $*Klass
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
end_borrow %0a : $FakeOptional<ClassLet>
|
|
destroy_value %0 : $FakeOptional<ClassLet>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_loadborrow : $@convention(thin) (@in_guaranteed FakeOptional<ClassLet>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'convert_load_copy_to_load_borrow_despite_switch_enum_loadborrow'
|
|
sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_loadborrow : $@convention(thin) (@in_guaranteed FakeOptional<ClassLet>) -> () {
|
|
bb0(%0 : $*FakeOptional<ClassLet>):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%0a = load_borrow %0 : $*FakeOptional<ClassLet>
|
|
switch_enum %0a : $FakeOptional<ClassLet>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%1 : @guaranteed $ClassLet):
|
|
%2 = ref_element_addr [immutable] %1 : $ClassLet, #ClassLet.aLet
|
|
%3 = load [copy] %2 : $*Klass
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
end_borrow %0a : $FakeOptional<ClassLet>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// TODO: We can support this in a little bit once the rest of SemanticARCOpts is
|
|
// guaranteed to be safe with guaranteed phis.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_1 : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_1'
|
|
sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_1 : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<ClassLet>):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
cond_br undef, bb0a, bb0b
|
|
|
|
bb0a:
|
|
%0a = begin_borrow %0 : $FakeOptional<ClassLet>
|
|
br bb0c(%0a : $FakeOptional<ClassLet>)
|
|
|
|
bb0b:
|
|
%0b = begin_borrow %0 : $FakeOptional<ClassLet>
|
|
br bb0c(%0b : $FakeOptional<ClassLet>)
|
|
|
|
bb0c(%0c : @guaranteed $FakeOptional<ClassLet>):
|
|
%0d = borrowed %0c : $FakeOptional<ClassLet> from (%0: $FakeOptional<ClassLet>)
|
|
switch_enum %0d : $FakeOptional<ClassLet>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%1 : @guaranteed $ClassLet):
|
|
%2 = ref_element_addr [immutable] %1 : $ClassLet, #ClassLet.aLet
|
|
%3 = load [copy] %2 : $*Klass
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
end_borrow %0d : $FakeOptional<ClassLet>
|
|
destroy_value %0 : $FakeOptional<ClassLet>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that if begin_borrow has a consuming end scope use, we can still
|
|
// eliminate load [copy].
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_2 : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_2'
|
|
sil [ossa] @convert_load_copy_to_load_borrow_despite_switch_enum_guaranteedphi_2 : $@convention(thin) (@owned FakeOptional<ClassLet>) -> () {
|
|
bb0(%0 : @owned $FakeOptional<ClassLet>):
|
|
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%0a = begin_borrow %0 : $FakeOptional<ClassLet>
|
|
br bb3(%0a : $FakeOptional<ClassLet>)
|
|
|
|
bb2:
|
|
%0b = begin_borrow %0 : $FakeOptional<ClassLet>
|
|
%0b2 = unchecked_enum_data %0b : $FakeOptional<ClassLet>, #FakeOptional.some!enumelt
|
|
%2 = ref_element_addr [immutable] %0b2 : $ClassLet, #ClassLet.aLet
|
|
%3 = load [copy] %2 : $*Klass
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
br bb3(%0b : $FakeOptional<ClassLet>)
|
|
|
|
bb3(%0c : @guaranteed $FakeOptional<ClassLet>):
|
|
%0d = borrowed %0c : $FakeOptional<ClassLet> from (%0: $FakeOptional<ClassLet>)
|
|
%f2 = function_ref @guaranteed_fakeoptional_classlet_user : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> ()
|
|
apply %f2(%0d) : $@convention(thin) (@guaranteed FakeOptional<ClassLet>) -> ()
|
|
end_borrow %0d : $FakeOptional<ClassLet>
|
|
destroy_value %0 : $FakeOptional<ClassLet>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_read_access : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_read_access'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_read_access : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [read] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
end_access %2 : $*Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_mut_access_without_writes : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_mut_access_without_writes'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_mut_access_without_writes : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [modify] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
end_access %2 : $*Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: load_borrow
|
|
// CHECK-NOT: load [copy]
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_mut_access_with_writes'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [modify] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
destroy_addr %2 : $*Klass
|
|
end_access %2 : $*Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We will never be able to handle this unless we can hoist the copy before the
|
|
// destroy_addr. Once we have begin_borrows around all interior_pointers, we can
|
|
// handle this version.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_2 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: load [copy]
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_mut_access_with_writes_2'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_2 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [modify] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_addr %2 : $*Klass
|
|
destroy_value %3 : $Klass
|
|
end_access %2 : $*Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We will never be able to handle this since we can't hoist the destroy_value
|
|
// before the guaranteed_klass_user.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_3 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: load [copy]
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_mut_access_with_writes_3'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_3 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [modify] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
destroy_addr %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
end_access %2 : $*Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We will never be able to handle this since the end_access is before the use
|
|
// of %3, so we can not form a long enough load_borrow.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_4 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: load [copy]
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: } // end sil function 'loadcopy_to_loadborrow_from_mut_access_with_writes_4'
|
|
sil [ossa] @loadcopy_to_loadborrow_from_mut_access_with_writes_4 : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = begin_access [modify] [dynamic] %1 : $*Klass
|
|
%3 = load [copy] %2 : $*Klass
|
|
end_access %2 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %3 : $Klass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that we do not promote the load [copy] to a load_borrow since it
|
|
// has a use outside of the access scope.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @deadEndBlockDoNotPromote : $@convention(method) (@guaranteed ClassLet) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'deadEndBlockDoNotPromote'
|
|
sil [ossa] @deadEndBlockDoNotPromote : $@convention(method) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%4 = ref_element_addr %0 : $ClassLet, #ClassLet.anotherLet
|
|
%5 = load [copy] %4 : $*ClassLet
|
|
%6 = begin_borrow %5 : $ClassLet
|
|
%7 = ref_element_addr %6 : $ClassLet, #ClassLet.anOptionalLet
|
|
%8 = begin_access [read] [dynamic] %7 : $*FakeOptional<Klass>
|
|
%9 = load [copy] %8 : $*FakeOptional<Klass>
|
|
end_access %8 : $*FakeOptional<Klass>
|
|
end_borrow %6 : $ClassLet
|
|
destroy_value %5 : $ClassLet
|
|
switch_enum %9 : $FakeOptional<Klass>, case #FakeOptional.none!enumelt: bb1, case #FakeOptional.some!enumelt: bb2
|
|
|
|
bb1:
|
|
%107 = tuple ()
|
|
return %107 : $()
|
|
|
|
bb2(%39 : @owned $Klass):
|
|
destroy_value [dead_end] %39 : $Klass
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @destructure_with_differing_lifetimes_inout_1 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> () {
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: } // end sil function 'destructure_with_differing_lifetimes_inout_1'
|
|
sil [ossa] @destructure_with_differing_lifetimes_inout_1 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> () {
|
|
bb0(%0 : $*FakeOptionalNativeObjectPairPair):
|
|
%0a = struct_element_addr %0 : $*FakeOptionalNativeObjectPairPair, #FakeOptionalNativeObjectPairPair.pair1
|
|
%1 = load [copy] %0a : $*FakeOptional<NativeObjectPair>
|
|
switch_enum %1 : $FakeOptional<NativeObjectPair>, case #FakeOptional.some!enumelt: bb1, default bb2
|
|
|
|
bb2:
|
|
br bbEnd
|
|
|
|
bb1(%3 : @owned $NativeObjectPair):
|
|
(%3a, %3b) = destructure_struct %3 : $NativeObjectPair
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
destroy_value %3a : $Builtin.NativeObject
|
|
destroy_value %3b : $Builtin.NativeObject
|
|
br bbEnd
|
|
|
|
bb1b:
|
|
destroy_value %3a : $Builtin.NativeObject
|
|
%f = function_ref @inout_user2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
apply %f(%0) : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
destroy_value %3b : $Builtin.NativeObject
|
|
br bbEnd
|
|
|
|
bbEnd:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @destructure_with_differing_lifetimes_inout_2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> () {
|
|
// CHECK-NOT: load_borrow
|
|
// CHECK: } // end sil function 'destructure_with_differing_lifetimes_inout_2'
|
|
sil [ossa] @destructure_with_differing_lifetimes_inout_2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> () {
|
|
bb0(%0 : $*FakeOptionalNativeObjectPairPair):
|
|
%0a = struct_element_addr %0 : $*FakeOptionalNativeObjectPairPair, #FakeOptionalNativeObjectPairPair.pair1
|
|
%1 = load [copy] %0a : $*FakeOptional<NativeObjectPair>
|
|
switch_enum %1 : $FakeOptional<NativeObjectPair>, case #FakeOptional.some!enumelt: bb1, default bb2
|
|
|
|
bb2:
|
|
br bbEnd
|
|
|
|
bb1(%3 : @owned $NativeObjectPair):
|
|
(%3a, %3b) = destructure_struct %3 : $NativeObjectPair
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
destroy_value %3a : $Builtin.NativeObject
|
|
br bb1ab
|
|
|
|
bb1ab:
|
|
destroy_value %3b : $Builtin.NativeObject
|
|
br bbEnd
|
|
|
|
bb1b:
|
|
destroy_value %3a : $Builtin.NativeObject
|
|
%f = function_ref @inout_user2 : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
apply %f(%0) : $@convention(thin) (@inout FakeOptionalNativeObjectPairPair) -> ()
|
|
cond_br undef, bb1ba, bb1bb
|
|
|
|
bb1ba:
|
|
br bb1baEnd
|
|
|
|
bb1bb:
|
|
br bb1baEnd
|
|
|
|
bb1baEnd:
|
|
destroy_value %3b : $Builtin.NativeObject
|
|
br bbEnd
|
|
|
|
bbEnd:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Just make sure that we do not crash on this code
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @improper_dead_end_block_crasher_test : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
// CHECK: } // end sil function 'improper_dead_end_block_crasher_test'
|
|
sil [ossa] @improper_dead_end_block_crasher_test : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Klass
|
|
%2 = load_borrow %1 : $*Klass
|
|
%3 = ref_element_addr %2 : $Klass, #Klass.baseLet
|
|
%4 = load [copy] %3 : $*Klass
|
|
%f = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %f(%4) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %4 : $Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
unreachable
|
|
|
|
bb2:
|
|
unreachable
|
|
}
|
|
|
|
// Make sure that we ignore type dependent operands when walking through the use
|
|
// list to determine if we are writing to a piece of memory.
|
|
protocol HasClassProperty {
|
|
var c: Klass { get set }
|
|
}
|
|
|
|
struct HasClassPropertyWrapper {
|
|
var h: HasClassProperty
|
|
var otherProperty: Builtin.NativeObject
|
|
}
|
|
|
|
sil @use_hasclassproperty : $@convention(method) <τ_0_0 where τ_0_0 : HasClassProperty> (@inout τ_0_0) -> (@owned Builtin.NativeObject, @error Error)
|
|
|
|
// Make sure we don't crash on this code. We used to crash by not ignoring the
|
|
// type dependent operand usage of %2.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @use_class_property_wrapper : $@convention(thin) (@inout HasClassPropertyWrapper) -> () {
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'use_class_property_wrapper'
|
|
sil [ossa] @use_class_property_wrapper : $@convention(thin) (@inout HasClassPropertyWrapper) -> () {
|
|
bb0(%0 : $*HasClassPropertyWrapper):
|
|
%1 = struct_element_addr %0 : $*HasClassPropertyWrapper, #HasClassPropertyWrapper.h
|
|
%2 = open_existential_addr mutable_access %1 : $*HasClassProperty to $*@opened("85AB1D00-DF62-11EB-A413-ACDE48001122", HasClassProperty) Self
|
|
%3 = function_ref @use_hasclassproperty : $@convention(method) <τ_0_0 where τ_0_0 : HasClassProperty> (@inout τ_0_0) -> (@owned Builtin.NativeObject, @error Error)
|
|
%4 = struct_element_addr %0 : $*HasClassPropertyWrapper, #HasClassPropertyWrapper.otherProperty
|
|
%5 = load [copy] %4 : $*Builtin.NativeObject
|
|
%f2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %f2(%5) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
try_apply %3<@opened("85AB1D00-DF62-11EB-A413-ACDE48001122", HasClassProperty) Self>(%2) : $@convention(method) <τ_0_0 where τ_0_0 : HasClassProperty> (@inout τ_0_0) -> (@owned Builtin.NativeObject, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%str : @owned $Builtin.NativeObject):
|
|
destroy_value %str : $Builtin.NativeObject
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2(%error : @owned $Error):
|
|
destroy_value %error : $Error
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure we don't crash on this code. We used to crash for @out args on the access path to the load
|
|
sil [ossa] @test_opt_out_arg : $@convention(thin)(@in NonTrivialStruct) -> (@out NonTrivialStruct) {
|
|
bb0(%0 : $*NonTrivialStruct, %1 : $*NonTrivialStruct):
|
|
copy_addr %1 to [init] %0 : $*NonTrivialStruct
|
|
%ele = struct_element_addr %0 : $*NonTrivialStruct, #NonTrivialStruct.val
|
|
%ld = load [copy] %ele : $*Klass
|
|
destroy_value %ld : $Klass
|
|
destroy_addr %1 : $*NonTrivialStruct
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_enum_test :
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'switch_enum_test'
|
|
sil [ossa] @switch_enum_test : $@convention(thin) (@inout StructWithEnum) -> () {
|
|
bb0(%0 : $*StructWithEnum):
|
|
%1 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
|
|
%2 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
|
|
%3 = load [copy] %2 : $*EnumA
|
|
destroy_addr %1 : $*EnumA
|
|
switch_enum %3 : $EnumA, case #EnumA.sometrivial!enumelt: bb1, case #EnumA.somenontrivial!enumelt:bb2, case #EnumA.none!enumelt: bb3
|
|
|
|
bb1(%6 : $TrivialStruct):
|
|
%f = function_ref @get_enum : $@convention(thin) () -> @owned EnumA
|
|
%r = apply %f() : $@convention(thin) () -> @owned EnumA
|
|
%ele = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
|
|
store %r to [init] %ele :$*EnumA
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
|
|
bb2(%7 : @owned $NonTrivialStruct):
|
|
destroy_value [dead_end] %7 : $NonTrivialStruct
|
|
unreachable
|
|
|
|
bb3:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @promote_moved_from_load_copy : {{.*}} {
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $C
|
|
// CHECK: [[GET_C:%[^,]+]] = function_ref @getC
|
|
// CHECK: [[STORED:%[^,]+]] = apply [[GET_C]]()
|
|
// CHECK: store [[STORED]] to [init] [[ADDR]]
|
|
// CHECK: [[LOADED:%[^,]+]] = load_borrow [[ADDR]]
|
|
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[LOADED]]
|
|
// CHECK: end_borrow [[LIFETIME]]
|
|
// CHECK: end_borrow [[LOADED]]
|
|
// CHECK: destroy_addr [[ADDR]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'promote_moved_from_load_copy'
|
|
sil [ossa] @promote_moved_from_load_copy : $@convention(thin) () -> () {
|
|
bb0:
|
|
%addr = alloc_stack $C
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%stored = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %stored to [init] %addr : $*C
|
|
%loaded = load [copy] %addr : $*C
|
|
debug_value %loaded : $C, let, name "x"
|
|
%lifetime = move_value [lexical] %loaded : $C
|
|
destroy_value %lifetime : $C
|
|
destroy_addr %addr : $*C
|
|
dealloc_stack %addr : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_promote_moved_from_load_copy_with_destroy_addr_above_range : {{.*}} {
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'dont_promote_moved_from_load_copy_with_destroy_addr_above_range'
|
|
sil [ossa] @dont_promote_moved_from_load_copy_with_destroy_addr_above_range : $@convention(thin) () -> () {
|
|
bb0:
|
|
%addr = alloc_stack $C
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%stored = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %stored to [init] %addr : $*C
|
|
%loaded = load [copy] %addr : $*C
|
|
destroy_addr %addr : $*C
|
|
%lifetime = move_value [lexical] %loaded : $C
|
|
destroy_value %lifetime : $C
|
|
dealloc_stack %addr : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_take_between_load_copy_and_move_inout : {{.*}} {
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'load_take_between_load_copy_and_move_inout'
|
|
sil [ossa] @load_take_between_load_copy_and_move_inout : $@convention(thin) (@inout C) -> () {
|
|
entry(%addr : $*C):
|
|
%v1 = load [copy] %addr : $*C
|
|
%v2 = load [take] %addr : $*C
|
|
%m1 = move_value [lexical] %v1 : $C
|
|
destroy_value %m1 : $C
|
|
store %v2 to [init] %addr : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_take_between_load_copy_and_move_stack : {{.*}} {
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'load_take_between_load_copy_and_move_stack'
|
|
sil [ossa] @load_take_between_load_copy_and_move_stack : $@convention(thin) () -> () {
|
|
entry:
|
|
%addr = alloc_stack $C
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%stored = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %stored to [init] %addr : $*C
|
|
|
|
%v1 = load [copy] %addr : $*C
|
|
%v2 = load [take] %addr : $*C
|
|
%m1 = move_value [lexical] %v1 : $C
|
|
destroy_value %m1 : $C
|
|
store %v2 to [init] %addr : $*C
|
|
|
|
destroy_addr %addr : $*C
|
|
dealloc_stack %addr : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @store_borrow_unaliased :
|
|
// CHECK: load_borrow
|
|
// CHECK-LABEL: } // end sil function 'store_borrow_unaliased'
|
|
sil [ossa] @store_borrow_unaliased : $@convention(thin) (@guaranteed C, @in_guaranteed C) -> () {
|
|
bb0(%0 : @guaranteed $C, %1 : $*C):
|
|
%2 = alloc_stack $C
|
|
%3 = store_borrow %0 to %2 : $*C
|
|
%4 = load [copy] %1 : $*C
|
|
end_borrow %3 : $*C
|
|
destroy_value %4 : $C
|
|
dealloc_stack %2 : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @store_borrow_aliased :
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'store_borrow_aliased'
|
|
sil [ossa] @store_borrow_aliased : $@convention(thin) (@guaranteed C) -> () {
|
|
bb0(%0 : @guaranteed $C):
|
|
%1 = alloc_stack $C
|
|
%2 = store_borrow %0 to %1 : $*C
|
|
%3 = load [copy] %2 : $*C
|
|
end_borrow %2 : $*C
|
|
destroy_value %3 : $C
|
|
dealloc_stack %1 : $*C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_extends_borrow_scope :
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'load_extends_borrow_scope'
|
|
sil [ossa] @load_extends_borrow_scope : $@convention(thin) (@owned Klass) -> @owned Klass {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = begin_borrow %0 : $Klass
|
|
%2 = ref_element_addr %1 : $Klass, #Klass.base
|
|
%3 = load [copy] %2 : $*Klass
|
|
end_borrow %1 : $Klass
|
|
destroy_value %3 : $Klass
|
|
return %0 : $Klass
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @write_in_unreachable_block :
|
|
// CHECK: load [copy]
|
|
// CHECK-LABEL: } // end sil function 'write_in_unreachable_block'
|
|
sil [ossa] @write_in_unreachable_block : $@convention(thin) (@inout Klass) -> () {
|
|
bb0(%0 : $*Klass):
|
|
%1 = load [copy] %0 : $*Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%3 = begin_borrow %1 : $Klass
|
|
%4 = ref_element_addr %3 : $Klass, #Klass.baseLet
|
|
destroy_addr %0 : $*Klass
|
|
%5 = load [copy] %4 : $*Klass
|
|
end_borrow %3 : $Klass
|
|
destroy_value [dead_end] %1 : $Klass
|
|
destroy_value [dead_end] %5 : $Klass
|
|
unreachable
|
|
|
|
bb2:
|
|
destroy_value %1 : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @no_write_in_unreachable_block :
|
|
// CHECK: load_borrow
|
|
// CHECK-LABEL: } // end sil function 'no_write_in_unreachable_block'
|
|
sil [ossa] @no_write_in_unreachable_block : $@convention(thin) (@inout Klass) -> () {
|
|
bb0(%0 : $*Klass):
|
|
%1 = load [copy] %0 : $*Klass
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%3 = begin_borrow %1 : $Klass
|
|
%4 = ref_element_addr %3 : $Klass, #Klass.baseLet
|
|
%5 = load [copy] %4 : $*Klass
|
|
unreachable
|
|
|
|
bb2:
|
|
destroy_value %1 : $Klass
|
|
br bb3
|
|
|
|
bb3:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend : $@convention(thin) (@in_guaranteed EnumWithIndirectCase) -> () {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK: } // end sil function 'enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend'
|
|
sil [ossa] @enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend : $@convention(thin) (@in_guaranteed EnumWithIndirectCase) -> () {
|
|
bb0(%0 : $*EnumWithIndirectCase):
|
|
%1 = load [copy] %0 : $*EnumWithIndirectCase
|
|
switch_enum %1 : $EnumWithIndirectCase, case #EnumWithIndirectCase.first!enumelt: bb1, case #EnumWithIndirectCase.second!enumelt: bb2
|
|
|
|
bb1:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
|
|
// NOTE: Eventually this will need to be changed when project_box has to be
|
|
// guarded by begin_borrow.
|
|
bb2(%2 : @owned ${ var Builtin.NativeObject }):
|
|
%3 = project_box %2 : ${ var Builtin.NativeObject }, 0
|
|
%4 = load [copy] %3 : $*Builtin.NativeObject
|
|
%user = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %user(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend_2 : $@convention(thin) (@in_guaranteed EnumWithIndirectCase) -> () {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: load_borrow
|
|
// CHECK: } // end sil function 'enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend_2'
|
|
sil [ossa] @enum_with_indirect_case_projectbox_loadcopy_to_loadborrow_deadend_2 : $@convention(thin) (@in_guaranteed EnumWithIndirectCase) -> () {
|
|
bb0(%0 : $*EnumWithIndirectCase):
|
|
%1 = load [copy] %0 : $*EnumWithIndirectCase
|
|
switch_enum %1 : $EnumWithIndirectCase, case #EnumWithIndirectCase.first!enumelt: bb1, case #EnumWithIndirectCase.second!enumelt: bb2
|
|
|
|
bb1:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
|
|
// NOTE: Eventually this will need to be changed when project_box has to be
|
|
// guarded by begin_borrow.
|
|
bb2(%2 : @owned ${ var Builtin.NativeObject }):
|
|
%3 = project_box %2 : ${ var Builtin.NativeObject }, 0
|
|
%4 = load [copy] %3 : $*Builtin.NativeObject
|
|
%user = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %user(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
destroy_value %2 : ${ var Builtin.NativeObject }
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @use_interior_pointer_in_deadend_block :
|
|
// CHECK: load [copy]
|
|
// CHECK: } // end sil function 'use_interior_pointer_in_deadend_block'
|
|
sil [ossa] @use_interior_pointer_in_deadend_block : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = load [copy] %1 : $*Klass
|
|
%3 = begin_borrow %2 : $Klass
|
|
%4 = ref_element_addr %3 : $Klass, #Klass.base
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %f(%4) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
unreachable
|
|
|
|
bb2:
|
|
end_borrow %3 : $Klass
|
|
destroy_value %2 : $Klass
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @use_interior_pointer_not_in_deadend_block :
|
|
// CHECK: load_borrow
|
|
// CHECK: } // end sil function 'use_interior_pointer_not_in_deadend_block'
|
|
sil [ossa] @use_interior_pointer_not_in_deadend_block : $@convention(thin) (@guaranteed ClassLet) -> () {
|
|
bb0(%0 : @guaranteed $ClassLet):
|
|
%1 = ref_element_addr %0 : $ClassLet, #ClassLet.aVar
|
|
%2 = load [copy] %1 : $*Klass
|
|
%3 = begin_borrow %2 : $Klass
|
|
%4 = ref_element_addr %3 : $Klass, #Klass.base
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %f(%1) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
unreachable
|
|
|
|
bb2:
|
|
end_borrow %3 : $Klass
|
|
destroy_value %2 : $Klass
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @multiple_destroys_and_switch_enum :
|
|
// CHECK: bb0(%0 : $*OptionalAndClass):
|
|
// CHECK-NEXT: %1 = load_borrow
|
|
// CHECK-NOT: end_borrow
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: } // end sil function 'multiple_destroys_and_switch_enum'
|
|
sil [ossa] @multiple_destroys_and_switch_enum : $@convention(thin) (@in_guaranteed OptionalAndClass) -> () {
|
|
bb0(%0 : $*OptionalAndClass):
|
|
%1 = load [copy] %0 : $*OptionalAndClass
|
|
(%2, %3) = destructure_struct %1 : $OptionalAndClass
|
|
switch_enum %2 : $FakeOptional<C>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1(%5 : @owned $C):
|
|
destroy_value %5 : $C
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %3 : $C
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_copy_with_borrow_users :
|
|
// CHECK: %1 = load_borrow
|
|
// CHECK: end_borrow %1
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK: } // end sil function 'load_copy_with_borrow_users'
|
|
sil [ossa] @load_copy_with_borrow_users : $@convention(thin) (@inout Klass) -> () {
|
|
bb0(%0 : $*Klass):
|
|
%ld1 = load [copy] %0 : $*Klass
|
|
%b = begin_borrow %ld1 : $Klass
|
|
%c = copy_value %b : $Klass
|
|
%stk = alloc_stack $Klass
|
|
store %c to [init] %stk : $*Klass
|
|
%f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %f(%stk) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
%ld2 = load [take] %stk : $*Klass
|
|
destroy_value %ld2 : $Klass
|
|
dealloc_stack %stk : $*Klass
|
|
end_borrow %b : $Klass
|
|
destroy_value %ld1 : $Klass
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @pa_user :
|
|
// CHECK: %1 = load_borrow
|
|
// CHECK: %2 = begin_borrow %1
|
|
// CHECK: end_borrow %2
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: } // end sil function 'pa_user'
|
|
sil [ossa] @pa_user : $@convention(thin) (@inout Klass) -> () {
|
|
bb0(%0 : $*Klass):
|
|
%ld1 = load [copy] %0 : $*Klass
|
|
%b = begin_borrow %ld1 : $Klass
|
|
%c = copy_value %b : $Klass
|
|
%stk = alloc_stack $Klass
|
|
store %c to [init] %stk : $*Klass
|
|
%f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %f(%stk) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
%ld2 = load [take] %stk : $*Klass
|
|
destroy_value %ld2 : $Klass
|
|
dealloc_stack %stk : $*Klass
|
|
end_borrow %b : $Klass
|
|
destroy_value %ld1 : $Klass
|
|
%closure = function_ref @closure : $@convention(thin) (@inout_aliasable Klass) -> ()
|
|
%pa = partial_apply [callee_guaranteed] [on_stack] %closure(%0) : $@convention(thin) (@inout_aliasable Klass) -> ()
|
|
destroy_value %pa : $@noescape @callee_guaranteed () -> ()
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @not_refcount_preserving_cast :
|
|
// CHECK: %1 = load [copy] %0
|
|
// CHECK: } // end sil function 'not_refcount_preserving_cast'
|
|
sil [ossa] @not_refcount_preserving_cast : $@convention(thin) (@inout AnyObject) -> () {
|
|
bb0(%0 : $*AnyObject):
|
|
%1 = load [copy] %0 : $*AnyObject
|
|
checked_cast_br AnyObject in %1 : $AnyObject to Klass, bb1, bb2
|
|
|
|
bb1(%3 : @owned $Klass):
|
|
destroy_value %3 : $Klass
|
|
br bb3
|
|
|
|
bb2(%6 : @owned $AnyObject):
|
|
destroy_value %6 : $AnyObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_end_loop :
|
|
// CHECK: %1 = load [copy] %0
|
|
// CHECK: } // end sil function 'dead_end_loop'
|
|
sil [ossa] @dead_end_loop : $@convention(thin) (@inout Klass) -> () {
|
|
bb0(%0 : $*Klass):
|
|
%1 = load [copy] %0 : $*Klass
|
|
cond_br undef, bb5, bb1
|
|
bb1:
|
|
br bb2
|
|
bb2:
|
|
%4 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %4(%1) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%6 = function_ref @getKlass : $@convention(thin) () -> @owned Klass
|
|
%7 = apply %6() : $@convention(thin) () -> @owned Klass
|
|
store %7 to [assign] %0 : $*Klass
|
|
cond_br undef, bb4, bb3
|
|
bb3:
|
|
br bb2
|
|
bb4:
|
|
unreachable
|
|
bb5:
|
|
destroy_value %1 : $Klass
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @blocked_by_end_borrow :
|
|
// CHECK: %7 = load [copy] %6
|
|
// CHECK: } // end sil function 'blocked_by_end_borrow'
|
|
sil [ossa] @blocked_by_end_borrow : $@convention(thin) (@guaranteed Container) -> () {
|
|
bb0(%0 : @guaranteed $Container):
|
|
%1 = function_ref @useC : $@convention(thin) (@guaranteed C) -> ()
|
|
%2 = ref_element_addr [immutable] %0 : $Container, #Container.b
|
|
%3 = load_borrow %2 : $*Base
|
|
%4 = unconditional_checked_cast %3 : $Base to Derived
|
|
%5 = upcast %4 : $Derived to $Base
|
|
%6 = ref_element_addr [immutable] %5 : $Base, #Base.c
|
|
%7 = load [copy] %6 : $*C
|
|
end_borrow %3 : $Base
|
|
%9 = apply %1(%7) : $@convention(thin) (@guaranteed C) -> ()
|
|
destroy_value %7 : $C
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_copy_of_guaranteed_arg :
|
|
// CHECK: %1 = destructure_struct %0
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'remove_copy_of_guaranteed_arg'
|
|
sil [ossa] @remove_copy_of_guaranteed_arg : $@convention(thin) (@guaranteed NonTrivialStruct) -> @owned Klass {
|
|
bb0(%0 : @guaranteed $NonTrivialStruct):
|
|
%1 = copy_value %0
|
|
%2 = destructure_struct %1
|
|
%3 = begin_borrow %2
|
|
%4 = ref_element_addr %3, #Klass.base
|
|
%5 = load [copy] %4 : $*Klass
|
|
end_borrow %3
|
|
destroy_value %2
|
|
return %5
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_copy_of_borrow :
|
|
// CHECK: %3 = apply %2(%1)
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'remove_copy_of_borrow'
|
|
sil [ossa] @remove_copy_of_borrow : $@convention(thin) (@owned Klass) -> @owned Klass {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = begin_borrow %0
|
|
%2 = copy_value %1
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %2
|
|
end_borrow %1
|
|
return %0
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_remove_copy_of_borrow :
|
|
// CHECK: %2 = copy_value %1
|
|
// CHECK: } // end sil function 'dont_remove_copy_of_borrow'
|
|
sil [ossa] @dont_remove_copy_of_borrow : $@convention(thin) (@owned Klass) -> @owned Klass {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = begin_borrow %0
|
|
%2 = copy_value %1
|
|
%3 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
end_borrow %1
|
|
%4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %2
|
|
return %0
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_copy_of_forwarded_borrow :
|
|
// CHECK: [[DS:%.*]] = destructure_struct
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: apply {{%[0-9]+}}([[DS]])
|
|
// CHECK: } // end sil function 'remove_copy_of_forwarded_borrow'
|
|
sil [ossa] @remove_copy_of_forwarded_borrow : $@convention(thin) (@owned Optional<NonTrivialStruct>) -> @owned Optional<NonTrivialStruct> {
|
|
bb0(%0 : @owned $Optional<NonTrivialStruct>):
|
|
%1 = begin_borrow %0
|
|
switch_enum %1, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
bb1(%3 : @guaranteed $NonTrivialStruct):
|
|
%4 = destructure_struct %3
|
|
%5 = copy_value %4
|
|
%6 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%7 = apply %6(%5) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
destroy_value %5
|
|
br bb3
|
|
bb2:
|
|
br bb3
|
|
bb3:
|
|
end_borrow %1
|
|
return %0
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @user_in_dead_end_block :
|
|
// CHECK: %2 = copy_value %1
|
|
// CHECK: } // end sil function 'user_in_dead_end_block'
|
|
sil [ossa] @user_in_dead_end_block : $@convention(thin) (@owned Klass) -> @owned Klass {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = begin_borrow %0
|
|
%2 = copy_value %1
|
|
end_borrow %1
|
|
%4 = function_ref @guaranteed_klass_user : $@convention(thin) (@guaranteed Klass) -> ()
|
|
%5 = apply %4(%2) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @end_borrows_in_liferange_exit_block :
|
|
// CHECK: %1 = load_borrow %0
|
|
// CHECK: %2 = begin_borrow [lexical] %1
|
|
// CHECK: bb1({{.*}} : @guaranteed $C):
|
|
// CHECK-NEXT: end_borrow %2
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: end_borrow %2
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: } // end sil function 'end_borrows_in_liferange_exit_block'
|
|
sil [ossa] @end_borrows_in_liferange_exit_block : $@convention(thin) (@in_guaranteed Optional<C>) -> () {
|
|
bb0(%0 : $*Optional<C>):
|
|
%1 = load [copy] %0
|
|
%2 = move_value [lexical] %1
|
|
switch_enum %2, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%4 : @owned $C):
|
|
destroy_value %4
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @lifetime_ending_enum_data :
|
|
// CHECK: %1 = load_borrow %0
|
|
// CHECK-NEXT: %2 = unchecked_enum_data %1
|
|
// CHECK-NEXT: end_borrow %1
|
|
// CHECK: } // end sil function 'lifetime_ending_enum_data'
|
|
sil [ossa] @lifetime_ending_enum_data : $@convention(method) (@in_guaranteed MultiPayload) -> MyInt {
|
|
bb0(%0 : $*MultiPayload):
|
|
%1 = load [copy] %0
|
|
%2 = unchecked_enum_data %1, #MultiPayload.b!enumelt
|
|
return %2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @duplicate_lifetime_end1 :
|
|
// CHECK: load_borrow %0
|
|
// CHECK: } // end sil function 'duplicate_lifetime_end1'
|
|
sil [ossa] @duplicate_lifetime_end1 : $@convention(thin) (@in_guaranteed (C, Optional<C>)) -> () {
|
|
bb0(%0 : $*(C, Optional<C>)):
|
|
%1 = load [copy] %0
|
|
(%2, %3) = destructure_tuple %1
|
|
switch_enum %3, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%4 : @owned $C):
|
|
destroy_value %2
|
|
destroy_value %4
|
|
br bb3
|
|
|
|
bb2:
|
|
debug_value %2
|
|
destroy_value %2
|
|
br bb3
|
|
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @duplicate_lifetime_end2 :
|
|
// CHECK: load_borrow %0
|
|
// CHECK: } // end sil function 'duplicate_lifetime_end2'
|
|
sil [ossa] @duplicate_lifetime_end2 : $@convention(thin) (@in_guaranteed (C, Optional<C>)) -> () {
|
|
bb0(%0 : $*(C, Optional<C>)):
|
|
%1 = load [copy] %0
|
|
(%2, %3) = destructure_tuple %1
|
|
switch_enum %3, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%4 : @owned $C):
|
|
destroy_value %2
|
|
destroy_value %4
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %2
|
|
br bb3
|
|
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @keep_yield2ed_copy : {{.*}} {
|
|
// CHECK: copy_value
|
|
// CHECK: } // end sil function 'keep_yield2ed_copy'
|
|
sil [ossa] @keep_yield2ed_copy : $@convention(thin) () -> () {
|
|
%lendC = function_ref @lendC : $@yield_once_2 @convention(thin) () -> @yields @guaranteed C
|
|
(%c, %token, %alloc) = begin_apply %lendC() : $@yield_once_2 @convention(thin) () -> @yields @guaranteed C
|
|
%copy = copy_value %c : $C
|
|
end_apply %token as $()
|
|
dealloc_stack %alloc : $*Builtin.SILToken
|
|
%useC = function_ref @useC : $@convention(thin) (@guaranteed C) -> ()
|
|
apply %useC(%copy) : $@convention(thin) (@guaranteed C) -> ()
|
|
destroy_value %copy : $C
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @borrowed_from_forward1 : {{.*}} {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-LABEL: } // end sil function 'borrowed_from_forward1'
|
|
sil [ossa] @borrowed_from_forward1 : $@convention(thin) (@guaranteed C) -> () {
|
|
bb0(%0 : @guaranteed $C):
|
|
br bb1(%0)
|
|
|
|
bb1(%1 : @guaranteed $C):
|
|
%2 = borrowed %1 from (%0)
|
|
%copy = copy_value %2
|
|
%useC = function_ref @useC : $@convention(thin) (@guaranteed C) -> ()
|
|
apply %useC(%copy) : $@convention(thin) (@guaranteed C) -> ()
|
|
destroy_value %copy
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @borrowed_from_forward2 : {{.*}} {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK-LABEL: } // end sil function 'borrowed_from_forward2'
|
|
sil [ossa] @borrowed_from_forward2 : $@convention(thin) (@guaranteed Array<Int>) -> () {
|
|
bb0(%0 : @guaranteed $Array<Int>):
|
|
%1 = struct_extract %0, #Array._buffer
|
|
%2 = struct_extract %1, #_ArrayBuffer._storage
|
|
%3 = struct_extract %2, #_BridgeStorage.rawValue
|
|
%4 = unchecked_ref_cast %3 to $__ContiguousArrayStorageBase
|
|
br bb1(%4)
|
|
|
|
bb1(%6 : @guaranteed $__ContiguousArrayStorageBase):
|
|
%7 = borrowed %6 from (%0)
|
|
%8 = copy_value %7
|
|
%9 = begin_borrow %8
|
|
%10 = ref_element_addr [immutable] %9, #__ContiguousArrayStorageBase.countAndCapacity
|
|
end_borrow %9
|
|
destroy_value %8
|
|
%13 = tuple ()
|
|
return %13
|
|
}
|