blob: 53babdea0c310bdd0bff9db922557ec671546a1e [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -verify-skip-unreachable-must-be-last | %FileCheck %s
// REQUIRES: objc_interop
// See https://bugs.swift.org/browse/SR-5065, rdar://32511494
// XFAIL: *
sil_stage canonical
import Builtin
import Swift
class ZZZ {
@objc deinit
init()
}
class C {}
sil @stringcore_invariant_check : $@convention(thin) (@owned _LegacyStringCore) -> @owned Optional<_CocoaString>
sil @reabstraction_thunk : $@convention(thin) (@owned @callee_owned () -> @owned Optional<_CocoaString>) -> @out Optional<_CocoaString>
// CHECK-LABEL: sil @dead_closure_elimination : $@convention(thin) (@owned _LegacyStringCore) -> ()
// CHECK: bb0
// CHECK-NEXT: release_value
// CHECK-NEXT: tuple
// CHECK-NEXT: return
sil @dead_closure_elimination : $@convention(thin) (@owned _LegacyStringCore) -> () {
bb0(%0 : $_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>
strong_release %4 : $@callee_owned () -> @out Optional<_CocoaString>
%5 = tuple()
return %5 : $()
}
// CHECK-LABEL: sil @dead_closure_elimination2
// CHECK: bb0
// CHECK-NEXT: br bb1
// CHECK: bb1
// CHECK-NEXT: release_value
// CHECK-NEXT: tuple
// CHECK-NEXT: return
sil @dead_closure_elimination2 : $@convention(thin) (@owned _LegacyStringCore) -> () {
bb0(%0 : $_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:
strong_retain %4 : $@callee_owned () -> @out Optional<_CocoaString>
strong_release %4 : $@callee_owned () -> @out Optional<_CocoaString>
strong_release %4 : $@callee_owned () -> @out Optional<_CocoaString>
%5 = tuple()
return %5 : $()
}
// FIXME: <rdar://problem/20980377> Add dead array elimination to DeadObjectElimination
// CHECK-LABEL: test_dead_array
// CHECK: bb0(%0 : $ZZZ):
// DISABLED-CHECK-NEXT: strong_release %0
// DISABLED-CHECK-NEXT: tuple
// DISABLED-CHECK-NEXT: return
sil @test_dead_array : $@convention(thin) (@owned ZZZ) -> () {
bb0(%0 : $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 = tuple_extract %3 : $(Array<ZZZ>, Builtin.RawPointer), 0
%5 = tuple_extract %3 : $(Array<ZZZ>, Builtin.RawPointer), 1
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*ZZZ
store %0 to %6 : $*ZZZ
%8 = struct_extract %4 : $Array<ZZZ>, #Array._buffer
%9 = struct_extract %8 : $_ArrayBuffer<ZZZ>, #_ArrayBuffer._storage
%10 = struct_extract %9 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
strong_release %10 : $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 : $@callee_owned () -> Bool):
%1 = apply %0() : $@callee_owned () -> Bool
%2 = tuple ()
return %2 : $()
}
sil @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
}
// Mimicks 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 @dead_array
// CHECK-NOT: release
// CHECK: retain_value %{{[0-9]+}} : $Optional<Builtin.NativeObject>
// CHECK: apply
// CHECK: strong_release %{{[0-9]+}} : $Builtin.BridgeObject
sil @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 = tuple_extract %3 : $(Array<_HeapBuffer<C, Int>>, Builtin.RawPointer), 0 // user: %15
%5 = tuple_extract %3 : $(Array<_HeapBuffer<C, Int>>, Builtin.RawPointer), 1 // user: %6
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*_HeapBuffer<C, Int> // user: %9
%7 = load %0 : $*_HeapBuffer<C, Int> // users: %8, %9
%8 = struct_extract %7 : $_HeapBuffer<C, Int>, #_HeapBuffer._storage // user: %13
store %7 to %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
retain_value %8 : $Optional<Builtin.NativeObject> // id: %13
%14 = apply %10(%12) : $@convention(thin) (@owned @callee_owned () -> Bool) -> ()
%15 = struct_extract %4 : $Array<_HeapBuffer<C, Int>>, #Array._buffer // user: %16
%16 = struct_extract %15 : $_ArrayBuffer<_HeapBuffer<C, Int>>, #_ArrayBuffer._storage // user: %17
%17 = struct_extract %16 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue // user: %18
strong_release %17 : $Builtin.BridgeObject // id: %18
%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 @cast_of_class_to_int
// CHECK: unconditional_checked_cast_addr
// CHECK: return
sil @cast_of_class_to_int : $@convention(thin) (C) -> Int {
bb0(%0 : $C):
%1 = alloc_stack $Int
%2 = alloc_stack $C
store %0 to %2 : $*C
unconditional_checked_cast_addr C in %2 : $*C to Int in %1 : $*Int
%4 = load %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 @remove_release_objc_metatype_to_object
// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
sil @remove_release_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
strong_release %2 : $AnyObject // id: %4
%5 = tuple () // user: %6
return %5 : $() // id: %6
}
// CHECK-LABEL: sil @remove_release_objc_existential_metatype_to_object
// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
sil @remove_release_objc_existential_metatype_to_object: $@convention(thin) (@owned XX) -> () {
bb0(%0 : $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
strong_release %4 : $AnyObject // id: %6
strong_release %0 : $XX // id: %7
%8 = tuple () // user: %9
return %8 : $() // id: %9
}