mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Also, add a third [serializable] state for functions whose bodies we *can* serialize, but only do so if they're referenced from another serialized function. This will be used for bodies synthesized for imported definitions, such as init(rawValue:), etc, and various thunks, but for now this change is NFC.
448 lines
23 KiB
Plaintext
448 lines
23 KiB
Plaintext
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -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 {
|
|
@sil_stored 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: bb2(%{{.*}} : $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 bb1
|
|
// CHECK-NOT: checked_cast_br
|
|
// CHECK: bb3:
|
|
// CHECK-NOT: function_ref
|
|
// CHECK: class_method
|
|
// CHECK-NOT: function_ref
|
|
// CHECK: br bb1
|
|
// 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] %0 : $FooClass to $FooClass, bb5, bb6 // id: %3
|
|
|
|
bb1(%4 : $Int32): // Preds: bb5 bb6
|
|
checked_cast_br [exact] %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] %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] %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!1 : (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!1 : (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!1 : (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!1 : (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(%{{.*}} : $FooClass):
|
|
// CHECK-NOT: class_method
|
|
// CHECK: br bb1
|
|
// CHECK-NOT: checked_cast_br
|
|
// CHECK: bb3
|
|
// CHECK: class_method
|
|
// CHECK: br bb1
|
|
// 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] %0 : $FooClass to $FooClass, bb3, bb4 // id: %1
|
|
|
|
bb1(%2 : $Int32): // Preds: bb3 bb4
|
|
checked_cast_br [exact] %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.1 : (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.1 : (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] %0 : $FooClass to $FooClass, bb3, bb4 // id: %1
|
|
|
|
bb1(%2 : $Int32): // Preds: bb3 bb4
|
|
%60 = alloc_stack $Int32
|
|
checked_cast_br [exact] %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.1 : (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.1 : (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] %0 : $FooClass to $FooClass, bb3, bb4 // id: %1
|
|
|
|
bb1(%2 : $Int32): // Preds: bb3 bb4
|
|
%101 = class_method [volatile] %100 : $Bar, #Bar.foo!1.foreign : (Bar) -> () -> (), $@convention(objc_method) (Bar) -> ()
|
|
checked_cast_br [exact] %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.1 : (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.1 : (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!1: _TFC18devirt_jump_thread8FooClass3foofS0_FSiSi // devirt_jump_thread.FooClass.foo (devirt_jump_thread.FooClass)(Swift.Int32) -> Swift.Int32
|
|
#FooClass.value!getter.1: _TFC18devirt_jump_thread8FooClassg5valueSi // devirt_jump_thread.FooClass.value.getter : Swift.Int32
|
|
#FooClass.value!setter.1: _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 %0
|
|
// CHECK: checked_cast_br %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 %0 : $AnyObject to $C, bb1, bb2
|
|
|
|
bb1(%4 : $C):
|
|
%5 = enum $Optional<C>, #Optional.some!enumelt.1, %4 : $C
|
|
br bb3(%5 : $Optional<C>)
|
|
|
|
bb2:
|
|
strong_release %0 : $AnyObject
|
|
%8 = enum $Optional<C>, #Optional.none!enumelt
|
|
br bb3(%8 : $Optional<C>)
|
|
|
|
bb3(%10 : $Optional<C>):
|
|
switch_enum %10 : $Optional<C>, case #Optional.some!enumelt.1: bb5, default bb4
|
|
|
|
bb4:
|
|
br bb13
|
|
|
|
bb5(%13 : $C):
|
|
strong_retain %1 : $AnyObject
|
|
checked_cast_br %1 : $AnyObject to $C, bb6, bb7
|
|
|
|
bb6(%16 : $C):
|
|
%17 = enum $Optional<C>, #Optional.some!enumelt.1, %16 : $C
|
|
br bb8(%17 : $Optional<C>)
|
|
|
|
bb7:
|
|
strong_release %1 : $AnyObject
|
|
%20 = enum $Optional<C>, #Optional.none!enumelt
|
|
br bb8(%20 : $Optional<C>)
|
|
|
|
bb8(%22 : $Optional<C>):
|
|
switch_enum %22 : $Optional<C>, case #Optional.some!enumelt.1: bb10, default bb9
|
|
|
|
bb9:
|
|
strong_release %13 : $C
|
|
br bb13
|
|
|
|
bb10(%26 : $C):
|
|
|
|
%27 = function_ref @_TZFsoi3eeeFTGSqPs9AnyObject__GSqPS____Sb : $@convention(thin) (@owned Optional<AnyObject>, @owned Optional<AnyObject>) -> Bool
|
|
strong_retain %13 : $C
|
|
%29 = init_existential_ref %13 : $C : $C, $AnyObject
|
|
%30 = enum $Optional<AnyObject>, #Optional.some!enumelt.1, %29 : $AnyObject
|
|
strong_retain %26 : $C
|
|
%32 = init_existential_ref %26 : $C : $C, $AnyObject
|
|
%33 = enum $Optional<AnyObject>, #Optional.some!enumelt.1, %32 : $AnyObject
|
|
%34 = apply %27(%30, %33) : $@convention(thin) (@owned Optional<AnyObject>, @owned Optional<AnyObject>) -> 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 [transparent] [serialized] @_TFSb21_getBuiltinLogicValuefSbFT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1
|
|
|
|
|
|
sil [serialized] @_TZFsoi3eeeFTGSqPs9AnyObject__GSqPS____Sb : $@convention(thin) (@owned Optional<AnyObject>, @owned Optional<AnyObject>) -> Bool
|
|
|
|
sil_witness_table C: AnyObject module main
|
|
|
|
|