1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -sil-combine | %FileCheck %s
// See https://github.com/apple/swift/issues/47641, rdar://32511494
// XFAIL: *
sil_stage canonical
import Builtin
import Swift
class ZZZ {
@objc deinit
init()
}
class C {}
sil [ossa] @stringcore_invariant_check : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
sil [ossa] @reabstraction_thunk : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
// CHECK-LABEL: sil [ossa] @dead_closure_elimination : $@convention(thin) (@owned _LegacyStringCore) -> ()
// CHECK: bb0
// CHECK-NEXT: destroy_value
// CHECK-NEXT: tuple
// CHECK-NEXT: return
sil [ossa] @dead_closure_elimination : $@convention(thin) (@owned _LegacyStringCore) -> () {
bb0(%0 : @owned $_LegacyStringCore):
%1 = function_ref @stringcore_invariant_check : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
%2 = partial_apply %1(%0) : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
%3 = function_ref @reabstraction_thunk : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
%4 = partial_apply %3(%2) : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
destroy_value %4 : $@callee_owned () -> @out Optional<_CocoaString>
%5 = tuple()
return %5 : $()
}
// CHECK-LABEL: sil [ossa] @dead_closure_elimination2
// CHECK: bb0
// CHECK-NEXT: br bb1
// CHECK: bb1
// CHECK-NEXT: destroy_value
// CHECK-NEXT: tuple
// CHECK-NEXT: return
sil [ossa] @dead_closure_elimination2 : $@convention(thin) (@owned _LegacyStringCore) -> () {
bb0(%0 : @owned $_LegacyStringCore):
%1 = function_ref @stringcore_invariant_check : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
%2 = partial_apply %1(%0) : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
%3 = function_ref @reabstraction_thunk : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
%4 = partial_apply %3(%2) : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
br bb1
bb1:
%4a = copy_value %4 : $@callee_owned () -> @out Optional<_CocoaString>
destroy_value %4 : $@callee_owned () -> @out Optional<_CocoaString>
destroy_value %4a : $@callee_owned () -> @out Optional<_CocoaString>
%5 = tuple()
return %5 : $()
}
// FIXME: <rdar://problem/20980377> Add dead array elimination to DeadObjectElimination
// CHECK-LABEL: test_dead_array
// HECK: bb0(%0 : @owned $ZZZ):
// DISABLED-XHECK-NEXT: destroy_value %0
// DISABLED-XHECK-NEXT: tuple
// DISABLED-XHECK-NEXT: return
sil [ossa] @test_dead_array : $@convention(thin) (@owned ZZZ) -> () {
bb0(%0 : @owned $ZZZ):
%1 = integer_literal $Builtin.Word, 1
%2 = function_ref @_allocate_uninitialized_ZZZ : $@convention(thin) (Builtin.Word) -> @owned (Array<ZZZ>, Builtin.RawPointer)
%3 = apply %2(%1) : $@convention(thin) (Builtin.Word) -> @owned (Array<ZZZ>, Builtin.RawPointer)
(%4, %5) = destructure_tuple %3 : $(Array<ZZZ>, Builtin.RawPointer)
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*ZZZ
store %0 to [init] %6 : $*ZZZ
destroy_value %4 : $Builtin.BridgeObject
%12 = tuple ()
return %12 : $()
}
sil [_semantics "array.uninitialized"] @_allocate_uninitialized_ZZZ : $@convention(thin) (Builtin.Word) -> @owned (Array<ZZZ>, Builtin.RawPointer)
// dead_array test helpers
sil [thunk] @dead_array_run_closure : $@convention(thin) (@owned @callee_owned () -> Bool) -> () {
bb0(%0 : @owned $@callee_owned () -> Bool):
%1 = apply %0() : $@callee_owned () -> Bool
%2 = tuple ()
return %2 : $()
}
sil [ossa] @dead_array_closure : $@convention(thin) (@inout _HeapBuffer<C, Int>) -> Bool {
bb0(%0 : $*_HeapBuffer<C, Int>):
%1 = struct_element_addr %0 : $*_HeapBuffer<C, Int>, #_HeapBuffer._storage // user: %2
%2 = is_unique %1 : $*Optional<Builtin.NativeObject> // user: %3
%3 = struct $Bool (%2 : $Builtin.Int1) // user: %4
return %3 : $Bool // id: %4
}
// Mimics Swift._allocateUninitializedArray
sil [_semantics "array.uninitialized"] @dead_array_alloc : $@convention(thin) <τ_0_0> (Builtin.Word) -> @owned (Array<τ_0_0>, Builtin.RawPointer)
// <rdar://problem/20980377> HeapBuffer.swift test case spuriously reports a "unique" buffer
// CHECK-LABEL: sil [ossa] @dead_array
// CHECK-NOT: destroy_value
// CHECK: copy_value %{{[0-9]+}} : $Optional<Builtin.NativeObject>
// CHECK: apply
// CHECK: destroy_value %{{[0-9]+}} : $Builtin.BridgeObject
sil [ossa] @dead_array : $@convention(thin) (@inout _HeapBuffer<C, Int>) -> () {
bb0(%0 : $*_HeapBuffer<C, Int>):
%1 = integer_literal $Builtin.Word, 1 // user: %3
%2 = function_ref @dead_array_alloc : $@convention(thin) <τ_0_0> (Builtin.Word) -> @owned (Array<τ_0_0>, Builtin.RawPointer)
%3 = apply %2<_HeapBuffer<C, Int>>(%1) : $@convention(thin) <τ_0_0> (Builtin.Word) -> @owned (Array<τ_0_0>, Builtin.RawPointer)
(%4, %5) = destructure_tuple %3 : $(Array<_HeapBuffer<C, Int>>, Builtin.RawPointer)
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*_HeapBuffer<C, Int> // user: %9
%7 = load [copy] %0 : $*_HeapBuffer<C, Int> // users: %8, %9
%7a = begin_borrow %7 : $_HeapBuffer<C, Int>
%8 = struct_extract %7a : $_HeapBuffer<C, Int>, #_HeapBuffer._storage // user: %13
%8a = copy_value %8 : $Optional<Builtin.NativeObject>
end_borrow %7 : $_HeapBuffer<C, Int>
store %7 to [init] %6 : $*_HeapBuffer<C, Int> // id: %9
%10 = function_ref @dead_array_run_closure : $@convention(thin) (@owned @callee_owned () -> Bool) -> () // user: %14
%11 = function_ref @dead_array_closure : $@convention(thin) (@inout _HeapBuffer<C, Int>) -> Bool // user: %12
%12 = partial_apply %11(%0) : $@convention(thin) (@inout _HeapBuffer<C, Int>) -> Bool // user: %14
%14 = apply %10(%12) : $@convention(thin) (@owned @callee_owned () -> Bool) -> ()
destroy_value %4 : $Array<_HeapBuffer<C, Int>>
%19 = tuple () // user: %20
return %19 : $() // id: %20
}
// Check that it does not crash the compiler.
// Int is ObjC-bridgeable in this case, but its conformance is not know,
// because Foundation is not imported yet.
// Therefore the cast may succeed from the compiler point of view.
// CHECK-LABEL: sil [ossa] @cast_of_class_to_int
// CHECK: unconditional_checked_cast_addr
// CHECK: return
sil [ossa] @cast_of_class_to_int : $@convention(thin) (@owned C) -> Int {
bb0(%0 : @owned $C):
%1 = alloc_stack $Int
%2 = alloc_stack $C
store %0 to [init] %2 : $*C
unconditional_checked_cast_addr C in %2 : $*C to Int in %1 : $*Int
%4 = load [trivial] %1 : $*Int
dealloc_stack %2 : $*C
dealloc_stack %1 : $*Int
return %4 : $Int
}
@objc(XX) protocol XX {
}
class XXImpl : XX {
@objc deinit
init()
}
// CHECK-LABEL: sil [ossa] @remove_destroy_value_objc_metatype_to_object :
// CHECK-NOT: destroy_value {{%[0-9]+}} : $AnyObject
// CHECK: } // end sil function 'remove_destroy_value_objc_metatype_to_object'
sil [ossa] @remove_destroy_value_objc_metatype_to_object : $@convention(thin) () -> () {
bb0:
%0 = metatype $@thick XXImpl.Type // user: %1
%1 = thick_to_objc_metatype %0 : $@thick XXImpl.Type to $@objc_metatype XXImpl.Type // user: %2
%2 = objc_metatype_to_object %1 : $@objc_metatype XXImpl.Type to $AnyObject // users: %3, %4
debug_value %2 : $AnyObject // id: %3
destroy_value %2 : $AnyObject // id: %4
%5 = tuple () // user: %6
return %5 : $() // id: %6
}
// CHECK-LABEL: sil [ossa] @remove_destroy_value_objc_existential_metatype_to_object :
// CHECK-NOT: destroy_value {{%[0-9]+}} : $AnyObject
// CHECK: } // end sil function 'remove_destroy_value_objc_existential_metatype_to_object'
sil [ossa] @remove_destroy_value_objc_existential_metatype_to_object: $@convention(thin) (@owned XX) -> () {
bb0(%0 : @owned $XX):
debug_value %0 : $XX // id: %1
%2 = existential_metatype $@thick XX.Type, %0 : $XX // user: %3
%3 = thick_to_objc_metatype %2 : $@thick XX.Type to $@objc_metatype XX.Type // user: %4
%4 = objc_existential_metatype_to_object %3 : $@objc_metatype XX.Type to $AnyObject // users: %5, %6
debug_value %4 : $AnyObject, let, name "obj1" // id: %5
destroy_value %4 : $AnyObject // id: %6
destroy_value %0 : $XX // id: %7
%8 = tuple () // user: %9
return %8 : $() // id: %9
}
|