blob: d9c5fe9bd1fa36eb6a551e6bb4cc00467158d3b0 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -enable-abcopts=1 %s | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -dce -enable-abcopts -enable-abc-hoisting %s | %FileCheck %s --check-prefix=HOIST
// RUN: %target-sil-opt -enable-sil-verify-all -abcopts %s | %FileCheck %s --check-prefix=RANGECHECK
sil_stage canonical
import Builtin
import Swift
struct _DependenceToken {}
struct ArrayIntBuffer {
var storage : Builtin.NativeObject
}
final class StorageBase {
@_hasStorage var header: Int64
}
struct ArrayInt{
var buffer : ArrayIntBuffer
}
struct UnsafeMutablePointerInt {
var _rawValue : Builtin.RawPointer
}
struct IntTupleStruct {
var tuple: (Int32, Int32)
}
// CHECK-LABEL: sil @abcopt_singleblock
sil @abcopt_singleblock : $@convention(thin) (@inout ArrayInt, @inout ArrayInt) -> () {
bb0(%0 : $*ArrayInt, %1 : $*ArrayInt):
%100 = function_ref @arrayPropertyIsNative : $@convention(method) (@owned ArrayInt) -> Bool
%101 = load %0 : $*ArrayInt
%102 = apply %100(%101) : $@convention(method) (@owned ArrayInt) -> Bool
// Don't assert on functions that are marked with array semantics but are not
// methods.
%302 = function_ref @checkbounds_no_meth : $@convention(thin) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%303 = load %0 : $*ArrayInt
%304 = struct_extract %303 : $ArrayInt, #ArrayInt.buffer
%305 = struct_extract %304 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %305 : $Builtin.NativeObject
%306 = integer_literal $Builtin.Int32, 0
%307 = struct $Int32(%306 : $Builtin.Int32)
%308 = apply %302(%307, %102, %303) : $@convention(thin) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[CHECKBOUNDSNO:%[0-9]+]] = function_ref @checkbounds_no_meth
%200 = function_ref @arrayinit: $@convention(thin) () -> @owned ArrayInt
%201 = apply %200() : $@convention(thin) () -> @owned ArrayInt
// CHECK: [[CHECKBOUNDS:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD1:%[0-9]+]] = load %0
%2 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%3 = load %0 : $*ArrayInt
%4 = struct_extract %3 : $ArrayInt, #ArrayInt.buffer
%5 = struct_extract %4 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %5 : $Builtin.NativeObject
// First check.
%x1 = integer_literal $Builtin.Int32, 1
%i1 = struct $Int32(%x1 : $Builtin.Int32)
%8 = apply %2(%i1, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[IDX1:%[0-9]+]] = struct $Int32
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]]
// Redundant same index and array.
retain_value %5 : $Builtin.NativeObject
%9 = apply %2(%i1, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK-NOT: apply [[CHECKBOUNDS]]([[IDX1]]
// Redundant same index and array and retain the array directly instead of
// through the array buffer storage.
retain_value %3 : $ArrayInt
%r9 = apply %2(%i1, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK-NOT: apply [[CHECKBOUNDS]]([[IDX1]]
// Redundant same index and array, but loaded again.
%l0 = load %0 : $*ArrayInt
retain_value %5 : $Builtin.NativeObject
%10 = apply %2(%i1, %102, %l0) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK-NOT: apply [[CHECKBOUNDS]]([[IDX1]]
// Not redundant - different index.
%x2 = integer_literal $Builtin.Int32, 2
%i2 = struct $Int32(%x2 : $Builtin.Int32)
retain_value %5 : $Builtin.NativeObject
%12 = apply %2(%i2, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[IDX2:%[0-9]+]] = struct $Int32
// CHECK: apply [[CHECKBOUNDS]]([[IDX2]]
// Not redundant - different array.
%13 = load %1 : $*ArrayInt
%14 = struct_extract %13 : $ArrayInt, #ArrayInt.buffer
%15 = struct_extract %14 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %15 : $Builtin.NativeObject
%16 = apply %2(%i1, %102, %13) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[LD2:%[0-9]+]] = load %1
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]], {{.*}}[[LD2]]
// Not redundant same index and array but append in between.
%17 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
%18 = alloc_stack $Int32
%19 = apply %17(%18, %0) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
retain_value %5 : $Builtin.NativeObject
%l2 = load %0 : $*ArrayInt
%20 = apply %2(%i1, %102, %l2) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[LD2:%[0-9]+]] = load %0
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]], {{.*}}[[LD2]]
// Not redundant same index and array but unknown function in between.
%x3 = integer_literal $Builtin.Int32, 3
%i3 = struct $Int32(%x3 : $Builtin.Int32)
retain_value %5 : $Builtin.NativeObject
%21 = apply %2(%i3, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[IDX3:%[0-9]+]] = struct $Int32
// CHECK: apply [[CHECKBOUNDS]]([[IDX3]], {{.*}}[[LD1]]
%22 = function_ref @unknown_func : $@convention(thin) () -> ()
%23 = apply %22() : $@convention(thin) () -> ()
// CHECK: [[UNKNOWN:%[0-9]+]] = function_ref @unknown_func
// CHECK: apply [[UNKNOWN]]()
%l3 = load %0 : $*ArrayInt
// CHECK: [[LD3:%[0-9]+]] = load %0
retain_value %5 : $Builtin.NativeObject
%24 = apply %2(%i3, %102, %l3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS]]([[IDX3]], {{.*}}[[LD3]]
// Not redundant same index and array but odd store in between.
%x4 = integer_literal $Builtin.Int32, 4
%i4 = struct $Int32(%x4 : $Builtin.Int32)
retain_value %5 : $Builtin.NativeObject
%25 = apply %2(%i4, %102, %3) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: [[IDX4:%[0-9]+]] = struct $Int32
// CHECK: apply [[CHECKBOUNDS]]([[IDX4]], {{.*}}[[LD1]]
%26 = ref_to_raw_pointer %5 : $Builtin.NativeObject to $Builtin.RawPointer
%27 = pointer_to_address %26 : $Builtin.RawPointer to [strict] $*Builtin.Int32
store %x1 to %27 : $*Builtin.Int32
%l4 = load %0 : $*ArrayInt
retain_value %5 : $Builtin.NativeObject
%30 = apply %2(%i4, %102, %l4) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: store
// CHECK: [[LD4:%[0-9]+]] = load %0
// CHECK: apply [[CHECKBOUNDS]]([[IDX4]], {{.*}}[[LD4]]
dealloc_stack %18 : $*Int32
%99 = tuple ()
return %99 : $()
// CHECK: return
}
// CHECK-LABEL: sil @not_dominating
sil @not_dominating : $@convention(thin) (Int32, @inout ArrayInt, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt, %25 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32):
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Int32"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
// CHECK: struct $Int32
bb4:
%36 = integer_literal $Builtin.Int32, 0
%37 = struct $Int32(%36 : $Builtin.Int32)
cond_br %8, bb5, bb6
// CHECK: [[IDX1:%[0-9]+]] = struct $Int32
bb5:
%32 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%33 = load %24 : $*ArrayInt
%34 = struct_extract %33 : $ArrayInt, #ArrayInt.buffer
%35 = struct_extract %34 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %35 : $Builtin.NativeObject
%38 = apply %32(%37, %101, %33) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
br bb2
// CHECK: [[CHECKBOUNDS:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD1:%[0-9]+]] = load {{.*}} : $*ArrayInt
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]]
bb6:
// CHECK: [[CHECKBOUNDS2:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD2:%[0-9]+]] = load {{.*}} : $*ArrayInt
%42 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%43 = load %24 : $*ArrayInt
%44 = struct_extract %43 : $ArrayInt, #ArrayInt.buffer
%45 = struct_extract %44 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %45 : $Builtin.NativeObject
%48 = apply %42(%37, %101, %43) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS2]]([[IDX1]]
br bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt.1, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt.1
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// CHECK: return
// CHECK-LABEL: sil @dominating
sil @dominating : $@convention(thin) (Int32, @inout ArrayInt, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt, %25 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32):
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Int32"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
// CHECK: struct $Int32
bb4:
%36 = integer_literal $Builtin.Int32, 0
%37 = struct $Int32(%36 : $Builtin.Int32)
// CHECK: [[IDX1:%[0-9]+]] = struct $Int32
// CHECK: [[CHECKBOUNDS3:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD3:%[0-9]+]] = load {{.*}} : $*ArrayInt
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS3]]([[IDX1]], {{.*}}[[LD3]]
cond_br %8, bb5, bb6
bb5:
// CHECK: [[CHECKBOUNDS:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD1:%[0-9]+]] = load {{.*}} : $*ArrayInt
%32 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%33 = load %24 : $*ArrayInt
%34 = struct_extract %33 : $ArrayInt, #ArrayInt.buffer
%35 = struct_extract %34 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %35 : $Builtin.NativeObject
%38 = apply %32(%37, %101, %33) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK-NOT: apply [[CHECKBOUNDS]]([[IDX1]], {{.*}}[[LD1]]
br bb2
bb6:
// CHECK: [[CHECKBOUNDS2:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD2:%[0-9]+]] = load {{.*}} : $*ArrayInt
%42 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%43 = load %24 : $*ArrayInt
%44 = struct_extract %43 : $ArrayInt, #ArrayInt.buffer
%45 = struct_extract %44 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %45 : $Builtin.NativeObject
%48 = apply %42(%37, %101, %43) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK-NOT: apply [[CHECKBOUNDS2]]([[IDX1]], {{.*}}[[LD2]]
br bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt.1, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt.1
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// CHECK: return
// CHECK-LABEL: sil @dominating_but_append
sil @dominating_but_append : $@convention(thin) (Int32, @inout ArrayInt, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt, %25 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32):
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Int32"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
// CHECK: struct $Int32
bb4:
%36 = integer_literal $Builtin.Int32, 0
%37 = struct $Int32(%36 : $Builtin.Int32)
// CHECK: [[IDX1:%[0-9]+]] = struct $Int32
// CHECK: [[CHECKBOUNDS3:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD3:%[0-9]+]] = load {{.*}} : $*ArrayInt
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS3]]([[IDX1]], {{.*}}[[LD3]]
cond_br %8, bb5, bb6
bb5:
// CHECK: [[CHECKBOUNDS:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD1:%[0-9]+]] = load {{.*}} : $*ArrayInt
%32 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%33 = load %24 : $*ArrayInt
%34 = struct_extract %33 : $ArrayInt, #ArrayInt.buffer
%35 = struct_extract %34 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %35 : $Builtin.NativeObject
%38 = apply %32(%37, %101, %33) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]], {{.*}}[[LD1]]
br bb2
bb6:
// CHECK: [[CHECKBOUNDS2:%[0-9]+]] = function_ref @checkbounds
// CHECK: [[LD2:%[0-9]+]] = load {{.*}} : $*ArrayInt
%42 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%43 = load %24 : $*ArrayInt
%44 = struct_extract %43 : $ArrayInt, #ArrayInt.buffer
%45 = struct_extract %44 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %45 : $Builtin.NativeObject
%48 = apply %42(%37, %101, %43) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
// CHECK: apply [[CHECKBOUNDS2]]([[IDX1]], {{.*}}[[LD2]]
br bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt.1, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt.1
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%117 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
%118 = alloc_stack $Int32
%119 = apply %117(%118, %24) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
retain_value %55 : $Builtin.NativeObject
%120 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
dealloc_stack %118 : $*Int32
// CHECK: [[APPEND:%[0-9]+]] = function_ref @append
// CHECK: apply [[APPEND]]
// CHECK: apply [[CHECKBOUNDS3]]
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// CHECK: return
// HOIST-LABEL: sil @hoist
// HOIST: bb0
// HOIST: [[END:%[0-9]+]] = struct_extract %0 : $Int32, #Int32._value
// HOIST: [[ZERO:%[0-9]+]] = integer_literal $Builtin.Int32, 0
// HOIST: cond_br
// HOIST: bb1
// Check overflow.
// HOIST: [[CB1:%[0-9]+]] = function_ref @checkbounds
// HOIST: [[SGE1:%[0-9]+]] = builtin "cmp_sge_Int32"([[ZERO]] : ${{.*}}, [[END]]
// HOIST: cond_fail [[SGE1]]
// Check start.
// HOIST: [[S1:%[0-9]+]] = struct $Int32 ([[ZERO]] : $Builtin.Int32)
// HOIST: [[L1:%[0-9]+]] = load %1 : $*ArrayInt
// HOIST: retain_value [[L1]]
// HOIST: apply [[CB1]]([[S1]], {{.*}}[[L1]])
// Check end.
// HOIST: [[ONE:%[0-9]+]] = integer_literal $Builtin.Int32, 1
// HOIST: [[SUB1:%[0-9]+]] = builtin "ssub_with_overflow_Int32"([[END]] : ${{.*}}, [[ONE]]
// HOIST: [[SUB2:%[0-9]+]] = tuple_extract [[SUB1]]
// HOIST: [[SUB3:%[0-9]+]] = struct $Int32 ([[SUB2]]
// HOIST: [[L2:%[0-9]+]] = load %1
// HOIST: retain_value [[L2]]
// HOIST: apply [[CB1]]([[SUB3]], {{.*}}[[L2]])
// HOIST: br bb3
// HOIST: bb3
// HOIST-NOT: cond_fail
// HOIST-NOT: @checkbounds
// HOIST: builtin
// HOIST: builtin
// HOIST-NOT: builtin
// HOIST: cond_br {{.*}}, {{.*}}, bb4
// HOIST: bb4
// HOIST: br bb3
// HOIST: return
sil @hoist : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%22 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %22 : $Builtin.Int1
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @always_false_hoist
// HOIST: bb4
// HOIST: builtin "sadd_with_overflow_Int32"
// HOIST: tuple_extract
// HOIST-NOT: builtin "cmp_slt_Int32"
// HOIST-NOT: builtin "cmp_sle_Int32"
// HOIST-NOT: builtin "cmp_eq_Int32"
// HOIST: cond_fail
// HOIST: cond_fail
// HOIST: cond_fail
// HOIST: cond_fail
// HOIST: builtin "cmp_eq_Int32"
// HOIST: cond_br
// HOIST: }
sil @always_false_hoist : $@convention(thin) (@owned Array<Int>) -> () {
bb0(%0 : $Array<Int>):
%z0 = integer_literal $Builtin.Int32, 0
%f1 = function_ref @getCount2 : $@convention(method) (@owned Array<Int>) -> Int32
retain_value %0 : $Array<Int>
%t1 = apply %f1(%0) : $@convention(method) (@owned Array<Int>) -> Int32
%c1 = struct_extract %t1 : $Int32, #Int32._value
%t2 = builtin "cmp_eq_Int32"(%z0 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %t2, bb5, bb1
bb1:
br bb2(%z0 : $Builtin.Int32)
bb2(%i0 : $Builtin.Int32):
cond_br undef, bb3, bb4
bb3:
%f2 = function_ref @checkbounds2 : $@convention(method) (Int32, Bool, @owned Array<Int>) -> _DependenceToken
retain_value %0 : $Array<Int>
%t3 = struct $Int32(%i0 : $Builtin.Int32)
br bb4
bb4:
%t5 = integer_literal $Builtin.Int1, 0
%i2 = integer_literal $Builtin.Int32, 1
%t6 = builtin "sadd_with_overflow_Int32"(%i0 : $Builtin.Int32, %i2 : $Builtin.Int32, %t5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%t7 = tuple_extract %t6 : $(Builtin.Int32, Builtin.Int1), 0
%t8 = tuple_extract %t6 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %t8 : $Builtin.Int1
%af1 = builtin "cmp_slt_Int32"(%i0 : $Builtin.Int32, %z0 : $Builtin.Int32) : $Builtin.Int1
cond_fail %af1 : $Builtin.Int1
%af2 = builtin "cmp_slt_Int32"(%t7 : $Builtin.Int32, %z0 : $Builtin.Int32) : $Builtin.Int1
cond_fail %af2 : $Builtin.Int1
%af3 = builtin "cmp_sle_Int32"(%t7 : $Builtin.Int32, %z0 : $Builtin.Int32) : $Builtin.Int1
cond_fail %af3 : $Builtin.Int1
%af4 = builtin "cmp_eq_Int32"(%t7 : $Builtin.Int32, %z0 : $Builtin.Int32) : $Builtin.Int1
cond_fail %af4 : $Builtin.Int1
%8 = builtin "cmp_eq_Int32"(%t7 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb5, bb2(%t7 : $Builtin.Int32)
bb5:
%r1 = tuple ()
return %r1 : $()
}
// HOIST-LABEL: sil @hoistinvariant
// Preheader.
// HOIST: bb1:
// HOIST: [[SGE1:%[0-9]+]] = builtin "cmp_sge_Int32"
// HOIST: cond_fail [[SGE1]]
// HOIST: load %1 : $*ArrayInt
// HOIST: retain_value
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb3
// Loop.
// HOIST: bb3{{.*}}:
// HOIST-NOT: cond_fail
// HOIST-NOT: @checkbounds
// HOIST: builtin
// HOIST: builtin
// HOIST-NOT: builtin
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4:
// HOIST: br bb3
// HOIST: bb5:
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @hoistinvariant : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%37 = struct $Int32(%2 : $Builtin.Int32)
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%22 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %22 : $Builtin.Int1
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @hoistinvariant_array_is_not_an_arg
// HOIST: bb0{{.*}}:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb1
// HOIST: bb3{{.*}}:
// HOIST-NOT: apply
// HOIST: return
sil @hoistinvariant_array_is_not_an_arg : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%37 = struct $Int32(%2 : $Builtin.Int32)
%f1 = function_ref @getArray : $@convention(thin) () -> ArrayInt
%x53 = apply %f1() : $@convention(thin) () -> ArrayInt
%x54 = struct_extract %x53 : $ArrayInt, #ArrayInt.buffer
%x55 = struct_extract %x54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %x55 : $Builtin.NativeObject
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%58 = apply %52(%37, %101, %x53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%22 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %22 : $Builtin.Int1
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb2, bb1(%21 : $Builtin.Int32)
bb2:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @hoist_rangechecked
// HOIST: bb0
// HOIST: cond_br {{.*}}, bb1{{.*}}, bb2
// HOIST: bb1:
// HOIST: br bb6
// HOIST: bb2:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb3{{.*}}
// HOIST: bb3{{.*}}:
// HOIST-NOT: function_ref @checkbounds
// HOIST-NOT: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4
// HOIST: br bb3
// HOIST: bb5
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @hoist_rangechecked : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%3 = integer_literal $Builtin.Int1, -1
%61 = builtin "cmp_sle_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%14 = builtin "xor_Int1"(%61 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %14 : $Builtin.Int1
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%40 = function_ref @getElementAddr : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
retain_value %55 : $Builtin.NativeObject
%42 = apply %40(%37, %53) : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
%43 = struct_extract %42 : $UnsafeMutablePointerInt, #UnsafeMutablePointerInt._rawValue
%44 = pointer_to_address %43 : $Builtin.RawPointer to [strict] $*Int32
store %0 to %44 : $*Int32
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @hoist_rangechecked_ref_tail_addr
// HOIST: bb0
// HOIST: cond_br {{.*}}, bb1{{.*}}, bb2
// HOIST: bb1:
// HOIST: br bb6
// HOIST: bb2:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb3{{.*}}
// HOIST: bb3{{.*}}:
// HOIST-NOT: function_ref @checkbounds
// HOIST-NOT: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4
// HOIST: br bb3
// HOIST: bb5
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @hoist_rangechecked_ref_tail_addr : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%3 = integer_literal $Builtin.Int1, -1
%61 = builtin "cmp_sle_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%14 = builtin "xor_Int1"(%61 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %14 : $Builtin.Int1
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
retain_value %55 : $Builtin.NativeObject
%69 = unchecked_ref_cast %55 : $Builtin.NativeObject to $StorageBase
%70 = ref_tail_addr %69 : $StorageBase, $Int32
%71 = index_addr %70 : $*Int32, %4 : $Builtin.Int32
store %0 to %71 : $*Int32
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @eliminate_zero_to_count
// HOIST-NOT: function_ref @checkbounds2
// HOIST: return
sil @eliminate_zero_to_count : $@convention(thin) (@owned Array<Int>) -> () {
bb0(%0 : $Array<Int>):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%z0 = integer_literal $Builtin.Int32, 0
%f1 = function_ref @getCount2 : $@convention(method) (@owned Array<Int>) -> Int32
retain_value %0 : $Array<Int>
%t1 = apply %f1(%0) : $@convention(method) (@owned Array<Int>) -> Int32
%c1 = struct_extract %t1 : $Int32, #Int32._value
%t2 = builtin "cmp_eq_Int32"(%z0 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %t2, bb5, bb1
bb1:
br bb2(%z0 : $Builtin.Int32)
bb2(%i0 : $Builtin.Int32):
cond_br undef, bb3, bb4
bb3:
%f2 = function_ref @checkbounds2 : $@convention(method) (Int32, Bool, @owned Array<Int>) -> _DependenceToken
retain_value %0 : $Array<Int>
%t3 = struct $Int32(%i0 : $Builtin.Int32)
// This subscript check can be completely eliminated because the loop goes
// from 0 to array.count.
// It's even not required that this loop block dominates the exit block.
%t4 = apply %f2(%t3, %101, %0) : $@convention(method) (Int32, Bool, @owned Array<Int>) -> _DependenceToken
br bb4
bb4:
%t5 = integer_literal $Builtin.Int1, 0
%i2 = integer_literal $Builtin.Int32, 1
%t6 = builtin "sadd_with_overflow_Int32"(%i0 : $Builtin.Int32, %i2 : $Builtin.Int32, %t5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%t7 = tuple_extract %t6 : $(Builtin.Int32, Builtin.Int1), 0
%8 = builtin "cmp_eq_Int32"(%t7 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb5, bb2(%t7 : $Builtin.Int32)
bb5:
%r1 = tuple ()
return %r1 : $()
}
// HOIST-LABEL: sil @dont_eliminate_zero_to_count_for_slices
// HOIST: {{^}}bb1:
// HOIST: [[F:%[0-9]+]] = function_ref @checkbounds3
// HOIST: apply [[F]]
// HOIST: return
sil @dont_eliminate_zero_to_count_for_slices : $@convention(thin) (@owned ArraySlice<Int>) -> () {
bb0(%0 : $ArraySlice<Int>):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%z0 = integer_literal $Builtin.Int32, 0
%f1 = function_ref @getCount3 : $@convention(method) (@owned ArraySlice<Int>) -> Int32
retain_value %0 : $ArraySlice<Int>
%t1 = apply %f1(%0) : $@convention(method) (@owned ArraySlice<Int>) -> Int32
%c1 = struct_extract %t1 : $Int32, #Int32._value
%t2 = builtin "cmp_eq_Int32"(%z0 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %t2, bb2, bb1(%z0 : $Builtin.Int32)
bb1(%i0 : $Builtin.Int32):
%f2 = function_ref @checkbounds3 : $@convention(method) (Int32, Bool, @owned ArraySlice<Int>) -> _DependenceToken
retain_value %0 : $ArraySlice<Int>
%t3 = struct $Int32(%i0 : $Builtin.Int32)
// Slices don't necessarily have a zero lower bound. So we can't eliminate the
// subscript check for 0..<count loops.
%t4 = apply %f2(%t3, %101, %0) : $@convention(method) (Int32, Bool, @owned ArraySlice<Int>) -> _DependenceToken
%t5 = integer_literal $Builtin.Int1, 0
%i2 = integer_literal $Builtin.Int32, 1
%t6 = builtin "sadd_with_overflow_Int32"(%i0 : $Builtin.Int32, %i2 : $Builtin.Int32, %t5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%t7 = tuple_extract %t6 : $(Builtin.Int32, Builtin.Int1), 0
%8 = builtin "cmp_eq_Int32"(%t7 : $Builtin.Int32, %c1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb2, bb1(%t7 : $Builtin.Int32)
bb2:
%r1 = tuple ()
return %r1 : $()
}
// HOIST-LABEL: sil @hoist_rangechecked_addr_proj_store
// HOIST: bb0
// HOIST: cond_br {{.*}}, bb1{{.*}}, bb2
// HOIST: bb1:
// HOIST: br bb6
// HOIST: bb2:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb3{{.*}}
// HOIST: bb3{{.*}}:
// HOIST-NOT: function_ref @checkbounds
// HOIST-NOT: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4
// HOIST: br bb3
// HOIST: bb5
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @hoist_rangechecked_addr_proj_store : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%3 = integer_literal $Builtin.Int1, -1
%61 = builtin "cmp_sle_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%14 = builtin "xor_Int1"(%61 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %14 : $Builtin.Int1
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%40 = function_ref @getElementAddr : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
retain_value %55 : $Builtin.NativeObject
%42 = apply %40(%37, %53) : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
%43 = struct_extract %42 : $UnsafeMutablePointerInt, #UnsafeMutablePointerInt._rawValue
%44 = pointer_to_address %43 : $Builtin.RawPointer to [strict] $*IntTupleStruct
%45 = struct_element_addr %44 : $*IntTupleStruct, #IntTupleStruct.tuple
%46 = tuple_element_addr %45 : $*(Int32, Int32), 0
store %0 to %46 : $*Int32
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: hoist_inclusive_rangechecked
// HOIST: bb0
// HOIST: cond_br {{.*}}, bb1{{.*}}, bb2
// HOIST: bb1:
// HOIST: br bb6
// HOIST: bb2:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: br bb3{{.*}}
// HOIST: bb3{{.*}}:
// HOIST-NOT: function_ref @checkbounds
// HOIST-NOT: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4:
// HOIST: br bb3
// HOIST: bb5:
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @hoist_inclusive_rangechecked : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%3 = integer_literal $Builtin.Int1, -1
%61 = builtin "cmp_sle_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%14 = builtin "xor_Int1"(%61 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %14 : $Builtin.Int1
%63 = integer_literal $Builtin.Int32, 1
%65 = integer_literal $Builtin.Int1, 0
%66 = builtin "sadd_with_overflow_Int32"(%1 : $Builtin.Int32, %63 : $Builtin.Int32, %65 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%67 = tuple_extract %66 : $(Builtin.Int32, Builtin.Int1), 0
%69 = builtin "cmp_sgt_Int32"(%67 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%70 = builtin "xor_Int1"(%69 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %70 : $Builtin.Int1
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %67 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
/// Don't hoist arrays that are variant.
// HOIST-LABEL: dont_hoist_variant_array
// HOIST: bb0
// HOIST: cond_br {{.*}}, bb1{{.*}}, bb2
// HOIST: bb1:
// HOIST: br bb6
// HOIST: bb2:
// HOIST-NOT: function_ref @checkbounds
// HOIST: br bb3{{.*}}
// HOIST: bb3{{.*}}:
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5{{.*}}, bb4{{.*}}
// HOIST: bb4:
// HOIST: br bb3
// HOIST: bb5:
// HOIST: br bb6
// HOIST: bb6{{.*}}:
// HOIST: return
sil @dont_hoist_variant_array: $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt):
%100 = integer_literal $Builtin.Int1, -1
%101 = struct $Bool(%100 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%3 = integer_literal $Builtin.Int1, -1
%61 = builtin "cmp_sle_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
%14 = builtin "xor_Int1"(%61 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
cond_fail %14 : $Builtin.Int1
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%36 = alloc_stack $ArrayInt
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %36 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
dealloc_stack %36 : $*ArrayInt
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @dont_hoist_due_to_unknown_release
// HOIST: bb3
// HOIST: [[CB:%.*]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: cond_br {{.*}}, bb5, bb4
// HOIST: bb4:
// HOIST: br bb3
sil @dont_hoist_due_to_unknown_release : $@convention(thin) (Int32, @inout ArrayInt, Builtin.NativeObject) -> Int32 {
bb0(%0 : $Int32, %24 : $*ArrayInt, %100: $Builtin.NativeObject):
%105 = integer_literal $Builtin.Int1, -1
%106 = struct $Bool(%105 : $Builtin.Int1)
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32):
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb4
bb4:
%37 = struct $Int32(%4 : $Builtin.Int32)
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%53 = load %24 : $*ArrayInt
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %55 : $Builtin.NativeObject
%58 = apply %52(%37, %106, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%10 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%22 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 1
// This release could have memory unsafe sideeffects in the deinit function.
strong_release %100: $Builtin.NativeObject
cond_fail %22 : $Builtin.Int1
br bb1(%21 : $Builtin.Int32)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// HOIST-LABEL: sil @hoist_but_dont_remove_bc_after_loop
// HOIST: {{^bb2}}
// HOIST: [[CB:%.*]] = function_ref @checkbounds
// HOIST: apply [[CB]]
// HOIST: apply [[CB]]
// HOIST: {{^bb3}}
// HOIST: cond_br {{.*}}, bb5, bb4
// HOIST: {{^bb4}}
// HOIST: br bb3
// HOIST: {{^bb5}}
// HOIST: apply [[CB]]
sil @hoist_but_dont_remove_bc_after_loop : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
bb0(%0 : $Int32, %1 : $*ArrayInt):
%2 = integer_literal $Builtin.Int1, -1
%3 = struct $Bool (%2 : $Builtin.Int1)
%4 = struct_extract %0 : $Int32, #Int32._value
%5 = integer_literal $Builtin.Int32, 0
%6 = builtin "cmp_eq_Int32"(%5 : $Builtin.Int32, %4 : $Builtin.Int32) : $Builtin.Int1
cond_br %6, bb4(%5 : $Builtin.Int32), bb1
bb1:
br bb2(%5 : $Builtin.Int32)
bb2(%10 : $Builtin.Int32):
%11 = struct $Int32 (%10 : $Builtin.Int32)
%12 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%13 = load %1 : $*ArrayInt
%14 = struct_extract %13 : $ArrayInt, #ArrayInt.buffer
%15 = struct_extract %14 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %15 : $Builtin.NativeObject
%17 = apply %12(%11, %3, %13) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%18 = integer_literal $Builtin.Int32, 1
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Int32"(%10 : $Builtin.Int32, %18 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
%22 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %22 : $Builtin.Int1
%24 = builtin "cmp_eq_Int32"(%21 : $Builtin.Int32, %4 : $Builtin.Int32) : $Builtin.Int1
cond_br %24, bb3(%21 : $Builtin.Int32), bb2(%21 : $Builtin.Int32)
bb3(%28 : $Builtin.Int32):
%t1 = function_ref @take_array : $@convention(thin) (@inout ArrayInt) -> ()
%t2 = apply %t1(%1) : $@convention(thin) (@inout ArrayInt) -> ()
%29 = load %1 : $*ArrayInt
%30 = apply %12(%11, %3, %29) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
br bb4(%28 : $Builtin.Int32)
bb4(%31 : $Builtin.Int32):
%32 = struct $Int32 (%31 : $Builtin.Int32)
return %32 : $Int32
}
sil public_external [_semantics "array.check_subscript"] @checkbounds_no_meth : $@convention(thin) (Int32, Bool, @owned ArrayInt) -> _DependenceToken {
bb0(%0: $Int32, %1: $Bool, %2: $ArrayInt):
unreachable
}
sil public_external [_semantics "array.props.isNativeTypeChecked"] @arrayPropertyIsNative : $@convention(method) (@owned ArrayInt) -> Bool {
bb0(%0: $ArrayInt):
unreachable
}
sil public_external [_semantics "array.check_subscript"] @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken {
bb0(%0: $Int32, %1: $Bool, %2: $ArrayInt):
unreachable
}
sil public_external [_semantics "array.mutate_unknown"] @append : $@convention(method) (@in Int32, @inout ArrayInt) -> () {
bb0(%0: $*Int32, %1: $*ArrayInt):
unreachable
}
sil public_external [_semantics "array.get_element_address"] @getElementAddr : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt {
bb0(%0: $Int32, %1: $ArrayInt):
unreachable
}
sil public_external [_semantics "array.init"] @arrayinit : $@convention(thin) () -> @owned ArrayInt {
bb0:
unreachable
}
sil public_external [_semantics "array.get_count"] @getCount : $@convention(method) (@owned ArrayInt) -> Int32 {
bb0(%0: $ArrayInt):
unreachable
}
sil @unknown_func : $@convention(thin) () -> () {
bb0:
unreachable
}
sil @take_array : $@convention(thin) (@inout ArrayInt) -> () {
bb0(%0 : $*ArrayInt):
unreachable
}
sil @getArray : $@convention(thin) () -> ArrayInt
sil [_semantics "array.get_count"] @getCount2 : $@convention(method) (@owned Array<Int>) -> Int32
sil [_semantics "array.check_subscript"] @checkbounds2 : $@convention(method) (Int32, Bool, @owned Array<Int>) -> _DependenceToken
sil [_semantics "array.get_count"] @getCount3 : $@convention(method) (@owned ArraySlice<Int>) -> Int32
sil [_semantics "array.check_subscript"] @checkbounds3 : $@convention(method) (Int32, Bool, @owned ArraySlice<Int>) -> _DependenceToken
// CHECK-LABEL: sil @rangeCheck
// CHECK: bb0
// CHECK: cond_br {{.*}}, bb2, bb1
// CHECK: bb1
// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3([[IV:%.*]] : $Builtin.Int64):
// CHECK: builtin "xor_Int1"([[TRUE]]
// CHECK: builtin "xor_Int1"([[TRUE]]
// CHECK: cond_fail
// CHECK: cond_br {{.*}}, bb2, bb4
// CHECK: bb4:
// CHECK: br bb3
// CHECK: }
sil @rangeCheck : $@convention(thin) (Builtin.Int64) -> () {
bb0(%0 : $Builtin.Int64):
%3 = integer_literal $Builtin.Int64, 0
%5 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%6 = integer_literal $Builtin.Int1, -1
%7 = builtin "xor_Int1"(%5 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
cond_fail %7 : $Builtin.Int1
%9 = builtin "cmp_eq_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %9, bb2, bb1
bb1:
%11 = integer_literal $Builtin.Int64, 1
br bb3(%3 : $Builtin.Int64)
bb2:
%13 = tuple ()
return %13 : $()
bb3(%15 : $Builtin.Int64):
%16 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %15 : $Builtin.Int64) : $Builtin.Int1
%17 = builtin "xor_Int1"(%16 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%18 = builtin "cmp_slt_Int64"(%15 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%19 = builtin "xor_Int1"(%18 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%20 = builtin "or_Int1"(%17 : $Builtin.Int1, %19 : $Builtin.Int1) : $Builtin.Int1
cond_fail %20 : $Builtin.Int1
%22 = builtin "sadd_with_overflow_Int64"(%15 : $Builtin.Int64, %11 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%23 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 0
%24 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 1
cond_fail %24 : $Builtin.Int1
%28 = builtin "cmp_eq_Int64"(%23 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %28, bb2, bb3(%23 : $Builtin.Int64)
}
// CHECK-LABEL: sil @rangeCheck2
// CHECK: bb0
// CHECK: cond_br {{.*}}, bb2, bb1
// CHECK: bb1
// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
// CHECK: [[FALSE:%.*]] = integer_literal $Builtin.Int1, 0
// CHECK: br bb3
// CHECK: bb2
// CHECK: return
// CHECK: bb3([[IV:%.*]] : $Builtin.Int64):
// CHECK: builtin "xor_Int1"([[TRUE]]
// CHECK: builtin "xor_Int1"([[TRUE]]
// CHECK: builtin "or_Int1"([[FALSE]]
// CHECK: cond_fail
// CHECK: cond_br {{.*}}, bb2, bb4
// CHECK: bb4:
// CHECK: br bb3
// CHECK: }
sil @rangeCheck2 : $@convention(thin) (Builtin.Int64) -> () {
bb0(%0 : $Builtin.Int64):
%3 = integer_literal $Builtin.Int64, 0
%5 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%6 = integer_literal $Builtin.Int1, -1
%7 = builtin "xor_Int1"(%5 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
cond_fail %7 : $Builtin.Int1
%9 = builtin "cmp_eq_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %9, bb2, bb1
bb1:
%11 = integer_literal $Builtin.Int64, 1
br bb3(%3 : $Builtin.Int64)
bb2:
%13 = tuple ()
return %13 : $()
bb3(%15 : $Builtin.Int64):
%16 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %15 : $Builtin.Int64) : $Builtin.Int1
%17 = builtin "xor_Int1"(%16 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%18 = builtin "cmp_slt_Int64"(%15 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%19 = builtin "xor_Int1"(%18 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%20 = builtin "or_Int1"(%7 : $Builtin.Int1, %17 : $Builtin.Int1) : $Builtin.Int1
%21 = builtin "or_Int1"(%20 : $Builtin.Int1, %19 : $Builtin.Int1) : $Builtin.Int1
cond_fail %21 : $Builtin.Int1
%22 = builtin "sadd_with_overflow_Int64"(%15 : $Builtin.Int64, %11 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%23 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 0
%24 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 1
cond_fail %24 : $Builtin.Int1
%28 = builtin "cmp_eq_Int64"(%23 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %28, bb2, bb3(%23 : $Builtin.Int64)
}
sil @unknown : $@convention(thin) () -> Builtin.Int1
// RANGECHECK-LABEL: sil @rangeCheck_early_exit
// RANGECHECK: bb0
// RANGECHECK: cond_fail
// RANGECHECK: cond_br {{.*}}, bb2, bb1
// RANGECHECK: bb1:
// RANGECHECK-NOT: cond_fail
// RANGECHECK: br bb3
// RANGECHECK: bb2:
// RANGECHECK: return
// RANGECHECK: bb3({{.*}}):
// RANGECHECK: apply
// RANGECHECK: cond_br {{.*}}, bb4, bb2
// RANGECHECK: bb4:
// RANGECHECK: cond_fail
// RANGECHECK: cond_fail
// RANGECHECK: cond_br {{.*}}, bb2, bb3
// RANGECHECK: }
sil @rangeCheck_early_exit : $@convention(thin) (Builtin.Int64) -> () {
bb0(%0 : $Builtin.Int64):
%3 = integer_literal $Builtin.Int64, 0
%5 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%6 = integer_literal $Builtin.Int1, -1
%7 = builtin "xor_Int1"(%5 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
cond_fail %7 : $Builtin.Int1
%9 = builtin "cmp_eq_Int64"(%3 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %9, bb2, bb1
bb1:
%11 = integer_literal $Builtin.Int64, 1
br bb3(%3 : $Builtin.Int64)
bb2:
%13 = tuple ()
return %13 : $()
bb3(%15 : $Builtin.Int64):
%1 = function_ref @unknown : $@convention(thin) () -> Builtin.Int1
%2 = apply %1() : $@convention(thin) () -> Builtin.Int1
cond_br %2, bb4, bb2
bb4:
%16 = builtin "cmp_sle_Int64"(%3 : $Builtin.Int64, %15 : $Builtin.Int64) : $Builtin.Int1
%17 = builtin "xor_Int1"(%16 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%18 = builtin "cmp_slt_Int64"(%15 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
%19 = builtin "xor_Int1"(%18 : $Builtin.Int1, %6 : $Builtin.Int1) : $Builtin.Int1
%20 = builtin "or_Int1"(%17 : $Builtin.Int1, %19 : $Builtin.Int1) : $Builtin.Int1
cond_fail %20 : $Builtin.Int1
%22 = builtin "sadd_with_overflow_Int64"(%15 : $Builtin.Int64, %11 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%23 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 0
%24 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 1
cond_fail %24 : $Builtin.Int1
%28 = builtin "cmp_eq_Int64"(%23 : $Builtin.Int64, %0 : $Builtin.Int64) : $Builtin.Int1
cond_br %28, bb2, bb3(%23 : $Builtin.Int64)
}
// Don't assert when we have an isNativeTypeChecked parameter that is not a
// constant or an array semantic call. It is valid for it to be a phi node.
sil @bb_arg_is_native2 : $@convention(thin) (Int32, @inout ArrayInt, Builtin.Int1) -> Int32 {
bb0(%0 : $Int32, %1 : $*ArrayInt, %2 : $Builtin.Int1):
cond_br %2, bb1, bb2
bb1:
%4 = integer_literal $Builtin.Int1, -1
%5 = struct $Bool (%4 : $Builtin.Int1)
br bb3(%5 : $Bool)
bb2:
%7 = integer_literal $Builtin.Int1, -1
%8 = struct $Bool (%7 : $Builtin.Int1)
br bb3(%8 : $Bool)
bb3(%10 : $Bool):
%11 = struct_extract %0 : $Int32, #Int32._value
%12 = integer_literal $Builtin.Int32, 0
%13 = builtin "cmp_eq_Int32"(%12 : $Builtin.Int32, %11 : $Builtin.Int32) : $Builtin.Int1
cond_br %13, bb6(%12 : $Builtin.Int32), bb4
bb4:
br bb5(%12 : $Builtin.Int32)
bb5(%16 : $Builtin.Int32):
%17 = struct $Int32 (%16 : $Builtin.Int32)
%18 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%19 = load %1 : $*ArrayInt
%20 = struct_extract %19 : $ArrayInt, #ArrayInt.buffer
%21 = struct_extract %20 : $ArrayIntBuffer, #ArrayIntBuffer.storage
retain_value %21 : $Builtin.NativeObject
%23 = apply %18(%17, %10, %19) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
%24 = integer_literal $Builtin.Int32, 1
%25 = integer_literal $Builtin.Int1, -1
%26 = builtin "sadd_with_overflow_Int32"(%16 : $Builtin.Int32, %24 : $Builtin.Int32, %25 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%27 = tuple_extract %26 : $(Builtin.Int32, Builtin.Int1), 0
%28 = tuple_extract %26 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %28 : $Builtin.Int1
%30 = builtin "cmp_eq_Int32"(%27 : $Builtin.Int32, %11 : $Builtin.Int32) : $Builtin.Int1
cond_br %30, bb6(%27 : $Builtin.Int32), bb5(%27 : $Builtin.Int32)
bb6(%32 : $Builtin.Int32):
%33 = struct $Int32 (%32 : $Builtin.Int32)
return %33 : $Int32
}