// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -jumpthread-simplify-cfg -cse | %FileCheck %s // Check that jump-threading works for sequences of checked_cast_br instructions produced by the devirtualizer. // This allows for simplifications of code like e.g. f.foo() + f.foo() sil_stage canonical import Builtin import Swift import SwiftShims /// Don't jumpthread blocks that contain objc method instructions. We don't /// support building phis with objc method values. class Bar { init() @objc func foo() } public class FooClass { @_hasStorage var value: Int32 { get set } @inline(never) func foo(x: Int32) -> Int32 init(value: Int32) deinit } // devirt_jump_thread.FooClass.value.getter : Swift.Int32 sil [transparent] [serialized] @_TFC18devirt_jump_thread8FooClassg5valueSi : $@convention(method) (@guaranteed FooClass) -> Int32 { bb0(%0 : $FooClass): %1 = ref_element_addr %0 : $FooClass, #FooClass.value // user: %2 %2 = load %1 : $*Int32 // user: %4 return %2 : $Int32 // id: %4 } // devirt_jump_thread.FooClass.value.setter : Swift.Int32 sil [transparent] [serialized] @_TFC18devirt_jump_thread8FooClasss5valueSi : $@convention(method) (Int32, @guaranteed FooClass) -> () { bb0(%0 : $Int32, %1 : $FooClass): %2 = ref_element_addr %1 : $FooClass, #FooClass.value // user: %3 store %0 to %2 : $*Int32 // id: %3 %5 = tuple () // user: %6 return %5 : $() // id: %6 } // devirt_jump_thread.FooClass.foo (devirt_jump_thread.FooClass)(Swift.Int32) -> Swift.Int32 sil [noinline] @_TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 { bb0(%0 : $Int32, %1 : $FooClass): // function_ref @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" %2 = function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %3 %3 = apply %2(%0, %1) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %6 return %3 : $Int32 // id: %6 } // Check that checked_cast_br instructions resulting from devirtualization // get jump-threaded. // // CHECK-LABEL: sil @_TF18devirt_jump_thread26jumpthread_checked_cast_brFCS_8FooClassSi // CHECK: checked_cast_br // CHECK: bb1(%{{.*}} : $FooClass): // CHECK: function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi // CHECK-NOT: function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi // CHECK-NOT: class_method // CHECK: br bb2 // CHECK-NOT: checked_cast_br // CHECK: bb3: // CHECK-NOT: function_ref // CHECK: class_method // CHECK-NOT: function_ref // CHECK: br bb2 // CHECK: } // devirt_jump_thread.jumpthread_checked_cast_br (devirt_jump_thread.FooClass) -> Swift.Int32 sil @_TF18devirt_jump_thread26jumpthread_checked_cast_brFCS_8FooClassSi : $@convention(thin) (@guaranteed FooClass) -> Int32 { bb0(%0 : $FooClass): %1 = integer_literal $Builtin.Int32, 2 // user: %2 %2 = struct $Int32 (%1 : $Builtin.Int32) // users: %37, %43, %48, %54 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb5, bb6 // id: %3 bb1(%4 : $Int32): // Preds: bb5 bb6 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb7, bb8 // id: %5 bb2(%6 : $Int32): // Preds: bb7 bb8 %7 = struct_extract %4 : $Int32, #Int32._value // user: %10 %8 = struct_extract %6 : $Int32, #Int32._value // user: %10 %9 = integer_literal $Builtin.Int1, -1 // users: %10, %19, %28 %10 = builtin "sadd_with_overflow_Int32"(%7 : $Builtin.Int32, %8 : $Builtin.Int32, %9 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %11, %12 %11 = tuple_extract %10 : $(Builtin.Int32, Builtin.Int1), 0 // user: %19 %12 = tuple_extract %10 : $(Builtin.Int32, Builtin.Int1), 1 // user: %13 cond_fail %12 : $Builtin.Int1 // id: %13 %14 = integer_literal $Builtin.Int32, 3 // user: %15 %15 = struct $Int32 (%14 : $Builtin.Int32) // users: %59, %65 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb9, bb10 // id: %16 bb3(%17 : $Int32): // Preds: bb9 bb10 %18 = struct_extract %17 : $Int32, #Int32._value // user: %19 %19 = builtin "sadd_with_overflow_Int32"(%11 : $Builtin.Int32, %18 : $Builtin.Int32, %9 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %20, %21 %20 = tuple_extract %19 : $(Builtin.Int32, Builtin.Int1), 0 // user: %28 %21 = tuple_extract %19 : $(Builtin.Int32, Builtin.Int1), 1 // user: %22 cond_fail %21 : $Builtin.Int1 // id: %22 %23 = integer_literal $Builtin.Int32, 4 // user: %24 %24 = struct $Int32 (%23 : $Builtin.Int32) // users: %69, %74 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb11, bb12 // id: %25 bb4(%26 : $Int32): // Preds: bb11 bb12 %27 = struct_extract %26 : $Int32, #Int32._value // user: %28 %28 = builtin "sadd_with_overflow_Int32"(%20 : $Builtin.Int32, %27 : $Builtin.Int32, %9 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %29, %30 %29 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 0 // user: %32 %30 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 1 // user: %31 cond_fail %30 : $Builtin.Int1 // id: %31 %32 = struct $Int32 (%29 : $Builtin.Int32) // user: %33 return %32 : $Int32 // id: %33 bb5(%34 : $FooClass): // Preds: bb0 // function_ref @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" %35 = function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %37 strong_retain %0 : $FooClass // id: %36 %37 = apply %35(%2, %34) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %40 fix_lifetime %34 : $FooClass // id: %38 strong_release %0 : $FooClass // id: %39 br bb1(%37 : $Int32) // id: %40 bb6: // Preds: bb0 %41 = class_method %0 : $FooClass, #FooClass.foo : (FooClass) -> (Int32) -> Int32, $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %43 strong_retain %0 : $FooClass // id: %42 %43 = apply %41(%2, %0) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %44 br bb1(%43 : $Int32) // id: %44 bb7(%45 : $FooClass): // Preds: bb1 // function_ref @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" %46 = function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %48 strong_retain %0 : $FooClass // id: %47 %48 = apply %46(%2, %45) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %51 fix_lifetime %45 : $FooClass // id: %49 strong_release %0 : $FooClass // id: %50 br bb2(%48 : $Int32) // id: %51 bb8: // Preds: bb1 %52 = class_method %0 : $FooClass, #FooClass.foo : (FooClass) -> (Int32) -> Int32, $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %54 strong_retain %0 : $FooClass // id: %53 %54 = apply %52(%2, %0) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %55 br bb2(%54 : $Int32) // id: %55 bb9(%56 : $FooClass): // Preds: bb2 // function_ref @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" %57 = function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %59 strong_retain %0 : $FooClass // id: %58 %59 = apply %57(%15, %56) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %62 fix_lifetime %56 : $FooClass // id: %60 strong_release %0 : $FooClass // id: %61 br bb3(%59 : $Int32) // id: %62 bb10: // Preds: bb2 %63 = class_method %0 : $FooClass, #FooClass.foo : (FooClass) -> (Int32) -> Int32, $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %65 strong_retain %0 : $FooClass // id: %64 %65 = apply %63(%15, %0) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %66 br bb3(%65 : $Int32) // id: %66 bb11(%67 : $FooClass): // Preds: bb3 // function_ref @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" %68 = function_ref @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %69 %69 = apply %68(%24, %67) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %72 fix_lifetime %67 : $FooClass // id: %70 strong_release %67 : $FooClass // id: %71 br bb4(%69 : $Int32) // id: %72 bb12: // Preds: bb3 %73 = class_method %0 : $FooClass, #FooClass.foo : (FooClass) -> (Int32) -> Int32, $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %74 %74 = apply %73(%24, %0) : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 // user: %75 br bb4(%74 : $Int32) // id: %75 } // Check that checked_cast_br gets jump threaded // CHECK-LABEL: sil @_TF18devirt_jump_thread6doubleFCS_8FooClassSi // CHECK: checked_cast_br // CHECK: bb2 // CHECK: class_method // CHECK: br bb4 // CHECK: bb3(%{{.*}} : $FooClass): // CHECK-NOT: class_method // CHECK: br bb1 // CHECK-NOT: checked_cast_br // CHECK: } // devirt_jump_thread.double (devirt_jump_thread.FooClass) -> Swift.Int32 sil @_TF18devirt_jump_thread6doubleFCS_8FooClassSi : $@convention(thin) (@guaranteed FooClass) -> Int32 { bb0(%0 : $FooClass): checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb3, bb4 // id: %1 bb1(%2 : $Int32): // Preds: bb3 bb4 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb5, bb6 // id: %3 bb2(%4 : $Int32): // Preds: bb5 bb6 %5 = struct_extract %2 : $Int32, #Int32._value // user: %8 %6 = struct_extract %4 : $Int32, #Int32._value // user: %8 %7 = integer_literal $Builtin.Int1, -1 // user: %8 %8 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %6 : $Builtin.Int32, %7 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %9, %10 %9 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 0 // user: %12 %10 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 1 // user: %11 cond_fail %10 : $Builtin.Int1 // id: %11 %12 = struct $Int32 (%9 : $Builtin.Int32) // user: %13 return %12 : $Int32 // id: %13 bb3(%14 : $FooClass): // Preds: bb0 %15 = ref_element_addr %14 : $FooClass, #FooClass.value // user: %16 %16 = load %15 : $*Int32 // user: %17 br bb1(%16 : $Int32) // id: %17 bb4: // Preds: bb0 %18 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %20 strong_retain %0 : $FooClass // id: %19 %20 = apply %18(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %21 br bb1(%20 : $Int32) // id: %21 bb5(%22 : $FooClass): // Preds: bb1 %23 = ref_element_addr %22 : $FooClass, #FooClass.value // user: %24 %24 = load %23 : $*Int32 // user: %26 strong_release %22 : $FooClass // id: %25 br bb2(%24 : $Int32) // id: %26 bb6: // Preds: bb1 %27 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %28 %28 = apply %27(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %29 br bb2(%28 : $Int32) // id: %29 } // Check that checked_cast_br in bb1 does not get jump threaded // because bb1 contains some instructions that cannot be cloned, namely alloc_stack. // // CHECK-LABEL: sil @_TF18devirt_jump_thread6dont_jump_thread_alloc_stackFCS_8FooClassSi // CHECK: bb0(%{{.*}} : $FooClass): // CHECK: checked_cast_br // CHECK: bb1(%{{.*}} : $Int32): // CHECK: checked_cast_br // CHECK: bb2(%{{.*}} : $Int32): // CHECK: } sil @_TF18devirt_jump_thread6dont_jump_thread_alloc_stackFCS_8FooClassSi : $@convention(thin) (@guaranteed FooClass) -> Int32 { bb0(%0 : $FooClass): checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb3, bb4 // id: %1 bb1(%2 : $Int32): // Preds: bb3 bb4 %60 = alloc_stack $Int32 checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb5, bb6 // id: %3 bb2(%4 : $Int32): // Preds: bb5 bb6 %5 = struct_extract %2 : $Int32, #Int32._value // user: %8 %6 = struct_extract %4 : $Int32, #Int32._value // user: %8 %7 = integer_literal $Builtin.Int1, -1 // user: %8 %8 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %6 : $Builtin.Int32, %7 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %9, %10 %9 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 0 // user: %12 %10 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 1 // user: %11 cond_fail %10 : $Builtin.Int1 // id: %11 dealloc_stack %60 : $*Int32 %12 = struct $Int32 (%9 : $Builtin.Int32) // user: %13 return %12 : $Int32 // id: %13 bb3(%14 : $FooClass): // Preds: bb0 %15 = ref_element_addr %14 : $FooClass, #FooClass.value // user: %16 %16 = load %15 : $*Int32 // user: %17 br bb1(%16 : $Int32) // id: %17 bb4: // Preds: bb0 %18 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %20 %20 = apply %18(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %21 br bb1(%20 : $Int32) // id: %21 bb5(%22 : $FooClass): // Preds: bb1 %23 = ref_element_addr %22 : $FooClass, #FooClass.value // user: %24 %24 = load %23 : $*Int32 // user: %26 br bb2(%24 : $Int32) // id: %26 bb6: // Preds: bb1 %27 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %28 %28 = apply %27(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %29 br bb2(%28 : $Int32) // id: %29 } // Check that checked_cast_br in bb1 does not get jump threaded // because bb1 contains some instructions that cannot be cloned, e.g. class_method // referring to an objc method. // // CHECK-LABEL: sil @_TF18devirt_jump_thread6dont_jump_thread_objc_methodFCS_8FooClassSi // CHECK: bb0(%{{.*}} : $FooClass): // CHECK: checked_cast_br // CHECK: bb1(%{{.*}} : $Int32): // CHECK: checked_cast_br // CHECK: bb2(%{{.*}} : $Int32): // CHECK: } sil @_TF18devirt_jump_thread6dont_jump_thread_objc_methodFCS_8FooClassSi : $@convention(thin) (@guaranteed FooClass) -> Int32 { bb0(%0 : $FooClass): %100 = alloc_ref $Bar checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb3, bb4 // id: %1 bb1(%2 : $Int32): // Preds: bb3 bb4 %101 = objc_method %100 : $Bar, #Bar.foo!foreign : (Bar) -> () -> (), $@convention(objc_method) (Bar) -> () checked_cast_br [exact] FooClass in %0 : $FooClass to FooClass, bb5, bb6 // id: %3 bb2(%4 : $Int32): // Preds: bb5 bb6 %5 = struct_extract %2 : $Int32, #Int32._value // user: %8 %6 = struct_extract %4 : $Int32, #Int32._value // user: %8 %7 = integer_literal $Builtin.Int1, -1 // user: %8 %8 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %6 : $Builtin.Int32, %7 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %9, %10 %9 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 0 // user: %12 %10 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 1 // user: %11 cond_fail %10 : $Builtin.Int1 // id: %11 %12 = struct $Int32 (%9 : $Builtin.Int32) // user: %13 return %12 : $Int32 // id: %13 bb3(%14 : $FooClass): // Preds: bb0 %15 = ref_element_addr %14 : $FooClass, #FooClass.value // user: %16 %16 = load %15 : $*Int32 // user: %17 br bb1(%16 : $Int32) // id: %17 bb4: // Preds: bb0 %18 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %20 strong_retain %0 : $FooClass // id: %19 %20 = apply %18(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %21 br bb1(%20 : $Int32) // id: %21 bb5(%22 : $FooClass): // Preds: bb1 %23 = ref_element_addr %22 : $FooClass, #FooClass.value // user: %24 %24 = load %23 : $*Int32 // user: %26 strong_release %22 : $FooClass // id: %25 br bb2(%24 : $Int32) // id: %26 bb6: // Preds: bb1 %27 = class_method %0 : $FooClass, #FooClass.value!getter : (FooClass) -> () -> Int32, $@convention(method) (@guaranteed FooClass) -> Int32 // user: %28 %28 = apply %27(%0) : $@convention(method) (@guaranteed FooClass) -> Int32 // user: %29 br bb2(%28 : $Int32) // id: %29 } // @!objc with unmangled suffix "no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi" sil [noinline] @_TTOS_no2g__TFC18devirt_jump_thread8FooClass3foofS0_FSiSi : $@convention(method) (Int32, @guaranteed FooClass) -> Int32 { bb0(%0 : $Int32, %1 : $FooClass): %2 = integer_literal $Builtin.Int32, 11 // user: %5 %3 = struct_extract %0 : $Int32, #Int32._value // user: %5 %4 = integer_literal $Builtin.Int1, -1 // user: %5 %5 = builtin "sadd_with_overflow_Int32"(%3 : $Builtin.Int32, %2 : $Builtin.Int32, %4 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %6, %7 %6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0 // user: %9 %7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1 // user: %8 cond_fail %7 : $Builtin.Int1 // id: %8 %9 = struct $Int32 (%6 : $Builtin.Int32) // user: %10 return %9 : $Int32 // id: %10 } sil_vtable FooClass { #FooClass.foo: @_TFC18devirt_jump_thread8FooClass3foofS0_FSiSi // devirt_jump_thread.FooClass.foo (devirt_jump_thread.FooClass)(Swift.Int32) -> Swift.Int32 #FooClass.value!getter: @_TFC18devirt_jump_thread8FooClassg5valueSi // devirt_jump_thread.FooClass.value.getter : Swift.Int32 #FooClass.value!setter: @_TFC18devirt_jump_thread8FooClasss5valueSi // devirt_jump_thread.FooClass.value.setter : Swift.Int32 } class C { deinit init() } // Check that checked_cast_br jump-threading works properly when both // conditions are arguments of the function's entry block. // CHECK: sil @test_checked_cast_br_jump_threading_with_entry_bb_arguments // CHECK: checked_cast_br AnyObject in %0 // CHECK: checked_cast_br AnyObject in %1 // CHECK: return sil @test_checked_cast_br_jump_threading_with_entry_bb_arguments : $@convention(thin) (@owned AnyObject, @owned AnyObject) -> Int32 { bb0(%0 : $AnyObject, %1 : $AnyObject): strong_retain %0 : $AnyObject checked_cast_br AnyObject in %0 : $AnyObject to C, bb1, bb2 bb1(%4 : $C): %5 = enum $Optional, #Optional.some!enumelt, %4 : $C br bb3(%5 : $Optional) bb2: strong_release %0 : $AnyObject %8 = enum $Optional, #Optional.none!enumelt br bb3(%8 : $Optional) bb3(%10 : $Optional): switch_enum %10 : $Optional, case #Optional.some!enumelt: bb5, default bb4 bb4: br bb13 bb5(%13 : $C): strong_retain %1 : $AnyObject checked_cast_br AnyObject in %1 : $AnyObject to C, bb6, bb7 bb6(%16 : $C): %17 = enum $Optional, #Optional.some!enumelt, %16 : $C br bb8(%17 : $Optional) bb7: strong_release %1 : $AnyObject %20 = enum $Optional, #Optional.none!enumelt br bb8(%20 : $Optional) bb8(%22 : $Optional): switch_enum %22 : $Optional, case #Optional.some!enumelt: bb10, default bb9 bb9: strong_release %13 : $C br bb13 bb10(%26 : $C): %27 = function_ref @_TZFsoi3eeeFTGSqPs9AnyObject__GSqPS____Sb : $@convention(thin) (@owned Optional, @owned Optional) -> Bool strong_retain %13 : $C %29 = init_existential_ref %13 : $C : $C, $AnyObject %30 = enum $Optional, #Optional.some!enumelt, %29 : $AnyObject strong_retain %26 : $C %32 = init_existential_ref %26 : $C : $C, $AnyObject %33 = enum $Optional, #Optional.some!enumelt, %32 : $AnyObject %34 = apply %27(%30, %33) : $@convention(thin) (@owned Optional, @owned Optional) -> Bool %35 = struct_extract %34 : $Bool, #Bool._value cond_br %35, bb11, bb12 bb11: %37 = integer_literal $Builtin.Int32, 1 %38 = struct $Int32 (%37 : $Builtin.Int32) strong_release %26 : $C strong_release %13 : $C br bb14(%38 : $Int32) bb12: strong_release %26 : $C strong_release %13 : $C br bb13 bb13: %45 = integer_literal $Builtin.Int32, 0 %46 = struct $Int32 (%45 : $Builtin.Int32) br bb14(%46 : $Int32) bb14(%48 : $Int32): strong_release %1 : $AnyObject strong_release %0 : $AnyObject return %48 : $Int32 } sil [serialized] @_TZFsoi3eeeFTGSqPs9AnyObject__GSqPS____Sb : $@convention(thin) (@owned Optional, @owned Optional) -> Bool