mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
726 lines
25 KiB
Plaintext
726 lines
25 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
|
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -late-codemotion -jumpthread-simplify-cfg | %FileCheck %s --check-prefix=CHECK_WITH_CODEMOTION
|
|
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
sil_global private @globalinit_token11 : $Builtin.Word
|
|
|
|
sil_global private @globalinit_token120 : $Builtin.Word
|
|
|
|
sil @globalinit_func11 : $@convention(thin) () -> ()
|
|
|
|
// CHECK: sil @a_method_to_simplify
|
|
sil @a_method_to_simplify : $@convention(thin) (Builtin.RawPointer, @owned Builtin.NativeObject, Builtin.Int32) -> Builtin.RawPointer {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.NativeObject, %2 : $Builtin.Int32):
|
|
%4 = struct $UnsafeMutablePointer<UInt8> (%0 : $Builtin.RawPointer) // user: %37
|
|
strong_retain %1 : $Builtin.NativeObject // id: %5
|
|
strong_retain %1 : $Builtin.NativeObject // id: %6
|
|
strong_release %1 : $Builtin.NativeObject // id: %7
|
|
%8 = integer_literal $Builtin.Int1, 0 // user: %23
|
|
%10 = global_addr @globalinit_token11 : $*Builtin.Word // user: %11
|
|
%11 = address_to_pointer %10 : $*Builtin.Word to $Builtin.RawPointer // user: %14
|
|
%12 = function_ref @globalinit_func11 : $@convention(thin) () -> () // users: %26, %13
|
|
%14 = builtin "once"(%11 : $Builtin.RawPointer, %12 : $@convention(thin) () -> ()) : $()
|
|
%15 = alloc_stack $Int32 // users: %38, %40, %41
|
|
%16 = struct_element_addr %15 : $*Int32, #Int32._value // users: %28, %17
|
|
%17 = load %16 : $*Builtin.Int32 // user: %20
|
|
%18 = integer_literal $Builtin.Int32, -1 // user: %20
|
|
%20 = builtin "xor_Int32"(%17 : $Builtin.Int32, %18 : $Builtin.Int32) : $Builtin.Int32 // user: %22
|
|
%22 = builtin "and_Int32"(%2 : $Builtin.Int32, %20 : $Builtin.Int32) : $Builtin.Int32 // users: %30, %23
|
|
// CHECK-NOT: cond_br
|
|
cond_br %8, bb1, bb2(%22 : $Builtin.Int32) // id: %23
|
|
|
|
bb1: // Preds: bb0
|
|
%24 = global_addr @globalinit_token11 : $*Builtin.Word // user: %25
|
|
%25 = address_to_pointer %24 : $*Builtin.Word to $Builtin.RawPointer // user: %27
|
|
%27 = builtin "once"(%25 : $Builtin.RawPointer, %12 : $@convention(thin) () -> ()) : $()
|
|
%28 = load %16 : $*Builtin.Int32 // user: %30
|
|
// CHECK: [[VAR_21:%[0-9]+]] = builtin "and_Int32"
|
|
%30 = builtin "or_Int32"(%22 : $Builtin.Int32, %28 : $Builtin.Int32) : $Builtin.Int32 // user: %31
|
|
br bb2(%30 : $Builtin.Int32) // id: %31
|
|
|
|
bb2(%32 : $Builtin.Int32): // Preds: bb0 bb1
|
|
// CHECK-NOT: tuple
|
|
%33 = tuple () // user: %34
|
|
br bb3(%33 : $()) // id: %34
|
|
|
|
bb3(%35 : $()): // Preds: bb2
|
|
// CHECK-NEXT: struct $Int32 ([[VAR_21]] : $Builtin.Int32)
|
|
%36 = struct $Int32 (%32 : $Builtin.Int32) // user: %37
|
|
strong_retain %1 : $Builtin.NativeObject // id: %38
|
|
strong_release %1 : $Builtin.NativeObject // id: %39
|
|
strong_release %1 : $Builtin.NativeObject // id: %40
|
|
dealloc_stack %15 : $*Int32 // id: %41
|
|
// CHECK: return
|
|
return %0 : $Builtin.RawPointer
|
|
}
|
|
|
|
|
|
//CHECK-LABEL: remove_dead_args
|
|
//CHECK-NOT: br bb2([[VAR_21:%[0-9]+]] : $Bool)
|
|
//CHECK: bb2:
|
|
//CHECK-NEXT: tuple ()
|
|
//CHECK-NEXT: return
|
|
sil @remove_dead_args: $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = integer_literal $Builtin.Int32, 37
|
|
%3 = struct_extract %0 : $Int32, #Int32._value
|
|
%4 = builtin "cmp_ne_Int32"(%3 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
|
|
%5 = struct $Bool (%4 : $Builtin.Int1)
|
|
cond_br %4, bb1, bb3
|
|
|
|
bb1:
|
|
%7 = integer_literal $Builtin.Int32, 42
|
|
%8 = builtin "cmp_ne_Int32"(%3 : $Builtin.Int32, %7 : $Builtin.Int32) : $Builtin.Int1
|
|
%9 = struct $Bool (%8 : $Builtin.Int1)
|
|
br bb2(%9 : $Bool)
|
|
|
|
bb3: // Preds: bb0
|
|
%13 = tuple()
|
|
br bb2(%5 : $Bool) // id: %14
|
|
|
|
// Remove this ARG.
|
|
bb2(%11 : $Bool): // Preds: bb1 bb3
|
|
%12 = tuple () // user: %13
|
|
return %12 : $() // id: %13
|
|
|
|
}
|
|
|
|
class A {}
|
|
|
|
//CHECK-LABEL: no_remove_mandatory_dead_args
|
|
//CHECK: checked_cast_br {{%.*}} : $AnyObject to A, bb1
|
|
//CHECK-NOT: bb1
|
|
//CHECK: bb1([[VAR:%[0-9]+]] : $A)
|
|
//CHECK-NOT: [[VAR]]
|
|
//CHECK: return
|
|
sil @no_remove_mandatory_dead_args : $@convention(thin) (@owned AnyObject) -> Int32 {
|
|
bb0(%0 : $AnyObject):
|
|
checked_cast_br %0 : $AnyObject to A, bb1, bb2 // id: %3
|
|
|
|
bb1(%1 : $A):
|
|
%2 = integer_literal $Builtin.Int32, 1
|
|
br bb3(%2 : $Builtin.Int32)
|
|
|
|
bb2:
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
br bb3(%3 : $Builtin.Int32)
|
|
|
|
bb3(%4 : $Builtin.Int32):
|
|
%5 = struct $Int32 (%4 : $Builtin.Int32)
|
|
strong_release %0 : $AnyObject
|
|
return %5 : $Int32
|
|
}
|
|
|
|
enum X {
|
|
case A
|
|
case B((Int32, Int32))
|
|
case C(Int32)
|
|
}
|
|
|
|
// CHECK-LABEL: simplify_switch_include_args
|
|
sil @simplify_switch_include_args : $@convention(thin) (Int32, Int32) -> Int32 {
|
|
bb0(%0 : $Int32, %1 : $Int32):
|
|
// CHECK: return %0 : $Int32
|
|
%2 = tuple (%0 : $Int32, %1 : $Int32) // user: %3
|
|
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32) // user: %4
|
|
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %5
|
|
|
|
bb2: // Preds: bb1
|
|
%6 = integer_literal $Builtin.Int32, 0 // user: %7
|
|
%7 = struct $Int32 (%6 : $Builtin.Int32) // user: %8
|
|
br bb7(%7 : $Int32) // id: %8
|
|
|
|
bb3(%9 : $(Int32, Int32)): // Preds: bb0
|
|
%10 = tuple_extract %9 : $(Int32, Int32), 0 // user: %12
|
|
br bb4 // id: %11
|
|
|
|
bb4: // Preds: bb3
|
|
br bb7(%10 : $Int32) // id: %12
|
|
|
|
bb5(%13 : $Int32): // Preds: bb0
|
|
br bb6 // id: %14
|
|
|
|
bb6: // Preds: bb5
|
|
br bb7(%13 : $Int32) // id: %15
|
|
|
|
bb7(%16 : $Int32): // Preds: bb2 bb4 bb6
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// CHECK-LABEL: simplify_switch_dont_include_args
|
|
sil @simplify_switch_dont_include_args : $@convention(thin) (Int32, Int32) -> Int32 {
|
|
bb0(%0 : $Int32, %1 : $Int32):
|
|
%2 = tuple (%0 : $Int32, %1 : $Int32) // user: %3
|
|
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32) // user: %4
|
|
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %5
|
|
|
|
bb2: // Preds: bb1
|
|
%6 = integer_literal $Builtin.Int32, 0 // user: %7
|
|
%7 = struct $Int32 (%6 : $Builtin.Int32) // user: %8
|
|
br bb6
|
|
|
|
bb3(%9 : $(Int32, Int32)): // Preds: bb0
|
|
%10 = tuple_extract %9 : $(Int32, Int32), 0 // user: %12
|
|
br bb4 // id: %11
|
|
|
|
bb4: // Preds: bb3
|
|
br bb6 // id: %12
|
|
|
|
bb5:
|
|
br bb6
|
|
|
|
bb6:
|
|
return %0 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: simplify_switch_dont_include_args_nested
|
|
sil @simplify_switch_dont_include_args_nested : $@convention(thin) (Int32, Int32, X) -> Int32 {
|
|
// CHECK: bb0
|
|
// CHECK: switch_enum %2
|
|
bb0(%0 : $Int32, %1 : $Int32, %2 : $X):
|
|
switch_enum %2 : $X, case #X.A!enumelt: bb3, case #X.B!enumelt: bb1, case #X.C!enumelt: bb5
|
|
|
|
// CHECK: bb1
|
|
// CHECK-NOT: switch_enum
|
|
bb1(%12: $(Int32, Int32)):
|
|
switch_enum %2 : $X, case #X.A!enumelt: bb6, case #X.B!enumelt: bb7, case #X.C!enumelt: bb8
|
|
|
|
bb2:
|
|
%6 = integer_literal $Builtin.Int32, 0
|
|
%7 = struct $Int32 (%6 : $Builtin.Int32)
|
|
br bb9(%7 : $Int32)
|
|
|
|
bb3:
|
|
%9 = integer_literal $Builtin.Int32, 1
|
|
%10 = struct $Int32 (%9 : $Builtin.Int32)
|
|
br bb4(%10 : $Int32)
|
|
|
|
bb4(%16 : $Int32):
|
|
br bb9(%16 : $Int32)
|
|
|
|
bb5(%18 : $Int32):
|
|
br bb9(%18 : $Int32)
|
|
|
|
bb6:
|
|
%20 = integer_literal $Builtin.Int32, 2
|
|
%21 = struct $Int32 (%20 : $Builtin.Int32)
|
|
br bb9(%21 : $Int32)
|
|
|
|
bb7:
|
|
%22 = integer_literal $Builtin.Int32, 3
|
|
%23 = struct $Int32 (%22 : $Builtin.Int32)
|
|
br bb9(%23 : $Int32)
|
|
|
|
bb8(%25 : $Int32):
|
|
br bb9(%25 : $Int32)
|
|
|
|
bb9(%27 : $Int32):
|
|
return %27 : $Int32
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: simplify_switch_wrong_args
|
|
sil @simplify_switch_wrong_args : $@convention(thin) (Int32, Int32, X, Builtin.Int1) -> Int32 {
|
|
// CHECK: bb0
|
|
// CHECK: switch_enum %2
|
|
bb0(%0 : $Int32, %1 : $Int32, %2 : $X, %24 : $Builtin.Int1):
|
|
switch_enum %2 : $X, case #X.A!enumelt: bb3, case #X.B!enumelt: bb9, case #X.C!enumelt: bb10
|
|
|
|
bb9(%21 : $(Int32, Int32)):
|
|
%22 = tuple_extract %21 : $(Int32, Int32), 1
|
|
cond_br %24, bb1(%22 : $Int32), bb5(%22 : $Int32)
|
|
|
|
// CHECK: bb1
|
|
// CHECK-NOT: switch_enum
|
|
bb1(%12: $Int32):
|
|
switch_enum %2 : $X, case #X.A!enumelt: bb6, case #X.B!enumelt: bb7, case #X.C!enumelt: bb8
|
|
|
|
bb2:
|
|
%6 = integer_literal $Builtin.Int32, 0
|
|
%7 = struct $Int32 (%6 : $Builtin.Int32)
|
|
br bb5(%7 : $Int32)
|
|
|
|
bb3:
|
|
%9 = integer_literal $Builtin.Int32, 1
|
|
%10 = struct $Int32 (%9 : $Builtin.Int32)
|
|
br bb4(%10 : $Int32)
|
|
|
|
bb4(%16 : $Int32):
|
|
br bb5(%16 : $Int32)
|
|
|
|
bb10(%18 : $Int32):
|
|
br bb5(%18 : $Int32)
|
|
|
|
bb5(%19 : $Int32):
|
|
return %19 : $Int32
|
|
|
|
bb6:
|
|
%14 = integer_literal $Builtin.Int32, 2
|
|
%15 = struct $Int32 (%14 : $Builtin.Int32)
|
|
br bb5(%15 : $Int32)
|
|
|
|
bb7(%23 : $(Int32, Int32)):
|
|
%17 = tuple_extract %21 : $(Int32, Int32), 0
|
|
br bb5(%17 : $Int32)
|
|
|
|
bb8(%20 : $Int32):
|
|
br bb5(%20 : $Int32)
|
|
}
|
|
|
|
enum EA {
|
|
case cA
|
|
case cB(Int32)
|
|
case cC(Float)
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: fold_unreachable_terminators1
|
|
sil @fold_unreachable_terminators1 : $@convention(thin) (EA) -> () {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: [[VAL:%[a-zA-Z0-9]+]] = tuple ()
|
|
// CHECK-NEXT: return [[VAL]]
|
|
bb0(%0 : $EA):
|
|
switch_enum %0 : $EA, case #EA.cA!enumelt: bb1, case #EA.cB!enumelt: bb3, case #EA.cC!enumelt: bb5
|
|
|
|
bb1:
|
|
br bb2
|
|
|
|
bb2:
|
|
br bb7
|
|
|
|
bb3(%6 : $Int32):
|
|
br bb4
|
|
|
|
bb4:
|
|
unreachable
|
|
|
|
bb5(%10 : $Float):
|
|
br bb6
|
|
|
|
bb6:
|
|
unreachable
|
|
|
|
bb7:
|
|
%14 = tuple ()
|
|
return %14 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: fold_unreachable_terminators2
|
|
sil @fold_unreachable_terminators2 : $@convention(thin) (EA) -> Int32 {
|
|
// CHECK: bb0
|
|
bb0(%0 : $EA):
|
|
// CHECK-NEXT: [[VAL:%[a-zA-Z0-9]+]] = unchecked_enum_data %0 : $EA, #EA.cB!enumelt{{.*}} // user: %2
|
|
// CHECK-NEXT: return [[VAL]] : $Int32
|
|
switch_enum %0 : $EA, case #EA.cA!enumelt: bb1, case #EA.cB!enumelt: bb3, case #EA.cC!enumelt: bb5
|
|
|
|
bb1:
|
|
br bb2
|
|
|
|
bb2:
|
|
unreachable
|
|
|
|
bb3(%6 : $Int32):
|
|
br bb4
|
|
|
|
bb4:
|
|
return %6 : $Int32
|
|
|
|
bb5(%10 : $Float):
|
|
br bb6
|
|
|
|
bb6:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: simplify_switch_to_select_enum
|
|
sil @simplify_switch_to_select_enum : $@convention(thin) (X) -> Bool {
|
|
bb0(%0 : $X):
|
|
// CHECK: bb0
|
|
// CHECK: [[TRUE:%.*]] = integer_literal {{.*}} -1
|
|
// CHECK: integer_literal {{.*}} 0
|
|
// CHECK: [[FALSE:%.*]] = integer_literal {{.*}} 0
|
|
// CHECK: [[VAL:%[a-zA-Z0-9]+]] = select_enum %0 : $X, case #X.A!enumelt: [[TRUE]], default [[FALSE]]
|
|
// CHECK-NOT: switch_enum
|
|
// CHECK-NOT: bb2
|
|
// CHECK: [[RETVAL:%[a-zA-Z0-9]+]] = struct $Bool ([[VAL]] : $Builtin.Int1)
|
|
// CHECK-NEXT: return [[RETVAL]] : $Bool
|
|
%2 = integer_literal $Builtin.Int1, 0
|
|
switch_enum %0 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb2, case #X.C!enumelt: bb3
|
|
|
|
bb1: // Preds: bb0
|
|
%10 = integer_literal $Builtin.Int1, -1
|
|
br bb4(%10 : $Builtin.Int1)
|
|
|
|
bb2: // Preds: bb0
|
|
br bb4(%2 : $Builtin.Int1)
|
|
|
|
bb3: // Preds: bb0
|
|
br bb4(%2 : $Builtin.Int1)
|
|
|
|
bb4(%20 : $Builtin.Int1): // Preds: bb1 bb2 bb3
|
|
%11 = struct $Bool (%20 : $Builtin.Int1)
|
|
return %11 : $Bool
|
|
}
|
|
|
|
|
|
sil @external_f : $@convention(thin) () -> ()
|
|
|
|
// Check that switch_enum to select_enum conversion does not
|
|
// take place in a presence of side-effects.
|
|
// CHECK-LABEL: simplify_switch_to_select_enum_with_side_effects
|
|
sil @simplify_switch_to_select_enum_with_side_effects : $@convention(thin) (X) -> Int32 {
|
|
bb0(%0 : $X):
|
|
// CHECK: bb0
|
|
// CHECK-NOT: select_enum
|
|
// CHECK: switch_enum
|
|
switch_enum %0 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb2, case #X.C!enumelt: bb3
|
|
|
|
// CHECK: bb1:
|
|
bb1: // Preds: bb0
|
|
%10 = integer_literal $Builtin.Int32, 1
|
|
br bb4(%10 : $Builtin.Int32)
|
|
|
|
bb2: // Preds: bb0
|
|
// This BB contains a side-effect. Therefore switch_enum cannot be eliminated.
|
|
%11 = function_ref @external_f : $@convention(thin) () -> ()
|
|
%12 = apply %11() : $@convention(thin) () -> ()
|
|
%13 = integer_literal $Builtin.Int32, 2
|
|
br bb4(%13 : $Builtin.Int32)
|
|
|
|
// CHECK: bb3:
|
|
// CHECK: br bb4
|
|
bb3: // Preds: bb0
|
|
%14 = integer_literal $Builtin.Int32, 3
|
|
br bb4(%14 : $Builtin.Int32)
|
|
|
|
bb4(%20 : $Builtin.Int32): // Preds: bb1 bb2 bb3
|
|
// CHECK: bb4([[VAL:%[a-zA-Z0-9]+]]{{.*}}):
|
|
// CHECK: [[RETVAL:%[a-zA-Z0-9]+]] = struct $Int32 ([[VAL]] : $Builtin.Int32)
|
|
// CHECK-NEXT: return [[RETVAL]] : $Int32
|
|
%21 = struct $Int32 (%20 : $Builtin.Int32)
|
|
return %21 : $Int32
|
|
}
|
|
|
|
enum TwoCases {
|
|
case A
|
|
case B
|
|
}
|
|
|
|
struct S {
|
|
var x: Builtin.Int32
|
|
}
|
|
|
|
sil @useSandInt : $@convention(thin) (S, Builtin.Int32) -> ()
|
|
|
|
// CHECK-LABEL: sil @dont_opt_switch_enum_with_arg_bb
|
|
sil @dont_opt_switch_enum_with_arg_bb : $@convention(thin) (TwoCases, S, S) -> Builtin.Int32 {
|
|
bb0(%0 : $TwoCases, %1 : $S, %2 : $S):
|
|
%3 = integer_literal $Builtin.Int32, 3
|
|
%4 = integer_literal $Builtin.Int32, 4
|
|
// CHECK: switch_enum
|
|
switch_enum %0 : $TwoCases, case #TwoCases.A!enumelt: bb1, case #TwoCases.B!enumelt: bb2
|
|
|
|
bb1:
|
|
br bb3(%1 : $S)
|
|
|
|
bb2:
|
|
br bb3(%2 : $S)
|
|
|
|
bb3(%10 : $S):
|
|
br bb4(%3 : $Builtin.Int32)
|
|
|
|
bb4(%20 : $Builtin.Int32):
|
|
%11 = function_ref @useSandInt : $@convention(thin) (S, Builtin.Int32) -> ()
|
|
%12 = apply %11(%10, %20) : $@convention(thin) (S, Builtin.Int32) -> ()
|
|
cond_br undef, bb5, bb6
|
|
|
|
bb5:
|
|
br bb4(%4 : $Builtin.Int32)
|
|
|
|
bb6:
|
|
// CHECK: return
|
|
return %20 : $Builtin.Int32
|
|
}
|
|
|
|
enum E {
|
|
case Nope, Yup(Builtin.Int1)
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simplify_switch_enum_pred_no_arg
|
|
sil @simplify_switch_enum_pred_no_arg : $@convention(thin) (E) -> Builtin.Int1 {
|
|
bb0(%0 : $E):
|
|
// CHECK-LABEL: bb0
|
|
// CHECK: switch_enum %0 : $E, case #E.Nope!enumelt: bb1, case #E.Yup!enumelt: bb2
|
|
switch_enum %0 : $E, case #E.Nope!enumelt: bb1, case #E.Yup!enumelt: bb2
|
|
|
|
bb1:
|
|
%1 = integer_literal $Builtin.Int1, -1
|
|
br bb5(%1 : $Builtin.Int1)
|
|
|
|
bb2:
|
|
// CHECK: unchecked_enum_data %0 : $E, #E.Yup!enumelt
|
|
// CHECK-NOT: switch_enum
|
|
// CHECK: return
|
|
switch_enum %0 : $E, case #E.Yup!enumelt: bb4, case #E.Nope!enumelt: bb3
|
|
|
|
bb3:
|
|
%2 = integer_literal $Builtin.Int1, 0
|
|
br bb5(%2 : $Builtin.Int1)
|
|
|
|
bb4(%3 : $Builtin.Int1):
|
|
br bb5(%3 : $Builtin.Int1)
|
|
|
|
bb5(%4 : $Builtin.Int1):
|
|
return %4 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @same_destination_unused_arg
|
|
sil @same_destination_unused_arg : $@convention(thin) (Optional<Int32>) -> Optional<Int32> {
|
|
bb0(%0 : $Optional<Int32>):
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
// CHECK: select_enum
|
|
// CHECK-NEXT: return
|
|
%1 = select_enum %0 : $Optional<Int32>, case #Optional.some!enumelt: %t, default %f : $Builtin.Int1
|
|
cond_br %1, bb1(%0 : $Optional<Int32>), bb2(%0 : $Optional<Int32>)
|
|
|
|
bb1(%2 : $Optional<Int32>):
|
|
br bb2(%2 : $Optional<Int32>)
|
|
|
|
bb2(%3 : $Optional<Int32>):
|
|
return %0 : $Optional<Int32>
|
|
}
|
|
|
|
public enum Numbers {
|
|
case First, Second, Third, Fourth, Fifth
|
|
//var hashValue: Int32 { get }
|
|
}
|
|
|
|
|
|
// Check that one of the switch_enum instructions can be
|
|
// converted into select_enum instructions, even though
|
|
// the destination block is used as a target also by
|
|
// another switch_enum instruction
|
|
|
|
// CHECK_WITH_CODEMOTION-LABEL: sil @FormSelectEnumFromTwoSelectSwitches
|
|
// CHECK_WITH_CODEMOTION: switch_enum %0 : $Numbers
|
|
// CHECK_WITH_CODEMOTION-NOT: switch_enum
|
|
// CHECK_WITH_CODEMOTION: select_enum
|
|
// CHECK_WITH_CODEMOTION: return
|
|
sil @FormSelectEnumFromTwoSelectSwitches : $@convention(thin) (Numbers) -> Int32 {
|
|
bb0(%0 : $Numbers):
|
|
debug_value %0 : $Numbers, let, name "e" // id: %1
|
|
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, default bb6 // id: %2
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %3
|
|
|
|
bb2: // Preds: bb1
|
|
%4 = integer_literal $Builtin.Int32, 42 // user: %5
|
|
br bb20(%4 : $Builtin.Int32) // id: %6
|
|
|
|
bb3: // Preds: bb0
|
|
br bb5 // id: %7
|
|
|
|
bb4: // Preds: bb0
|
|
br bb5 // id: %8
|
|
|
|
bb5: // Preds: bb3 bb4
|
|
%9 = integer_literal $Builtin.Int32, 24 // user: %10
|
|
br bb20(%9 : $Builtin.Int32) // id: %11
|
|
|
|
bb6: // Preds: bb0
|
|
br bb7 // id: %12
|
|
|
|
bb7: // Preds: bb6
|
|
br bb8 // id: %13
|
|
|
|
bb8: // Preds: bb7
|
|
br bb9 // id: %14
|
|
|
|
bb9: // Preds: bb8
|
|
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb10, case #Numbers.Second!enumelt: bb12, case #Numbers.Third!enumelt: bb13, case #Numbers.Fourth!enumelt: bb15, default bb17 // id: %15
|
|
|
|
bb10: // Preds: bb9
|
|
br bb11 // id: %16
|
|
|
|
bb11: // Preds: bb10
|
|
%17 = integer_literal $Builtin.Int32, 42 // user: %18
|
|
br bb20(%17 : $Builtin.Int32) // id: %19
|
|
|
|
bb12: // Preds: bb9
|
|
br bb14 // id: %20
|
|
|
|
bb13: // Preds: bb9
|
|
br bb14 // id: %21
|
|
|
|
bb14: // Preds: bb12 bb13
|
|
%22 = integer_literal $Builtin.Int32, 24 // user: %23
|
|
br bb20(%22 : $Builtin.Int32) // id: %24
|
|
|
|
bb15: // Preds: bb9
|
|
br bb16 // id: %25
|
|
|
|
bb16: // Preds: bb15
|
|
%26 = integer_literal $Builtin.Int32, 100 // user: %27
|
|
br bb20(%26 : $Builtin.Int32) // id: %28
|
|
|
|
bb17: // Preds: bb9
|
|
br bb18 // id: %29
|
|
|
|
bb18: // Preds: bb17
|
|
br bb19 // id: %30
|
|
|
|
bb19: // Preds: bb18
|
|
%31 = integer_literal $Builtin.Int32, 100 // user: %32
|
|
br bb20(%31 : $Builtin.Int32) // id: %33
|
|
|
|
bb20(%34 : $Builtin.Int32): // Preds: bb2 bb5 bb11 bb14 bb16 bb19
|
|
%35 = struct $Int32 (%34 : $Builtin.Int32) // user: %36
|
|
return %35 : $Int32 // id: %36
|
|
}
|
|
|
|
// CHECK_WITH_CODEMOTION-LABEL: sil @FormSelectEnumIntResult
|
|
// CHECK_WITH_CODEMOTION-NOT: switch_enum
|
|
// CHECK_WITH_CODEMOTION: select_enum
|
|
// CHECK_WITH_CODEMOTION: return
|
|
sil @FormSelectEnumIntResult : $@convention(thin) (Numbers) -> Int32 {
|
|
bb0(%0 : $Numbers):
|
|
debug_value %0 : $Numbers, let, name "e" // id: %1
|
|
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, case #Numbers.Fourth!enumelt: bb6, default bb8 // id: %2
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %3
|
|
|
|
bb2: // Preds: bb1
|
|
%4 = integer_literal $Builtin.Int32, 42 // user: %5
|
|
br bb11(%4 : $Builtin.Int32) // id: %6
|
|
|
|
bb3: // Preds: bb0
|
|
br bb5 // id: %7
|
|
|
|
bb4: // Preds: bb0
|
|
br bb5 // id: %8
|
|
|
|
bb5: // Preds: bb3 bb4
|
|
%9 = integer_literal $Builtin.Int32, 24 // user: %10
|
|
br bb11(%9 : $Builtin.Int32) // id: %11
|
|
|
|
bb6: // Preds: bb0
|
|
br bb7 // id: %12
|
|
|
|
bb7: // Preds: bb6
|
|
%13 = integer_literal $Builtin.Int32, 100 // user: %14
|
|
br bb11(%13 : $Builtin.Int32) // id: %15
|
|
|
|
bb8: // Preds: bb0
|
|
br bb9 // id: %16
|
|
|
|
bb9: // Preds: bb8
|
|
br bb10 // id: %17
|
|
|
|
bb10: // Preds: bb9
|
|
%18 = integer_literal $Builtin.Int32, 100 // user: %19
|
|
br bb11(%18 : $Builtin.Int32) // id: %20
|
|
|
|
bb11(%21 : $Builtin.Int32): // Preds: bb2 bb5 bb7 bb10
|
|
%22 = struct $Int32 (%21: $Builtin.Int32)
|
|
return %22 : $Int32 // id: %22
|
|
}
|
|
|
|
// CHECK_WITH_CODEMOTION-LABEL: sil @FormSelectEnumBoolResult
|
|
// CHECK_WITH_CODEMOTION-NOT: switch_enum
|
|
// CHECK_WITH_CODEMOTION: select_enum
|
|
// CHECK_WITH_CODEMOTION: return
|
|
sil @FormSelectEnumBoolResult : $@convention(thin) (Numbers) -> Bool {
|
|
bb0(%0 : $Numbers):
|
|
debug_value %0 : $Numbers, let, name "e" // id: %1
|
|
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, default bb6 // id: %2
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %3
|
|
|
|
bb2: // Preds: bb1
|
|
%4 = integer_literal $Builtin.Int1, -1 // user: %5
|
|
br bb9(%4 : $Builtin.Int1) // id: %6
|
|
|
|
bb3: // Preds: bb0
|
|
br bb5 // id: %7
|
|
|
|
bb4: // Preds: bb0
|
|
br bb5 // id: %8
|
|
|
|
bb5: // Preds: bb3 bb4
|
|
%9 = integer_literal $Builtin.Int1, 0 // user: %10
|
|
br bb9(%9 : $Builtin.Int1) // id: %11
|
|
|
|
bb6: // Preds: bb0
|
|
br bb7 // id: %12
|
|
|
|
bb7: // Preds: bb6
|
|
br bb8 // id: %13
|
|
|
|
bb8: // Preds: bb7
|
|
%14 = integer_literal $Builtin.Int1, -1 // user: %15
|
|
br bb9(%14 : $Builtin.Int1) // id: %16
|
|
|
|
bb9(%17 : $Builtin.Int1): // Preds: bb2 bb5 bb8
|
|
%18 = struct $Bool (%17 : $Builtin.Int1)
|
|
return %18 : $Bool // id: %19
|
|
}
|
|
|
|
// CHECK_WITH_CODEMOTION-LABEL: sil @DontFormSelectEnumBoolResult
|
|
// CHECK_WITH_CODEMOTION: switch_enum
|
|
// CHECK_WITH_CODEMOTION-NOT: select_enum
|
|
// CHECK_WITH_CODEMOTION: return
|
|
sil @DontFormSelectEnumBoolResult : $@convention(thin) (Numbers, Bool) -> Bool {
|
|
bb0(%0 : $Numbers, %1 : $Bool):
|
|
debug_value %0 : $Numbers, let, name "e" // id: %2
|
|
%2 = struct_extract %1 : $Bool, #Bool._value
|
|
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, default bb6 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
br bb2 // id: %5
|
|
|
|
bb2: // Preds: bb1
|
|
%6 = integer_literal $Builtin.Int1, -1 // user: %7
|
|
br bb10(%6 : $Builtin.Int1) // id: %8
|
|
|
|
bb3: // Preds: bb0
|
|
br bb5 // id: %9
|
|
|
|
bb4: // Preds: bb0
|
|
br bb5 // id: %10
|
|
|
|
bb5: // Preds: bb3 bb4
|
|
%11 = integer_literal $Builtin.Int1, 0 // user: %12
|
|
br bb10(%11 : $Builtin.Int1) // id: %13
|
|
|
|
bb6: // Preds: bb0
|
|
br bb7 // id: %14
|
|
|
|
bb7: // Preds: bb6
|
|
br bb8 // id: %15
|
|
|
|
bb8: // Preds: bb7
|
|
br bb9 // id: %16
|
|
|
|
bb9: // Preds: bb8
|
|
br bb10(%2 : $Builtin.Int1) // id: %17
|
|
|
|
bb10(%18 : $Builtin.Int1): // Preds: bb2 bb5 bb9
|
|
%19 = struct $Bool (%18 : $Builtin.Int1)
|
|
return %19 : $Bool // id: %19
|
|
}
|
|
|