Files
swift-mirror/test/SILOptimizer/simplify_cfg_args.sil
Erik Eckstein 7cceaff5f3 SIL: don't print operand types in textual SIL
Type annotations for instruction operands are omitted, e.g.

```
  %3 = struct $S(%1, %2)
```

Operand types are redundant anyway and were only used for sanity checking in the SIL parser.

But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:

* if the block with the definition appears after the block where the operand's instruction is located

* if a block or instruction is printed in isolation, e.g. in a debugger

The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
2024-11-21 18:49:52 +01:00

817 lines
20 KiB
Plaintext

// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
// RUN: %target-sil-opt -sil-print-types -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)
strong_retain %1 : $Builtin.NativeObject
strong_retain %1 : $Builtin.NativeObject
strong_release %1 : $Builtin.NativeObject
%8 = integer_literal $Builtin.Int1, 0
%10 = global_addr @globalinit_token11 : $*Builtin.Word
%11 = address_to_pointer %10 : $*Builtin.Word to $Builtin.RawPointer
%12 = function_ref @globalinit_func11 : $@convention(thin) () -> ()
%14 = builtin "once"(%11 : $Builtin.RawPointer, %12 : $@convention(thin) () -> ()) : $()
%15 = alloc_stack $Int32
%16 = struct_element_addr %15 : $*Int32, #Int32._value
%17 = load %16 : $*Builtin.Int32
%18 = integer_literal $Builtin.Int32, -1
%20 = builtin "xor_Int32"(%17 : $Builtin.Int32, %18 : $Builtin.Int32) : $Builtin.Int32
%22 = builtin "and_Int32"(%2 : $Builtin.Int32, %20 : $Builtin.Int32) : $Builtin.Int32
// CHECK-NOT: cond_br
cond_br %8, bb1, bb2(%22 : $Builtin.Int32)
bb1:
%24 = global_addr @globalinit_token11 : $*Builtin.Word
%25 = address_to_pointer %24 : $*Builtin.Word to $Builtin.RawPointer
%27 = builtin "once"(%25 : $Builtin.RawPointer, %12 : $@convention(thin) () -> ()) : $()
%28 = load %16 : $*Builtin.Int32
// CHECK: [[VAR_21:%[0-9]+]] = builtin "and_Int32"
%30 = builtin "or_Int32"(%22 : $Builtin.Int32, %28 : $Builtin.Int32) : $Builtin.Int32
br bb2(%30 : $Builtin.Int32)
bb2(%32 : $Builtin.Int32):
// CHECK-NOT: tuple
%33 = tuple ()
br bb3(%33 : $())
bb3(%35 : $()):
// CHECK-NEXT: struct $Int32 ([[VAR_21]] : $Builtin.Int32)
%36 = struct $Int32 (%32 : $Builtin.Int32)
strong_retain %1 : $Builtin.NativeObject
strong_release %1 : $Builtin.NativeObject
strong_release %1 : $Builtin.NativeObject
dealloc_stack %15 : $*Int32
// CHECK: return
return %0 : $Builtin.RawPointer
}
//CHECK-LABEL: remove_dead_args
//CHECK-NOT: br bb2([[VAR_21:%[0-9]+]] : $Bool)
//CHECK: bb3:
//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:
%13 = tuple()
br bb2(%5 : $Bool)
// Remove this ARG.
bb2(%11 : $Bool):
%12 = tuple ()
return %12 : $()
}
class A {}
//CHECK-LABEL: no_remove_mandatory_dead_args
//CHECK: checked_cast_br AnyObject in {{%.*}} : $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 AnyObject in %0 : $AnyObject to A, bb1, bb2
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: sil @simplify_switch_include_args :
// CHECK: tuple
// CHECK-NEXT: enum $X
// CHECK-NEXT: unchecked_enum_data
// CHECK-NEXT: tuple_extract
// CHECK-NEXT: return
// CHECK: } // end sil function 'simplify_switch_include_args'
sil @simplify_switch_include_args : $@convention(thin) (Int32, Int32) -> Int32 {
bb0(%0 : $Int32, %1 : $Int32):
%2 = tuple (%0 : $Int32, %1 : $Int32)
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32)
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5
bb1:
br bb2
bb2:
%6 = integer_literal $Builtin.Int32, 0
%7 = struct $Int32 (%6 : $Builtin.Int32)
br bb7(%7 : $Int32)
bb3(%9 : $(Int32, Int32)):
%10 = tuple_extract %9 : $(Int32, Int32), 0
br bb4
bb4:
br bb7(%10 : $Int32)
bb5(%13 : $Int32):
br bb6
bb6:
br bb7(%13 : $Int32)
bb7(%16 : $Int32):
return %16 : $Int32
}
// 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)
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32)
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5
bb1:
br bb2
bb2:
%6 = integer_literal $Builtin.Int32, 0
%7 = struct $Int32 (%6 : $Builtin.Int32)
br bb6
bb3(%9 : $(Int32, Int32)):
%10 = tuple_extract %9 : $(Int32, Int32), 0
br bb4
bb4:
br bb6
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{{.*}}
// 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:
%10 = integer_literal $Builtin.Int1, -1
br bb4(%10 : $Builtin.Int1)
bb2:
br bb4(%2 : $Builtin.Int1)
bb3:
br bb4(%2 : $Builtin.Int1)
bb4(%20 : $Builtin.Int1):
%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:
%10 = integer_literal $Builtin.Int32, 1
br bb4(%10 : $Builtin.Int32)
bb2:
// 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:
%14 = integer_literal $Builtin.Int32, 3
br bb4(%14 : $Builtin.Int32)
bb4(%20 : $Builtin.Int32):
// 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"
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, default bb6
bb1:
br bb2
bb2:
%4 = integer_literal $Builtin.Int32, 42
br bb20(%4 : $Builtin.Int32)
bb3:
br bb5
bb4:
br bb5
bb5:
%9 = integer_literal $Builtin.Int32, 24
br bb20(%9 : $Builtin.Int32)
bb6:
br bb7
bb7:
br bb8
bb8:
br bb9
bb9:
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
bb10:
br bb11
bb11:
%17 = integer_literal $Builtin.Int32, 42
br bb20(%17 : $Builtin.Int32)
bb12:
br bb14
bb13:
br bb14
bb14:
%22 = integer_literal $Builtin.Int32, 24
br bb20(%22 : $Builtin.Int32)
bb15:
br bb16
bb16:
%26 = integer_literal $Builtin.Int32, 100
br bb20(%26 : $Builtin.Int32)
bb17:
br bb18
bb18:
br bb19
bb19:
%31 = integer_literal $Builtin.Int32, 100
br bb20(%31 : $Builtin.Int32)
bb20(%34 : $Builtin.Int32):
%35 = struct $Int32 (%34 : $Builtin.Int32)
return %35 : $Int32
}
// 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"
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
bb1:
br bb2
bb2:
%4 = integer_literal $Builtin.Int32, 42
br bb11(%4 : $Builtin.Int32)
bb3:
br bb5
bb4:
br bb5
bb5:
%9 = integer_literal $Builtin.Int32, 24
br bb11(%9 : $Builtin.Int32)
bb6:
br bb7
bb7:
%13 = integer_literal $Builtin.Int32, 100
br bb11(%13 : $Builtin.Int32)
bb8:
br bb9
bb9:
br bb10
bb10:
%18 = integer_literal $Builtin.Int32, 100
br bb11(%18 : $Builtin.Int32)
bb11(%21 : $Builtin.Int32):
%22 = struct $Int32 (%21: $Builtin.Int32)
return %22 : $Int32
}
// 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"
switch_enum %0 : $Numbers, case #Numbers.First!enumelt: bb1, case #Numbers.Second!enumelt: bb3, case #Numbers.Third!enumelt: bb4, default bb6
bb1:
br bb2
bb2:
%4 = integer_literal $Builtin.Int1, -1
br bb9(%4 : $Builtin.Int1)
bb3:
br bb5
bb4:
br bb5
bb5:
%9 = integer_literal $Builtin.Int1, 0
br bb9(%9 : $Builtin.Int1)
bb6:
br bb7
bb7:
br bb8
bb8:
%14 = integer_literal $Builtin.Int1, -1
br bb9(%14 : $Builtin.Int1)
bb9(%17 : $Builtin.Int1):
%18 = struct $Bool (%17 : $Builtin.Int1)
return %18 : $Bool
}
// 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"
%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
bb1:
br bb2
bb2:
%6 = integer_literal $Builtin.Int1, -1
br bb10(%6 : $Builtin.Int1)
bb3:
br bb5
bb4:
br bb5
bb5:
%11 = integer_literal $Builtin.Int1, 0
br bb10(%11 : $Builtin.Int1)
bb6:
br bb7
bb7:
br bb8
bb8:
br bb9
bb9:
br bb10(%2 : $Builtin.Int1)
bb10(%18 : $Builtin.Int1):
%19 = struct $Bool (%18 : $Builtin.Int1)
return %19 : $Bool
}
// --- Test simplifyArguments; unwrap enum argument
// This optimization should not be defeated by the existence of other
// (unrelated) block arguments
struct Payload {
init()
}
enum MyEnum {
case payload(Payload)
}
enum ThreeWay {
case one
case two
case three
@_implements(Equatable, ==(_:_:)) static func __derived_enum_equals(_ a: ThreeWay, _ b: ThreeWay) -> Bool
var hashValue: Int { get }
func hash(into hasher: inout Hasher)
}
// CHECK-LABEL: sil hidden [noinline] @testUnwrapEnumArg : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: br bb1(%{{.*}} : $Payload)
// CHECK: bb1(%{{.*}} : $Payload):
// CHECK: alloc_stack $Payload
// CHECK: switch_enum undef : $ThreeWay, case #ThreeWay.one!enumelt: bb4, case #ThreeWay.two!enumelt: bb2, case #ThreeWay.three!enumelt: bb3
// CHECK: bb2:
// CHECK: [[P2:%.*]] = load %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: br bb1([[P2]] : $Payload)
// CHECK: bb3:
// CHECK: [[P3:%.*]] = load %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: br bb7
// CHECK: bb4:
// CHECK: [[P4:%.*]] = load %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: cond_br undef, bb5, bb6
// CHECK: bb5:
// CHECK: br bb7
// CHECK: bb6:
// CHECK: br bb1([[P4]] : $Payload)
// CHECK: bb7:
// CHECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function 'testUnwrapEnumArg'
sil hidden [noinline] @testUnwrapEnumArg : $@convention(thin) () -> () {
bb0:
%0 = struct $Payload (undef : $_UIntBuffer<UInt8>)
%1 = enum $MyEnum, #MyEnum.payload!enumelt, %0 : $Payload
br bb1(undef : $Builtin.Int64, %1 : $MyEnum)
bb1(%3 : $Builtin.Int64, %4 : $MyEnum):
%5 = alloc_stack $Payload
%6 = unchecked_enum_data %4 : $MyEnum, #MyEnum.payload!enumelt
store %6 to %5 : $*Payload
%8 = builtin "cmp_eq_Int64"(%3 : $Builtin.Int64, undef : $Builtin.Int64) : $Builtin.Int1
switch_enum undef : $ThreeWay, case #ThreeWay.one!enumelt: bb4, case #ThreeWay.two!enumelt: bb2, case #ThreeWay.three!enumelt: bb3
bb2:
%10 = load %5 : $*Payload
%11 = enum $MyEnum, #MyEnum.payload!enumelt, %10 : $Payload
dealloc_stack %5 : $*Payload
br bb6(%11 : $MyEnum)
bb3:
%14 = load %5 : $*Payload
%15 = enum $MyEnum, #MyEnum.payload!enumelt, %14 : $Payload
dealloc_stack %5 : $*Payload
br bb7
bb4:
%18 = load %5 : $*Payload
%19 = enum $MyEnum, #MyEnum.payload!enumelt, %18 : $Payload
dealloc_stack %5 : $*Payload
cond_br undef, bb7, bb5
bb5:
br bb6(%19 : $MyEnum)
bb6(%23 : $MyEnum):
br bb1(undef : $Builtin.Int64, %23 : $MyEnum)
bb7:
%25 = tuple ()
return %25 : $()
}