mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* access * accessed * accesses * accessor * acquiring * across * activated * additive * address * addresses' * aggregated * analysis * and * appropriately * archetype * argument * associated * availability * barriers * because * been * beginning * belongs * beneficial * blocks * borrow * builtin * cannot * canonical * canonicalize * clazz * cleanup * coalesceable * coalesced * comparisons * completely * component * computed * concrete * conjunction * conservatively * constituent * construct * consuming * containing * covered * creates * critical * dataflow * declaration * defined * defining * definition * deinitialization * deliberately * dependencies * dependent * deserialized * destroy * deterministic * deterministically * devirtualizes * diagnostic * diagnostics * differentiation * disable * discipline * dominate * dominates * don't * element * eliminate * eliminating * elimination * embedded * encounter * epilogue * epsilon * escape * escaping * essential * evaluating * evaluation * evaluator * executing * existential * existentials * explicit * expression * extended * extension * extract * for * from * function * generic * guarantee * guaranteed * happened * heuristic * however * identifiable * immediately * implementation * improper * include * infinite * initialize * initialized * initializer * inside * instruction * interference * interferes * interleaved * internal * intersection * intractable * intrinsic * invalidates * irreducible * irrelevant * language * lifetime * literal * looks * materialize * meaning * mergeable * might * mimics * modification * modifies * multiple * mutating * necessarily * necessary * needsmultiplecopies * nonetheless * nothing * occurred * occurs * optimization * optimizing * original * outside * overflow * overlapping * overridden * owned * ownership * parallel * parameter * paths * patterns * pipeline * plottable * possible * potentially * practically * preamble * precede * preceding * predecessor * preferable * preparation * probably * projection * properties * property * protocol * reabstraction * reachable * recognized * recursive * recursively * redundant * reentrancy * referenced * registry * reinitialization * reload * represent * requires * response * responsible * retrieving * returned * returning * returns * rewriting * rewritten * sample * scenarios * scope * should * sideeffects * similar * simplify * simplifycfg * somewhat * spaghetti * specialization * specializations * specialized * specially * statistically * substitute * substitution * succeeds * successful * successfully * successor * superfluous * surprisingly * suspension * swift * targeted * that * that our * the * therefore * this * those * threshold * through * transform * transformation * truncated * ultimate * unchecked * uninitialized * unlikely * unmanaged * unoptimized key * updataflow * usefulness * utilities * villain * whenever * writes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
189 lines
8.9 KiB
Plaintext
189 lines
8.9 KiB
Plaintext
// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -sil-combine | %FileCheck %s
|
|
|
|
// 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 @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
|
|
}
|
|
|
|
// 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 @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
|
|
}
|
|
|