Files
swift-mirror/test/SILOptimizer/cowarray_opt.sil
T
Andrew Trick cf962e0148 [SILVerifier] Disallow address-type block arguments in raw SIL.
As a structural SIL property, we disallow address-type block
arguments. Supporting them would prevent reliably reasoning about the
underlying storage of memory access. This reasoning is important for
diagnosing violations of memory access rules and supporting future
optimizations such as bitfield packing. Address-type block arguments
also create unnecessary complexity for SIL optimization passes that
need to reason about memory aliasing.

This must be enforced in RAW SIL for diagnosing exclusive memory
access. The optimizer currently breaks the invariant in three places:
1. Normal Simplify CFG during conditional branch simplification
   (sneaky jump threading).
2. Simplify CFG via Jump Threading.
3. Loop Rotation.
2018-02-27 09:53:13 -08:00

1325 lines
62 KiB
Plaintext

// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enforce-exclusivity=none -enable-sil-verify-all -cowarray-opt %s | %FileCheck %s
// Declare this SIL to be canonical because some tests break raw SIL
// conventions. e.g. address-type block args. -enforce-exclusivity=none is also
// required to allow address-type block args in canonical SIL.
sil_stage canonical
import Builtin
import Swift
/////////////
// Utility //
/////////////
struct ArrayIntBuffer {
var storage : Builtin.NativeObject
}
struct MyArray<T> {
var buffer : ArrayIntBuffer
}
struct MyStruct {
}
class MyArrayContainer<T> {
var array: MyArray<T>
init()
deinit
}
struct Container {
var array: MyArray<MyStruct>
}
struct ContainerContainer {
var container: Container
}
sil [_semantics "array.make_mutable"] @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
sil [_semantics "array.get_count"] @guaranteed_array_get_count : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
sil [_semantics "array.get_capacity"] @guaranteed_array_get_capacity : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
sil [_semantics "array.mutate_unknown"] @array_unknown_mutate : $@convention(method) (@inout MyArray<MyStruct>) -> ()
// An unknown user
sil @unknown : $@convention(thin) () -> ()
///////////
// Tests //
///////////
// CHECK-LABEL: sil @simple_hoist
// CHECK: bb0([[ARRAY:%[0-9]+]]
// CHECK: [[FUN:%[0-9]+]] = function_ref @array_make_mutable
// CHECK: apply [[FUN]]([[ARRAY]]
// CHECK: bb1
// CHECK-NOT: array_make_mutable
// CHECK-NOT: apply [[FUN]]
sil @simple_hoist : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
debug_value_addr %0 : $*MyArray<MyStruct>
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_ignoring_paired_retain_release_and_hoist
// CHECK: bb0(
// CHECK-NOT: br bb
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK-NOT: br bb
// CHECK: apply [[MM]]
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: cond_br {{.*}}, bb1
sil @hoist_ignoring_paired_retain_release_and_hoist : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
release_value %2 : $MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_blocked_by_unpaired_retain_release_1
// CHECK: bb0(
// CHECK-NOT: apply
// CHECK: bb1:
// CHECK: retain_value
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK: apply [[MM]]
// CHECK: cond_br {{.*}}, bb1
sil @hoist_blocked_by_unpaired_retain_release_1 : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_blocked_by_unpaired_retain_release_2
// CHECK: bb0(
// CHECK-NOT: apply
// CHECK: bb1:
// CHECK: retain_value
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK: apply [[MM]]
// CHECK: cond_br {{.*}}, bb1
sil @hoist_blocked_by_unpaired_retain_release_2 : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
br bb1
bb1:
%10 = load %0 : $*MyArray<MyStruct>
%11 = load %0 : $*MyArray<MyStruct>
%8 = struct_extract %10 : $MyArray<MyStruct>, #MyArray.buffer
%9 = struct_extract %11 : $MyArray<MyStruct>, #MyArray.buffer
retain_value %8 : $ArrayIntBuffer
retain_value %9 : $ArrayIntBuffer
release_value %9 : $ArrayIntBuffer
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_not_blocked_by_unpaired_release
// CHECK: bb0(
// CHECK-NOT: br bb
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK-NOT: br bb
// CHECK: apply [[MM]]
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: cond_br {{.*}}, bb1
sil @hoist_not_blocked_by_unpaired_release : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
release_value %2 : $MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @cow_should_ignore_mark_dependence_addrproj_use : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
// CHECK: bb0(
// CHECK-NOT: br bb
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK-NOT: br bb
// CHECK: apply [[MM]]
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: cond_br {{.*}}, bb1
sil @cow_should_ignore_mark_dependence_addrproj_use : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%999 = struct_element_addr %0 : $*MyArray<MyStruct>, #MyArray.buffer
%9999 = struct_element_addr %999 : $*ArrayIntBuffer, #ArrayIntBuffer.storage
%99999 = load %9999 : $*Builtin.NativeObject
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
release_value %2 : $MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
mark_dependence %1 : $*Builtin.Int1 on %99999 : $Builtin.NativeObject
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @cow_should_ignore_mark_dependence_value : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
// CHECK: bb0(
// CHECK-NOT: br bb
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK-NOT: br bb
// CHECK: apply [[MM]]
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: cond_br {{.*}}, bb1
sil @cow_should_ignore_mark_dependence_value : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
release_value %2 : $MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
mark_dependence %1 : $*Builtin.Int1 on %2 : $MyArray<MyStruct>
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @cow_should_ignore_enum : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
// CHECK: bb0(
// CHECK-NOT: br bb
// CHECK: [[MM:%.*]] = function_ref @array_make_mutable
// CHECK-NOT: br bb
// CHECK: apply [[MM]]
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: cond_br {{.*}}, bb1
sil @cow_should_ignore_enum : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
%3 = load %1 : $*Builtin.Int1
%4 = load %0 : $*MyArray<MyStruct>
release_value %2 : $MyArray<MyStruct>
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%8 = enum $Optional<MyArray<MyStruct>>, #Optional.some!enumelt.1, %2 : $MyArray<MyStruct>
mark_dependence %1 : $*Builtin.Int1 on %8 : $Optional<MyArray<MyStruct>>
cond_br %3, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @cow_should_ignore_guaranteed_semantic_call_sequence : $@convention(thin) (@guaranteed MyArrayContainer<MyStruct>, Builtin.NativeObject) -> () {
// CHECK: bb0
// CHECK: [[F:%.*]] = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
// CHECK: apply [[F]](
// CHECK: bb1:
// CHECK: bb2:
// CHECK-NOT: apply [[F]](
// CHECK: bb3:
// CHECK: bb4:
// CHECK-NOT: apply [[F]](
// CHECK: bb5:
// CHECK: bb6:
// CHECK-NOT: apply [[F]](
// CHECK: bb7:
// CHECK: bb8:
// CHECK-NOT: apply [[F]](
// CHECK: bb9:
sil @cow_should_ignore_guaranteed_semantic_call_sequence : $@convention(thin) (@guaranteed MyArrayContainer<MyStruct>, Builtin.NativeObject) -> () {
bb0(%0 : $MyArrayContainer<MyStruct>, %00 : $Builtin.NativeObject):
%1 = ref_element_addr %0 : $MyArrayContainer<MyStruct>, #MyArrayContainer.array
%2 = load %1 : $*MyArray<MyStruct>
%3 = function_ref @guaranteed_array_get_count : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
%4 = function_ref @guaranteed_array_get_capacity : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
%5 = function_ref @unknown : $@convention(thin) () -> ()
%6 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
br bb1
bb1:
// Simple case. This should hoist.
retain_value %2 : $MyArray<MyStruct>
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
br bb3
bb3:
// Failure case b/c of use in between release and call.
retain_value %2 : $MyArray<MyStruct>
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
fix_lifetime %0 : $MyArrayContainer<MyStruct>
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb4, bb3
bb4:
br bb5
bb5:
// Failure case b/c of use in between calls.
retain_value %2 : $MyArray<MyStruct>
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
fix_lifetime %0 : $MyArrayContainer<MyStruct>
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb5, bb6
bb6:
br bb7
bb7:
// Failure b/c use is in between apply and retain.
retain_value %2 : $MyArray<MyStruct>
fix_lifetime %0 : $MyArrayContainer<MyStruct>
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb7, bb8
bb8:
br bb9
bb9:
// Failure b/c of release_value
retain_value %00 : $Builtin.NativeObject
retain_value %2 : $MyArray<MyStruct>
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %00 : $Builtin.NativeObject
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb9, bb10
bb10:
%7 = tuple()
return %7 : $()
}
// CHECK: sil @cow_handle_array_address_load
// CHECK: bb0({{.*}}):
// CHECK: apply
// CHECK: br bb1
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: bb2
sil @cow_handle_array_address_load : $@convention(thin) (@inout MyArray<MyStruct>, @inout Builtin.Int1) -> () {
bb0(%0 : $*MyArray<MyStruct>, %1 : $*Builtin.Int1):
%2 = load %0 : $*MyArray<MyStruct>
%3 = struct_element_addr %0 : $*MyArray<MyStruct>, #MyArray.buffer
%4 = struct_element_addr %3 : $*ArrayIntBuffer, #ArrayIntBuffer.storage
br bb1
bb1:
%6 = load %4 : $*Builtin.NativeObject
strong_retain %6 : $Builtin.NativeObject
%8 = load %1 : $*Builtin.Int1
strong_release %6 : $Builtin.NativeObject
%10 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%11 = apply %10(%0) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%12 = enum $Optional<MyArray<MyStruct>>, #Optional.some!enumelt.1, %2 : $MyArray<MyStruct>
%13 = mark_dependence %1 : $*Builtin.Int1 on %12 : $Optional<MyArray<MyStruct>>
cond_br %8, bb1, bb2
bb2:
%15 = tuple ()
return %15 : $()
}
// CHECK-LABEL: sil @cow_type_based_hoisting_retain_release_matching : $@convention(thin) (@guaranteed MyArrayContainer<MyStruct>, Builtin.NativeObject) -> () {
// CHECK: bb0
// CHECK: [[F:%.*]] = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
// CHECK-NOT: apply [[F]](
// CHECK: bb1:
// CHECK: apply [[F]](
// CHECK: bb2:
// CHECK-NOT: apply [[F]](
// CHECK: bb3:
// CHECK: apply [[F]](
// CHECK: bb4:
sil @cow_type_based_hoisting_retain_release_matching : $@convention(thin) (@guaranteed MyArrayContainer<MyStruct>, Builtin.NativeObject) -> () {
bb0(%0 : $MyArrayContainer<MyStruct>, %00 : $Builtin.NativeObject):
%1 = ref_element_addr %0 : $MyArrayContainer<MyStruct>, #MyArrayContainer.array
%2 = load %1 : $*MyArray<MyStruct>
%3 = function_ref @guaranteed_array_get_count : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
%4 = function_ref @guaranteed_array_get_capacity : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
%5 = function_ref @unknown : $@convention(thin) () -> ()
%6 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%7 = function_ref @array_unknown_mutate : $@convention(method) (@inout MyArray<MyStruct>) -> ()
br bb1
bb1:
retain_value %2 : $MyArray<MyStruct>
retain_value %00 : $Builtin.NativeObject
release_value %00: $Builtin.NativeObject
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
br bb3
bb3:
retain_value %2 : $MyArray<MyStruct>
apply %7(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
apply %3(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
apply %4(%2) : $@convention(method) (@guaranteed MyArray<MyStruct>) -> Int
release_value %2 : $MyArray<MyStruct>
apply %6(%1) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb3, bb4
bb4:
%8 = tuple()
return %8 : $()
}
struct _MyBridgeStorage {
var rawValue : Builtin.BridgeObject
}
struct _My2dArrayBuffer<T> {
var _storage : _MyBridgeStorage
}
struct My2dArray<T> {
var _buffer : _My2dArrayBuffer<T>
}
struct MyInt {
@sil_stored var _value: Builtin.Int64
init(_ value: Int16)
}
sil [_semantics "array.check_subscript"] @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
sil [_semantics "array.check_subscript"] @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
sil [_semantics "array.make_mutable"] @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
sil [_semantics "array.get_element_address"] @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
sil [_semantics "array.make_mutable"] @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
sil [_semantics "array.get_element_address"] @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
// Check hoisting of uniqueness checks in a 2D array loop.
// CHECK-LABEL: sil @hoist2DArray
// CHECK: bb0
// CHECK: cond_br undef, bb2, bb1
// CHECK: bb1
// CHECK: [[CS:%.*]] = function_ref @checkSubscript
// CHECK: [[MM:%.*]] = function_ref @makeMutable
// CHECK: apply [[MM]]
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3:
// CHECK: cond_br undef, bb5, bb4
// CHECK: bb4:
// CHECK: [[CS2:%.*]] = function_ref @checkSubscript2
// CHECK: [[GEA:%.*]] = function_ref @getElementAddress
// CHECK: [[MM2:%.*]] = function_ref @makeMutable2
// CHECK: [[GEA2:%.*]] = function_ref @getElementAddress2
// CHECK: strong_retain
// CHECK: apply [[CS]]
// CHECK: strong_release
// CHECK: strong_retain
// CHECK: [[ADDR:%.*]] = apply [[GEA]]
// CHECK: strong_release
// CHECK: [[SE:%.*]] = struct_extract [[ADDR]]
// CHECK: [[PTA:%.*]] = pointer_to_address [[SE]]
// CHECK: [[MD:%.*]] = mark_dependence [[PTA]]
// CHECK: apply [[MM2]]([[MD]]
// CHECK: br bb6
// CHECK: bb5:
// CHECK: cond_br undef, bb2, bb3
// CHECK: bb6
// CHECK: strong_retain
// CHECK: apply [[CS2]]
// CHECK: strong_release
// CHECK: strong_retain
// CHECK: apply [[GEA2]]
// CHECK: strong_release
// CHECK-NOT: apply
// CHECK: cond_br
sil @hoist2DArray : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>):
%1 = integer_literal $Builtin.Int64, 0
%2 = struct $MyInt (%1 : $Builtin.Int64)
%3 = integer_literal $Builtin.Int1, -1
cond_br undef, bb2, bb1
bb1:
%5 = integer_literal $Builtin.Int64, 1
%6 = integer_literal $Builtin.Int1, 0
%7 = function_ref @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
br bb3
bb2:
%9 = tuple ()
return %9 : $()
bb3:
cond_br undef, bb5, bb4
bb4:
%12 = function_ref @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
%13 = function_ref @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%14 = struct $Bool (%3 : $Builtin.Int1)
%15 = function_ref @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%16 = struct_element_addr %0 : $*My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%17 = struct_element_addr %16 : $*_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%18 = struct_element_addr %17 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%19 = function_ref @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%20 = function_ref @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb6(%1 : $Builtin.Int64)
bb5:
cond_br undef, bb2, bb3
bb6(%23 : $Builtin.Int64):
%24 = struct $MyInt (%23 : $Builtin.Int64)
%25 = builtin "sadd_with_overflow_Int64"(%23 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 0
%27 = apply %13(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%28 = load %0 : $*My2dArray<My2dArray<MyInt>>
%29 = struct_extract %28 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%30 = struct_extract %29 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%31 = struct_extract %30 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %31 : $Builtin.BridgeObject
%33 = apply %7(%2, %14, %28) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
strong_release %31 : $Builtin.BridgeObject
%35 = load %0 : $*My2dArray<My2dArray<MyInt>>
%36 = struct_extract %35 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%37 = struct_extract %36 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%38 = struct_extract %37 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %38 : $Builtin.BridgeObject
%40 = apply %15(%2, %35) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
strong_release %38 : $Builtin.BridgeObject
%42 = load %18 : $*Builtin.BridgeObject
%43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $Builtin.NativeObject
%44 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %43 : $Builtin.NativeObject
%45 = struct_extract %40 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%46 = pointer_to_address %45 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%47 = mark_dependence %46 : $*My2dArray<MyInt> on %44 : $Optional<Builtin.NativeObject>
%48 = apply %19(%47) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%49 = load %47 : $*My2dArray<MyInt>
%50 = struct_extract %49 : $My2dArray<MyInt>, #My2dArray._buffer
%51 = struct_extract %50 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%52 = struct_extract %51 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %52 : $Builtin.BridgeObject
%54 = apply %12(%24, %14, %49) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
strong_release %52 : $Builtin.BridgeObject
%56 = load %47 : $*My2dArray<MyInt>
%57 = struct_extract %56 : $My2dArray<MyInt>, #My2dArray._buffer
%58 = struct_extract %57 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%59 = struct_extract %58 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %59 : $Builtin.BridgeObject
%61 = apply %20(%24, %56) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
strong_release %59 : $Builtin.BridgeObject
%63 = struct_element_addr %47 : $*My2dArray<MyInt>, #My2dArray._buffer
%64 = struct_element_addr %63 : $*_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%65 = struct_element_addr %64 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%66 = load %65 : $*Builtin.BridgeObject
%67 = unchecked_ref_cast %66 : $Builtin.BridgeObject to $Builtin.NativeObject
%68 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %67 : $Builtin.NativeObject
%69 = struct_extract %61 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%70 = pointer_to_address %69 : $Builtin.RawPointer to [strict] $*MyInt
%71 = mark_dependence %70 : $*MyInt on %68 : $Optional<Builtin.NativeObject>
store %24 to %71 : $*MyInt
cond_br undef, bb5, bb6(%26 : $Builtin.Int64)
}
// CHECK-LABEL: sil @dont_hoist_because_release_2DArray
// CHECK: bb0
// CHECK: cond_br undef, bb2, bb1
// CHECK: bb1
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3:
// CHECK: cond_br undef, bb5, bb4
// CHECK: bb4:
// CHECK-NOT: apply
// CHECK: br bb6
sil @dont_hoist_because_release_2DArray : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>):
%1 = integer_literal $Builtin.Int64, 0
%2 = struct $MyInt (%1 : $Builtin.Int64)
%3 = integer_literal $Builtin.Int1, -1
cond_br undef, bb2, bb1
bb1:
%5 = integer_literal $Builtin.Int64, 1
%6 = integer_literal $Builtin.Int1, 0
%7 = function_ref @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
br bb3
bb2:
%9 = tuple ()
return %9 : $()
bb3:
cond_br undef, bb5, bb4
bb4:
%12 = function_ref @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
%13 = function_ref @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%14 = struct $Bool (%3 : $Builtin.Int1)
%15 = function_ref @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%16 = struct_element_addr %0 : $*My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%17 = struct_element_addr %16 : $*_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%18 = struct_element_addr %17 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%19 = function_ref @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%20 = function_ref @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb6(%1 : $Builtin.Int64)
bb5:
cond_br undef, bb2, bb3
bb6(%23 : $Builtin.Int64):
%24 = struct $MyInt (%23 : $Builtin.Int64)
%25 = builtin "sadd_with_overflow_Int64"(%23 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 0
%27 = apply %13(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%28 = load %0 : $*My2dArray<My2dArray<MyInt>>
%29 = struct_extract %28 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%30 = struct_extract %29 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%31 = struct_extract %30 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %31 : $Builtin.BridgeObject
%33 = apply %7(%2, %14, %28) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
strong_release %31 : $Builtin.BridgeObject
%35 = load %0 : $*My2dArray<My2dArray<MyInt>>
%36 = struct_extract %35 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%37 = struct_extract %36 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%38 = struct_extract %37 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %38 : $Builtin.BridgeObject
%40 = apply %15(%2, %35) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
strong_release %38 : $Builtin.BridgeObject
%42 = load %18 : $*Builtin.BridgeObject
%43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $Builtin.NativeObject
%44 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %43 : $Builtin.NativeObject
%45 = struct_extract %40 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%46 = pointer_to_address %45 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%47 = mark_dependence %46 : $*My2dArray<MyInt> on %44 : $Optional<Builtin.NativeObject>
%48 = apply %19(%47) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%49 = load %47 : $*My2dArray<MyInt>
%50 = struct_extract %49 : $My2dArray<MyInt>, #My2dArray._buffer
%51 = struct_extract %50 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%52 = struct_extract %51 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %52 : $Builtin.BridgeObject
%54 = apply %12(%24, %14, %49) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
strong_release %52 : $Builtin.BridgeObject
%56 = load %47 : $*My2dArray<MyInt>
%57 = struct_extract %56 : $My2dArray<MyInt>, #My2dArray._buffer
%58 = struct_extract %57 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%59 = struct_extract %58 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %59 : $Builtin.BridgeObject
%61 = apply %20(%24, %56) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
strong_release %59 : $Builtin.BridgeObject
%63 = struct_element_addr %47 : $*My2dArray<MyInt>, #My2dArray._buffer
%64 = struct_element_addr %63 : $*_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%65 = struct_element_addr %64 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%66 = load %65 : $*Builtin.BridgeObject
%67 = unchecked_ref_cast %66 : $Builtin.BridgeObject to $Builtin.NativeObject
%68 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %67 : $Builtin.NativeObject
%69 = struct_extract %61 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%70 = pointer_to_address %69 : $Builtin.RawPointer to [strict] $*MyInt
%71 = mark_dependence %70 : $*MyInt on %68 : $Optional<Builtin.NativeObject>
store %24 to %71 : $*MyInt
release_value %28 : $My2dArray<My2dArray<MyInt>>
cond_br undef, bb5, bb6(%26 : $Builtin.Int64)
}
// CHECK-LABEL: sil @dont_hoist_because_retain_2DArray
// CHECK: bb0
// CHECK: cond_br undef, bb2, bb1
// CHECK: bb1
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3:
// CHECK: cond_br undef, bb5, bb4
// CHECK: bb4:
// CHECK-NOT: apply
// CHECK: br bb6
sil @dont_hoist_because_retain_2DArray : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>):
%1 = integer_literal $Builtin.Int64, 0
%2 = struct $MyInt (%1 : $Builtin.Int64)
%3 = integer_literal $Builtin.Int1, -1
cond_br undef, bb2, bb1
bb1:
%5 = integer_literal $Builtin.Int64, 1
%6 = integer_literal $Builtin.Int1, 0
%7 = function_ref @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
br bb3
bb2:
%9 = tuple ()
return %9 : $()
bb3:
cond_br undef, bb5, bb4
bb4:
%12 = function_ref @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
%13 = function_ref @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%14 = struct $Bool (%3 : $Builtin.Int1)
%15 = function_ref @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%16 = struct_element_addr %0 : $*My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%17 = struct_element_addr %16 : $*_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%18 = struct_element_addr %17 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%19 = function_ref @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%20 = function_ref @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb6(%1 : $Builtin.Int64)
bb5:
cond_br undef, bb2, bb3
bb6(%23 : $Builtin.Int64):
%24 = struct $MyInt (%23 : $Builtin.Int64)
%25 = builtin "sadd_with_overflow_Int64"(%23 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 0
%27 = apply %13(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%28 = load %0 : $*My2dArray<My2dArray<MyInt>>
%29 = struct_extract %28 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%30 = struct_extract %29 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%31 = struct_extract %30 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %31 : $Builtin.BridgeObject
%33 = apply %7(%2, %14, %28) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
strong_release %31 : $Builtin.BridgeObject
%35 = load %0 : $*My2dArray<My2dArray<MyInt>>
%36 = struct_extract %35 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%37 = struct_extract %36 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%38 = struct_extract %37 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %38 : $Builtin.BridgeObject
%40 = apply %15(%2, %35) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
strong_release %38 : $Builtin.BridgeObject
%42 = load %18 : $*Builtin.BridgeObject
%43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $Builtin.NativeObject
%44 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %43 : $Builtin.NativeObject
%45 = struct_extract %40 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%46 = pointer_to_address %45 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%47 = mark_dependence %46 : $*My2dArray<MyInt> on %44 : $Optional<Builtin.NativeObject>
%48 = apply %19(%47) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%49 = load %47 : $*My2dArray<MyInt>
%50 = struct_extract %49 : $My2dArray<MyInt>, #My2dArray._buffer
%51 = struct_extract %50 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%52 = struct_extract %51 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %52 : $Builtin.BridgeObject
%54 = apply %12(%24, %14, %49) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
strong_release %52 : $Builtin.BridgeObject
%56 = load %47 : $*My2dArray<MyInt>
%57 = struct_extract %56 : $My2dArray<MyInt>, #My2dArray._buffer
%58 = struct_extract %57 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%59 = struct_extract %58 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %59 : $Builtin.BridgeObject
%61 = apply %20(%24, %56) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
strong_release %59 : $Builtin.BridgeObject
%63 = struct_element_addr %47 : $*My2dArray<MyInt>, #My2dArray._buffer
%64 = struct_element_addr %63 : $*_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%65 = struct_element_addr %64 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%66 = load %65 : $*Builtin.BridgeObject
%67 = unchecked_ref_cast %66 : $Builtin.BridgeObject to $Builtin.NativeObject
%68 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %67 : $Builtin.NativeObject
%69 = struct_extract %61 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%70 = pointer_to_address %69 : $Builtin.RawPointer to [strict] $*MyInt
%71 = mark_dependence %70 : $*MyInt on %68 : $Optional<Builtin.NativeObject>
store %24 to %71 : $*MyInt
retain_value %28 : $My2dArray<My2dArray<MyInt>>
cond_br undef, bb5, bb6(%26 : $Builtin.Int64)
}
// CHECK-LABEL: sil @dont_hoist_because_store_2DArray
// CHECK: bb0
// CHECK: cond_br undef, bb2, bb1
// CHECK: bb1
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3:
// CHECK: cond_br undef, bb5, bb4
// CHECK: bb4:
// CHECK-NOT: apply
// CHECK: br bb6
sil @dont_hoist_because_store_2DArray : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>, @inout My2dArray<My2dArray<MyInt>>) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>, %100: $*My2dArray<My2dArray<MyInt>>):
%1 = integer_literal $Builtin.Int64, 0
%2 = struct $MyInt (%1 : $Builtin.Int64)
%3 = integer_literal $Builtin.Int1, -1
cond_br undef, bb2, bb1
bb1:
%5 = integer_literal $Builtin.Int64, 1
%6 = integer_literal $Builtin.Int1, 0
%7 = function_ref @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
br bb3
bb2:
%9 = tuple ()
return %9 : $()
bb3:
cond_br undef, bb5, bb4
bb4:
%12 = function_ref @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
%13 = function_ref @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%14 = struct $Bool (%3 : $Builtin.Int1)
%15 = function_ref @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%16 = struct_element_addr %0 : $*My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%17 = struct_element_addr %16 : $*_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%18 = struct_element_addr %17 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%19 = function_ref @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%20 = function_ref @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb6(%1 : $Builtin.Int64)
bb5:
cond_br undef, bb2, bb3
bb6(%23 : $Builtin.Int64):
%24 = struct $MyInt (%23 : $Builtin.Int64)
%25 = builtin "sadd_with_overflow_Int64"(%23 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 0
%27 = apply %13(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%28 = load %0 : $*My2dArray<My2dArray<MyInt>>
%29 = struct_extract %28 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%30 = struct_extract %29 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%31 = struct_extract %30 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %31 : $Builtin.BridgeObject
%33 = apply %7(%2, %14, %28) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
strong_release %31 : $Builtin.BridgeObject
%35 = load %0 : $*My2dArray<My2dArray<MyInt>>
%36 = struct_extract %35 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%37 = struct_extract %36 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%38 = struct_extract %37 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %38 : $Builtin.BridgeObject
%40 = apply %15(%2, %35) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
strong_release %38 : $Builtin.BridgeObject
%42 = load %18 : $*Builtin.BridgeObject
%43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $Builtin.NativeObject
%44 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %43 : $Builtin.NativeObject
%45 = struct_extract %40 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%46 = pointer_to_address %45 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%47 = mark_dependence %46 : $*My2dArray<MyInt> on %44 : $Optional<Builtin.NativeObject>
%48 = apply %19(%47) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%49 = load %47 : $*My2dArray<MyInt>
%50 = struct_extract %49 : $My2dArray<MyInt>, #My2dArray._buffer
%51 = struct_extract %50 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%52 = struct_extract %51 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %52 : $Builtin.BridgeObject
%54 = apply %12(%24, %14, %49) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
strong_release %52 : $Builtin.BridgeObject
%56 = load %47 : $*My2dArray<MyInt>
%57 = struct_extract %56 : $My2dArray<MyInt>, #My2dArray._buffer
%58 = struct_extract %57 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%59 = struct_extract %58 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %59 : $Builtin.BridgeObject
%61 = apply %20(%24, %56) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
strong_release %59 : $Builtin.BridgeObject
%63 = struct_element_addr %47 : $*My2dArray<MyInt>, #My2dArray._buffer
%64 = struct_element_addr %63 : $*_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%65 = struct_element_addr %64 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%66 = load %65 : $*Builtin.BridgeObject
%67 = unchecked_ref_cast %66 : $Builtin.BridgeObject to $Builtin.NativeObject
%68 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %67 : $Builtin.NativeObject
%69 = struct_extract %61 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%70 = pointer_to_address %69 : $Builtin.RawPointer to [strict] $*MyInt
%71 = mark_dependence %70 : $*MyInt on %68 : $Optional<Builtin.NativeObject>
store %24 to %71 : $*MyInt
%72 = load %100: $*My2dArray<My2dArray<MyInt>>
store %72 to %0: $*My2dArray<My2dArray<MyInt>>
cond_br undef, bb5, bb6(%26 : $Builtin.Int64)
}
// CHECK-LABEL: sil @dont_hoist_because_apply_2DArray
// CHECK: bb0
// CHECK: cond_br undef, bb2, bb1
// CHECK: bb1
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3:
// CHECK: cond_br undef, bb5, bb4
// CHECK: bb4:
// CHECK-NOT: apply
// CHECK: br bb6
sil @dont_hoist_because_apply_2DArray : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>, @inout My2dArray<My2dArray<MyInt>>) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>, %100: $*My2dArray<My2dArray<MyInt>>):
%1 = integer_literal $Builtin.Int64, 0
%2 = struct $MyInt (%1 : $Builtin.Int64)
%3 = integer_literal $Builtin.Int1, -1
cond_br undef, bb2, bb1
bb1:
%5 = integer_literal $Builtin.Int64, 1
%6 = integer_literal $Builtin.Int1, 0
%7 = function_ref @checkSubscript : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
br bb3
bb2:
%9 = tuple ()
return %9 : $()
bb3:
cond_br undef, bb5, bb4
bb4:
%12 = function_ref @checkSubscript2 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
%13 = function_ref @makeMutable : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%14 = struct $Bool (%3 : $Builtin.Int1)
%15 = function_ref @getElementAddress : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%16 = struct_element_addr %0 : $*My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%17 = struct_element_addr %16 : $*_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%18 = struct_element_addr %17 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%19 = function_ref @makeMutable2 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%20 = function_ref @getElementAddress2 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb6(%1 : $Builtin.Int64)
bb5:
cond_br undef, bb2, bb3
bb6(%23 : $Builtin.Int64):
%24 = struct $MyInt (%23 : $Builtin.Int64)
%25 = builtin "sadd_with_overflow_Int64"(%23 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 0
%27 = apply %13(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%28 = load %0 : $*My2dArray<My2dArray<MyInt>>
%29 = struct_extract %28 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%30 = struct_extract %29 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%31 = struct_extract %30 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %31 : $Builtin.BridgeObject
%33 = apply %7(%2, %14, %28) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> ()
strong_release %31 : $Builtin.BridgeObject
%35 = load %0 : $*My2dArray<My2dArray<MyInt>>
%36 = struct_extract %35 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%37 = struct_extract %36 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%38 = struct_extract %37 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %38 : $Builtin.BridgeObject
%40 = apply %15(%2, %35) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
strong_release %38 : $Builtin.BridgeObject
%42 = load %18 : $*Builtin.BridgeObject
%43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $Builtin.NativeObject
%44 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %43 : $Builtin.NativeObject
%45 = struct_extract %40 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%46 = pointer_to_address %45 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%47 = mark_dependence %46 : $*My2dArray<MyInt> on %44 : $Optional<Builtin.NativeObject>
%48 = apply %19(%47) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%49 = load %47 : $*My2dArray<MyInt>
%50 = struct_extract %49 : $My2dArray<MyInt>, #My2dArray._buffer
%51 = struct_extract %50 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%52 = struct_extract %51 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %52 : $Builtin.BridgeObject
%54 = apply %12(%24, %14, %49) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> ()
strong_release %52 : $Builtin.BridgeObject
%56 = load %47 : $*My2dArray<MyInt>
%57 = struct_extract %56 : $My2dArray<MyInt>, #My2dArray._buffer
%58 = struct_extract %57 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%59 = struct_extract %58 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_retain %59 : $Builtin.BridgeObject
%61 = apply %20(%24, %56) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
strong_release %59 : $Builtin.BridgeObject
%63 = struct_element_addr %47 : $*My2dArray<MyInt>, #My2dArray._buffer
%64 = struct_element_addr %63 : $*_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%65 = struct_element_addr %64 : $*_MyBridgeStorage, #_MyBridgeStorage.rawValue
%66 = load %65 : $*Builtin.BridgeObject
%67 = unchecked_ref_cast %66 : $Builtin.BridgeObject to $Builtin.NativeObject
%68 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %67 : $Builtin.NativeObject
%69 = struct_extract %61 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%70 = pointer_to_address %69 : $Builtin.RawPointer to [strict] $*MyInt
%71 = mark_dependence %70 : $*MyInt on %68 : $Optional<Builtin.NativeObject>
store %24 to %71 : $*MyInt
%72 = function_ref @unknown : $@convention(thin) () -> ()
%73 = apply %72() : $@convention(thin) () -> ()
cond_br undef, bb5, bb6(%26 : $Builtin.Int64)
}
// CHECK-LABEL: sil @hoist_projections
// CHECK: bb0([[CONTAINER:%[0-9]+]]
// CHECK: [[CONTAINER2:%.*]] = struct_element_addr [[CONTAINER]] : $*ContainerContainer
// CHECK: [[ARRAY:%.*]] = struct_element_addr [[CONTAINER2]] : $*Container,
// CHECK: [[FUN:%[0-9]+]] = function_ref @array_make_mutable
// CHECK: apply [[FUN]]([[ARRAY]]
// CHECK: bb1
// CHECK-NOT: array_make_mutable
// CHECK-NOT: apply [[FUN]]
sil @hoist_projections : $@convention(thin) (@inout ContainerContainer, @inout Builtin.Int1) -> () {
bb0(%0 : $*ContainerContainer, %1 : $*Builtin.Int1):
br bb1
bb1:
%2 = struct_element_addr %0 : $*ContainerContainer, #ContainerContainer.container
br bb3(%2 : $*Container)
bb3(%3: $*Container):
%4 = struct_element_addr %3 : $*Container, #Container.array
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%4) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// We don't support hoisting non-unary projections yet.
// CHECK-LABEL: sil @dont_hoist_non_unary_projections
// CHECK-NOT: index_addr
// CHECK: bb2({{.*}}):
// CHECK: index_addr
sil @dont_hoist_non_unary_projections : $@convention(thin) (@inout ContainerContainer, @inout Builtin.Int1) -> () {
bb0(%0 : $*ContainerContainer, %1 : $*Builtin.Int1):
br bb1
bb1:
%2 = struct_element_addr %0 : $*ContainerContainer, #ContainerContainer.container
br bb2(%2 : $*Container)
bb2(%3: $*Container):
%i = integer_literal $Builtin.Int32, 0
%3i = index_addr %3 : $*Container, %i : $Builtin.Int32
%4 = struct_element_addr %3i : $*Container, #Container.array
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%4) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb3
bb3:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_projections2
// CHECK: bb0([[CONTAINER:%[0-9]+]]
// CHECK: [[CONTAINER2:%.*]] = struct_element_addr [[CONTAINER]] : $*ContainerContainer
// CHECK: [[ARRAY:%.*]] = struct_element_addr [[CONTAINER2]] : $*Container,
// CHECK: [[FUN:%[0-9]+]] = function_ref @array_make_mutable
// CHECK: apply [[FUN]]([[ARRAY]]
// CHECK: bb1
// CHECK-NOT: array_make_mutable
// CHECK-NOT: apply [[FUN]]
sil @hoist_projections2 : $@convention(thin) (@inout ContainerContainer, @inout Builtin.Int1) -> () {
bb0(%0 : $*ContainerContainer, %1 : $*Builtin.Int1):
br bb1
bb1:
%2 = struct_element_addr %0 : $*ContainerContainer, #ContainerContainer.container
%3 = struct_element_addr %2 : $*Container, #Container.array
br bb3(%3 : $*MyArray<MyStruct>)
bb3(%4 : $*MyArray<MyStruct>):
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%4) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
// CHECK-LABEL: sil @hoist_projections3
// CHECK: bb0([[CONTAINER:%[0-9]+]]
// CHECK: [[CONTAINER2:%.*]] = struct_element_addr [[CONTAINER]] : $*ContainerContainer
// CHECK: [[ARRAY:%.*]] = struct_element_addr [[CONTAINER2]] : $*Container,
// CHECK: [[FUN:%[0-9]+]] = function_ref @array_make_mutable
// CHECK: apply [[FUN]]([[ARRAY]]
// CHECK: bb1
// CHECK-NOT: array_make_mutable
// CHECK-NOT: apply [[FUN]]
sil @hoist_projections3 : $@convention(thin) (@inout ContainerContainer, @inout Builtin.Int1) -> () {
bb0(%0 : $*ContainerContainer, %1 : $*Builtin.Int1):
br bb1
bb1:
%2 = struct_element_addr %0 : $*ContainerContainer, #ContainerContainer.container
%3 = struct_element_addr %2 : $*Container, #Container.array
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%3) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb2
bb2:
%7 = tuple()
return %7 : $()
}
sil [_semantics "array.props.isNativeTypeChecked"] @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed My2dArray<My2dArray<MyInt>>) -> Bool
sil [_semantics "array.check_subscript"] @checkSubscript3 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> _DependenceToken
sil [_semantics "array.get_element"] @getElement3 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @out My2dArray<MyInt>
sil [_semantics "array.props.isNativeTypeChecked"] @hoistableIsNativeTypeChecked2 : $@convention(method) (@guaranteed My2dArray<MyInt>) -> Bool
sil [_semantics "array.check_subscript"] @checkSubscript4 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
sil [_semantics "array.get_element"] @getElement4 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> @out MyInt
sil [_semantics "array.make_mutable"] @makeMutable3 : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
sil [_semantics "array.get_element_address"] @getElementAddress3 : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
sil [_semantics "array.make_mutable"] @makeMutable4 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
sil [_semantics "array.get_element_address"] @getElementAddress4 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
// CHECK-LABEL: sil @hoist2DArray_2
// CHECK: bb0
// CHECK: apply {{.*}} : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
// CHECK: apply {{.*}} : $@convention(method) (@inout My2dArray<MyInt>) -> ()
// CHECK: br bb2
// CHECK: bb1
// CHECK: return
// CHECK: bb2
// CHECK-NOT: apply {{.*}} : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
// CHECK-NOT: apply {{.*}} : $@convention(method) (@inout My2dArray<MyInt>) -> ()
// CHECK: cond_br
sil @hoist2DArray_2 : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>, MyInt) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>, %1 : $MyInt):
%4 = integer_literal $Builtin.Int64, 0
%5 = integer_literal $Builtin.Int64, 1024
%6 = integer_literal $Builtin.Int64, 1
%7 = integer_literal $Builtin.Int1, 0
%9 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed My2dArray<My2dArray<MyInt>>) -> Bool
%10 = function_ref @checkSubscript3 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> _DependenceToken
%11 = function_ref @getElement3 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @out My2dArray<MyInt>
%12 = function_ref @hoistableIsNativeTypeChecked2 : $@convention(method) (@guaranteed My2dArray<MyInt>) -> Bool
%13 = function_ref @checkSubscript4 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%14 = function_ref @getElement4 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> @out MyInt
%15 = integer_literal $Builtin.Int1, -1
%18 = function_ref @makeMutable3 : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%20 = struct $Bool (%15 : $Builtin.Int1)
%21 = function_ref @getElementAddress3 : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%22 = function_ref @makeMutable4 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%23 = function_ref @getElementAddress4 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb2(%4 : $Builtin.Int64)
bb1:
%25 = tuple ()
return %25 : $()
bb2(%27 : $Builtin.Int64):
%28 = struct $MyInt (%27 : $Builtin.Int64)
%29 = builtin "sadd_with_overflow_Int64"(%27 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%30 = tuple_extract %29 : $(Builtin.Int64, Builtin.Int1), 0
%32 = load %0 : $*My2dArray<My2dArray<MyInt>>
%33 = alloc_stack $My2dArray<MyInt>
%35 = apply %9(%32) : $@convention(method) (@guaranteed My2dArray<My2dArray<MyInt>>) -> Bool
%37 = apply %10(%1, %35, %32) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> _DependenceToken
%39 = apply %11(%33, %1, %35, %37, %32) : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @out My2dArray<MyInt>
%40 = load %33 : $*My2dArray<MyInt>
%41 = alloc_stack $MyInt
%44 = apply %12(%40) : $@convention(method) (@guaranteed My2dArray<MyInt>) -> Bool
%46 = apply %13(%28, %44, %40) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%48 = apply %14(%41, %28, %44, %46, %40) : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> @out MyInt
%49 = struct_extract %40 : $My2dArray<MyInt>, #My2dArray._buffer
%50 = struct_extract %49 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%51 = struct_extract %50 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_release %51 : $Builtin.BridgeObject
%53 = struct_element_addr %41 : $*MyInt, #MyInt._value
%54 = load %53 : $*Builtin.Int64
%55 = builtin "sadd_with_overflow_Int64"(%54 : $Builtin.Int64, %6 : $Builtin.Int64, %15 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%56 = tuple_extract %55 : $(Builtin.Int64, Builtin.Int1), 0
%57 = tuple_extract %55 : $(Builtin.Int64, Builtin.Int1), 1
cond_fail %57 : $Builtin.Int1
%59 = struct $MyInt (%56 : $Builtin.Int64)
%60 = apply %18(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%61 = load %0 : $*My2dArray<My2dArray<MyInt>>
%63 = apply %21(%1, %61) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%65 = struct_extract %61 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%66 = struct_extract %65 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%67 = struct_extract %66 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
%72 = unchecked_ref_cast %67 : $Builtin.BridgeObject to $Builtin.NativeObject
%73 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %72 : $Builtin.NativeObject
%74 = struct_extract %63 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%75 = pointer_to_address %74 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%76 = mark_dependence %75 : $*My2dArray<MyInt> on %73 : $Optional<Builtin.NativeObject>
%79 = apply %22(%76) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%80 = load %76 : $*My2dArray<MyInt>
%83 = apply %13(%28, %20, %80) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%84 = apply %23(%28, %80) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
%86 = struct_extract %80 : $My2dArray<MyInt>, #My2dArray._buffer
%87 = struct_extract %86 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%88 = struct_extract %87 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
%93 = unchecked_ref_cast %88 : $Builtin.BridgeObject to $Builtin.NativeObject
%94 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %93 : $Builtin.NativeObject
%95 = struct_extract %84 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%96 = pointer_to_address %95 : $Builtin.RawPointer to [strict] $*MyInt
%97 = mark_dependence %96 : $*MyInt on %94 : $Optional<Builtin.NativeObject>
store %59 to %97 : $*MyInt
dealloc_stack %41 : $*MyInt
dealloc_stack %33 : $*My2dArray<MyInt>
%101 = builtin "cmp_eq_Int64"(%30 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
cond_br %101, bb1, bb2(%30 : $Builtin.Int64)
}
sil [_semantics "array.get_element"] @getElement5 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @owned My2dArray<MyInt>
sil [_semantics "array.get_element"] @getElement6 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> MyInt
// CHECK-LABEL: sil @hoist2DArray_with_get_element_returning_direct_result
// CHECK: bb0
// CHECK: apply {{.*}} : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
// CHECK: apply {{.*}} : $@convention(method) (@inout My2dArray<MyInt>) -> ()
// CHECK: br bb2
// CHECK: bb1
// CHECK: return
// CHECK: bb2
// CHECK-NOT: apply {{.*}} : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
// CHECK-NOT: apply {{.*}} : $@convention(method) (@inout My2dArray<MyInt>) -> ()
// CHECK: cond_br
sil @hoist2DArray_with_get_element_returning_direct_result : $@convention(thin) (@inout My2dArray<My2dArray<MyInt>>, MyInt) -> () {
bb0(%0 : $*My2dArray<My2dArray<MyInt>>, %1 : $MyInt):
%4 = integer_literal $Builtin.Int64, 0
%5 = integer_literal $Builtin.Int64, 1024
%6 = integer_literal $Builtin.Int64, 1
%7 = integer_literal $Builtin.Int1, 0
%9 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed My2dArray<My2dArray<MyInt>>) -> Bool
%10 = function_ref @checkSubscript3 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> _DependenceToken
%11 = function_ref @getElement5 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @owned My2dArray<MyInt>
%12 = function_ref @hoistableIsNativeTypeChecked2 : $@convention(method) (@guaranteed My2dArray<MyInt>) -> Bool
%13 = function_ref @checkSubscript4 : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%14 = function_ref @getElement6 : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> MyInt
%15 = integer_literal $Builtin.Int1, -1
%18 = function_ref @makeMutable3 : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%20 = struct $Bool (%15 : $Builtin.Int1)
%21 = function_ref @getElementAddress3 : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%22 = function_ref @makeMutable4 : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%23 = function_ref @getElementAddress4 : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
br bb2(%4 : $Builtin.Int64)
bb1:
%25 = tuple ()
return %25 : $()
bb2(%27 : $Builtin.Int64):
%28 = struct $MyInt (%27 : $Builtin.Int64)
%29 = builtin "sadd_with_overflow_Int64"(%27 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%30 = tuple_extract %29 : $(Builtin.Int64, Builtin.Int1), 0
%32 = load %0 : $*My2dArray<My2dArray<MyInt>>
%35 = apply %9(%32) : $@convention(method) (@guaranteed My2dArray<My2dArray<MyInt>>) -> Bool
%37 = apply %10(%1, %35, %32) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<My2dArray<MyInt>>) -> _DependenceToken
%40 = apply %11(%1, %35, %37, %32) : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<My2dArray<MyInt>>) -> @owned My2dArray<MyInt>
%44 = apply %12(%40) : $@convention(method) (@guaranteed My2dArray<MyInt>) -> Bool
%46 = apply %13(%28, %44, %40) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%48 = apply %14(%28, %44, %46, %40) : $@convention(method) (MyInt, Bool, _DependenceToken, @guaranteed My2dArray<MyInt>) -> MyInt
%49 = struct_extract %40 : $My2dArray<MyInt>, #My2dArray._buffer
%50 = struct_extract %49 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%51 = struct_extract %50 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
strong_release %51 : $Builtin.BridgeObject
%54 = struct_extract %48 : $MyInt, #MyInt._value
%55 = builtin "sadd_with_overflow_Int64"(%54 : $Builtin.Int64, %6 : $Builtin.Int64, %15 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%56 = tuple_extract %55 : $(Builtin.Int64, Builtin.Int1), 0
%57 = tuple_extract %55 : $(Builtin.Int64, Builtin.Int1), 1
cond_fail %57 : $Builtin.Int1
%59 = struct $MyInt (%56 : $Builtin.Int64)
%60 = apply %18(%0) : $@convention(method) (@inout My2dArray<My2dArray<MyInt>>) -> ()
%61 = load %0 : $*My2dArray<My2dArray<MyInt>>
%63 = apply %21(%1, %61) : $@convention(method) (MyInt, @guaranteed My2dArray<My2dArray<MyInt>>) -> UnsafeMutablePointer<My2dArray<MyInt>>
%65 = struct_extract %61 : $My2dArray<My2dArray<MyInt>>, #My2dArray._buffer
%66 = struct_extract %65 : $_My2dArrayBuffer<My2dArray<MyInt>>, #_My2dArrayBuffer._storage
%67 = struct_extract %66 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
%72 = unchecked_ref_cast %67 : $Builtin.BridgeObject to $Builtin.NativeObject
%73 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %72 : $Builtin.NativeObject
%74 = struct_extract %63 : $UnsafeMutablePointer<My2dArray<MyInt>>, #UnsafeMutablePointer._rawValue
%75 = pointer_to_address %74 : $Builtin.RawPointer to [strict] $*My2dArray<MyInt>
%76 = mark_dependence %75 : $*My2dArray<MyInt> on %73 : $Optional<Builtin.NativeObject>
%79 = apply %22(%76) : $@convention(method) (@inout My2dArray<MyInt>) -> ()
%80 = load %76 : $*My2dArray<MyInt>
%83 = apply %13(%28, %20, %80) : $@convention(method) (MyInt, Bool, @guaranteed My2dArray<MyInt>) -> _DependenceToken
%84 = apply %23(%28, %80) : $@convention(method) (MyInt, @guaranteed My2dArray<MyInt>) -> UnsafeMutablePointer<MyInt>
%86 = struct_extract %80 : $My2dArray<MyInt>, #My2dArray._buffer
%87 = struct_extract %86 : $_My2dArrayBuffer<MyInt>, #_My2dArrayBuffer._storage
%88 = struct_extract %87 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
%93 = unchecked_ref_cast %88 : $Builtin.BridgeObject to $Builtin.NativeObject
%94 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %93 : $Builtin.NativeObject
%95 = struct_extract %84 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
%96 = pointer_to_address %95 : $Builtin.RawPointer to [strict] $*MyInt
%97 = mark_dependence %96 : $*MyInt on %94 : $Optional<Builtin.NativeObject>
store %59 to %97 : $*MyInt
%101 = builtin "cmp_eq_Int64"(%30 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
cond_br %101, bb1, bb2(%30 : $Builtin.Int64)
}