| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s |
| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -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.1, %2 : $(Int32, Int32) // user: %4 |
| switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt.1: bb3, case #X.C!enumelt.1: 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.1, %2 : $(Int32, Int32) // user: %4 |
| switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt.1: bb3, case #X.C!enumelt.1: 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.1: bb1, case #X.C!enumelt.1: bb5 |
| |
| // CHECK: bb1 |
| // CHECK-NOT: switch_enum |
| bb1(%12: $(Int32, Int32)): |
| switch_enum %2 : $X, case #X.A!enumelt: bb6, case #X.B!enumelt.1: bb7, case #X.C!enumelt.1: 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.1: bb9, case #X.C!enumelt.1: 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.1: bb7, case #X.C!enumelt.1: 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.1: bb3, case #EA.cC!enumelt.1: 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.1{{.*}} // user: %2 |
| // CHECK-NEXT: return [[VAL]] : $Int32 |
| switch_enum %0 : $EA, case #EA.cA!enumelt: bb1, case #EA.cB!enumelt.1: bb3, case #EA.cC!enumelt.1: 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.1: bb2, case #X.C!enumelt.1: 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.1: bb2, case #X.C!enumelt.1: 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 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.1: bb2 |
| switch_enum %0 : $E, case #E.Nope!enumelt: bb1, case #E.Yup!enumelt.1: bb2 |
| |
| bb1: |
| %1 = integer_literal $Builtin.Int1, -1 |
| br bb5(%1 : $Builtin.Int1) |
| |
| bb2: |
| // CHECK: unchecked_enum_data %0 : $E, #E.Yup!enumelt.1 |
| // CHECK-NOT: switch_enum |
| // CHECK: return |
| switch_enum %0 : $E, case #E.Yup!enumelt.1: 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.1: %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 |
| } |
| |