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
|
// RUN: %target-sil-opt -enable-sil-verify-all -enable-loop-arc=0 -arc-sequence-opts %s | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all -enable-loop-arc=1 -arc-sequence-opts %s | %FileCheck %s
import Builtin
import Swift
import SwiftShims
class MD5 {
init()
final var w: [UInt32]
}
// CHECK-LABEL:sil @test_unique_check_arc : $@convention(method) (@owned MD5) -> ()
sil @test_unique_check_arc : $@convention(method) (@owned MD5) -> () {
// CHECK: bb0
bb0(%0 : $MD5):
%1 = integer_literal $Builtin.Int32, 0
%2 = integer_literal $Builtin.Int32, 16
%3 = struct $Int32 (%1 : $Builtin.Int32)
br bb1(%1 : $Builtin.Int32)
// CHECK: bb1
bb1(%5 : $Builtin.Int32):
%7 = builtin "cmp_eq_Int32"(%5 : $Builtin.Int32, %2 : $Builtin.Int32) : $Builtin.Int1
cond_br %7, bb3, bb2
// CHECK: bb2
bb2:
%9 = integer_literal $Builtin.Int32, 1
%11 = integer_literal $Builtin.Int1, -1
%12 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %9 : $Builtin.Int32, %11 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%13 = tuple_extract %12 : $(Builtin.Int32, Builtin.Int1), 0
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
strong_retain %0 : $MD5
%314 = ref_element_addr %0 : $MD5, #MD5.w
%318 = load %314 : $*Array<UInt32>
%319 = alloc_stack $Array<UInt32>
store %318 to %319 : $*Array<UInt32>
dealloc_stack %319 : $*Array<UInt32>
%179 = is_unique %314 : $*Array<UInt32>
cond_br %179, bb4, bb5
// CHECK: bb3
// CHECK-NEXT: strong_release
// CHECK-NEXT: tuple
// CHECK-NEXT: return
bb3:
strong_release %0 : $MD5
%273 = tuple ()
return %273 : $()
bb4:
br bb6
bb5:
br bb6
// CHECK-NOT: strong_release
bb6:
strong_release %0 : $MD5
br bb1(%13 : $Builtin.Int32)
}
class C {}
// Check that retains are not moved across an is_unique that may alias.
sil @test_uniq_alias : $@convention(method) (@owned C) -> Builtin.Int1 {
// CHECK: bb0
bb0(%0 : $C):
%1 = alloc_stack $C, var, name "x"
store %0 to %1 : $*C
// CHECK: strong_retain %0 : $C
strong_retain %0 : $C
// CHECK: is_unique %1 : $*C
%4 = is_unique %1 : $*C
// CHECK-NOT: strong_retain
fix_lifetime %0 : $C
// CHECK: strong_release %0 : $C
strong_release %0 : $C
// CHECK: [[LOADED:%[0-9]+]] = load %1 : $*C
%8 = load %1 : $*C
// CHECK: strong_release [[LOADED]] : $C
strong_release %8 : $C
dealloc_stack %1 : $*C
return %4 : $Builtin.Int1
}
// The following test could optimize to:
// %2 = load %1 : $*C // user: %4
// %3 = is_unique %0 : $*C // user: %5
// fix_lifetime %2 : $C // id: %4
//
// But ARC is currently conservative. When this is fixed,
// change _CHECK: strong... into _CHECK_NOT: strong...
sil @test_uniq_noalias : $@convention(thin) (@inout C, @inout C) -> Builtin.Int1 {
// CHECK: bb0
bb0(%0 : $*C, %1 : $*C):
%2 = load %1 : $*C
// CHECK: strong_retain %2 : $C
strong_retain %2 : $C
// CHECK: is_unique %0 : $*C
%4 = is_unique %0 : $*C
fix_lifetime %2 : $C
// CHECK: strong_release %2 : $C
strong_release %2 : $C
return %4 : $Builtin.Int1
}
// Similarly, do not remove a retain/release pair that spans an
// is_escaping_closure instruction. This would fail to catch closures
// that are returned from the function.
// <rdar://problem/52803634>
// thunk for @callee_guaranteed () -> ()
sil shared [transparent] [serialized] [reabstraction_thunk] [without_actually_escaping] @$sIg_Ieg_TR : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () {
bb0(%0 : $@noescape @callee_guaranteed () -> ()):
%1 = apply %0() : $@noescape @callee_guaranteed () -> ()
return %1 : $()
}
sil hidden [noinline] @testEscapingClosure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> @owned @callee_guaranteed () -> () {
bb0(%0 : $@noescape @callee_guaranteed () -> ()):
%1 = function_ref @$sIg_Ieg_TR : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%3 = mark_dependence %2 : $@callee_guaranteed () -> () on %0 : $@noescape @callee_guaranteed () -> ()
strong_retain %3 : $@callee_guaranteed () -> ()
%5 = is_escaping_closure %3 : $@callee_guaranteed () -> ()
strong_release %3 : $@callee_guaranteed () -> ()
cond_fail %5 : $Builtin.Int1
return %3 : $@callee_guaranteed () -> ()
}
|