Files
swift-mirror/test/SILOptimizer/looprotate.sil
Erik Eckstein 287619445b LoopRotate: limit the size of the block to be duplicated.
This avoids significant code size regressions if the loop block to be duplicated is very large.

Also remove the ShouldRotate option. It's not needed anymore as disabling the pass can be done by -sil-disable-pass.

rdar://problem/33970453
2020-04-01 10:02:43 +02:00

465 lines
19 KiB
Plaintext

// RUN: %target-sil-opt -enable-objc-interop -enforce-exclusivity=none -enable-sil-verify-all -loop-rotate %s | %FileCheck %s
// Declare this SIL to be canonical because some tests break raw SIL
// conventions. e.g. address-type block args. -enforce-exclusivity=none is also
// required to allow address-type block args in canonical SIL.
sil_stage canonical
import Builtin
import Swift
protocol P {
func boo() -> Int64
}
class Bar {
func boo() -> Int64
func foo()
@objc func foo_objc()
}
sil @_TFC4main3Bar3foofS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> ()
sil @_TFC4main3Bar3boofS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> Int64
sil @_TFC4main3Bar3foo_objcfS0_FT_T_ : $@convention(objc_method) (Bar) -> ()
sil_vtable Bar {
#Bar.boo: @_TFC4main3Bar3boofS0_FT_T_
#Bar.foo: @_TFC4main3Bar3foofS0_FT_T_
#Bar.foo_objc: @_TFC4main3Bar3foofS0_FT_T_
}
// CHECK-LABEL: looprotate
// CHECK: bb0(%0 : $Int32, %1 : $Bar):
// CHECK: class_method
// CHECK: apply
// CHECK: cond_br {{.*}}, bb3({{.*}} : $Builtin.Int32), bb1
// CHECK: bb1:
// CHECK: br bb2({{.*}} : $Builtin.Int32, {{.*}} : $Builtin.Int32, {{.*}}: $Int32)
// CHECK: bb2({{.*}}: $Builtin.Int32, {{.*}} : $Builtin.Int32, {{.*}} : $Int32):
// CHECK: class_method
// CHECK: apply
// CHECK: cond_br {{%.*}}, bb3({{.*}} : $Builtin.Int32), bb2({{.*}} : $Builtin.Int32, {{.*}} : $Builtin.Int32, {{.*}} : $Int32)
// CHECK: bb3({{.*}} : $Builtin.Int32):
// CHECK: [[STRUCT:%.*]] = struct $Int32 ({{%.*}} : $Builtin.Int32)
// CHECK: return [[STRUCT]] : $Int32
// CHECK: } // end sil function 'looprotate'
sil @looprotate : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: $Bar):
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%30 = alloc_box $<τ_0_0> { var τ_0_0 } <Bool>
%30a = project_box %30 : $<τ_0_0> { var τ_0_0 } <Bool>, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32, %25: $Bar, %30 : $<τ_0_0> { var τ_0_0 } <Bool>, %30a : $*Bool)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool):
%24 = class_method %26 : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %6
%27 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Word"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Word"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Word"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// CHECK-LABEL: dont_duplicate_large_block
// CHECK: bb0(%0 : $Int32, %1 : $Bar):
// CHECK-NOT: class_method
// CHECK-NOT: apply
// CHECK: br bb1
// CHECK: bb1({{.*}}):
// CHECK: class_method
// CHECK: apply
// CHECK: cond_br
// CHECK: bb2:
// CHECK: br bb1
// CHECK: bb3:
// CHECK: return
// CHECK: } // end sil function 'dont_duplicate_large_block'
sil @dont_duplicate_large_block : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: $Bar):
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%30 = alloc_box $<τ_0_0> { var τ_0_0 } <Bool>
%30a = project_box %30 : $<τ_0_0> { var τ_0_0 } <Bool>, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32, %25: $Bar, %30 : $<τ_0_0> { var τ_0_0 } <Bool>, %30a : $*Bool)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool):
%24 = class_method %26 : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %6
%27 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%28 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%29 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%33 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%34 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%35 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%36 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%37 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%38 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%39 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%40 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%41 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%42 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%43 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%44 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%45 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%46 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%47 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%48 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%49 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%50 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%51 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%52 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%53 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%54 = apply %24(%25) : $@convention(method) (@guaranteed Bar) -> ()
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Word"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Word"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Word"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// This example illustrates the problem with using ValueUseIterators.
// As part of updating SSA form we will introduce a phi node argument to the
// branch to bb2. This means we change "cond_br %8, bb3(%4 : $Builtin.Int32),
// bb2" invalidating any outstanding use iterator pointing to the use of "%4" in
// said branch.
// CHECK-LABEL: looprotate2
// CHECK: return
sil @looprotate2 : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32):
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Word"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3(%4 : $Builtin.Int32), bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Word"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Word"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32)
bb3 (%23 : $Builtin.Int32) :
%24 = struct $Int32 (%23 : $Builtin.Int32)
return %24 : $Int32
}
// The following function used to crash the compiler, because loop rotate
// could not properly handle the reference from witness_method to the
// archetype opened by open_existential_addr
// CHECK-LABEL: sil @looprotate_with_opened_archetype
// CHECK: return
sil @looprotate_with_opened_archetype : $@convention(thin) (Int32, @in P) -> Int32 {
bb0(%0 : $Int32, %25: $*P):
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
%30 = alloc_box $<τ_0_0> { var τ_0_0 } <Bool>
%30a = project_box %30 : $<τ_0_0> { var τ_0_0 } <Bool>, 0
%40 = open_existential_addr immutable_access %25 : $*P to $*@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83") P
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32, %25: $*P, %30 : $<τ_0_0> { var τ_0_0 } <Bool>, %30a : $*Bool)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $*P, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool):
%111 = witness_method $@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83") P, #P.boo, %40 : $*@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
%122 = apply %111<@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83") P>(%40) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Word"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb2
bb2:
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Word"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Word"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32, %26: $*P, %31 : $<τ_0_0> { var τ_0_0 } <Bool>, %32 : $*Bool)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// Don't assert on this loop. bb2 is bb1 loop's new header after rotation but
// also bb2 loop's header.
// CHECK-LABEL: @testnested
// CHECK: return
sil @testnested : $@convention(thin) () -> () {
bb0:
br bb1(undef : $Builtin.Int32, undef : $Builtin.Int32) // id: %0
bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32): // Preds: bb0 bb2
%3 = integer_literal $Builtin.Int1, 0 // user: %4
cond_br %3, bb2(%1 : $Builtin.Int32, %2 : $Builtin.Int32), bb10 // id: %4
bb2(%5 : $Builtin.Int32, %6 : $Builtin.Int32): // Preds: bb1 bb8
%7 = integer_literal $Builtin.Int1, -1 // user: %8
cond_br %7, bb3, bb1(%5 : $Builtin.Int32, %6 : $Builtin.Int32) // id: %8
bb3: // Preds: bb2
%9 = integer_literal $Builtin.Int32, 0 // user: %11
%10 = integer_literal $Builtin.Int32, 1 // users: %14, %23
br bb4(%9 : $Builtin.Int32) // id: %11
bb4(%12 : $Builtin.Int32): // Preds: bb3 bb7
%14 = builtin "cmp_eq_Word"(%12 : $Builtin.Int32, %10 : $Builtin.Int32) : $Builtin.Int1 // user: %15
cond_br %14, bb5, bb9 // id: %15
bb5: // Preds: bb4
%16 = enum $Optional<Int32>, #Optional.none!enumelt // user: %17
br bb6(%12 : $Builtin.Int32, %16 : $Optional<Int32>) // id: %17
bb6(%18 : $Builtin.Int32, %19 : $Optional<Int32>): // Preds: bb5 bb9
switch_enum %19 : $Optional<Int32>, case #Optional.some!enumelt: bb7, case #Optional.none!enumelt: bb8 // id: %20
bb7: // Preds: bb6
%21 = unchecked_enum_data %19 : $Optional<Int32>, #Optional.some!enumelt
br bb4(%18 : $Builtin.Int32) // id: %22
bb8: // Preds: bb6
br bb2(%18 : $Builtin.Int32, %10 : $Builtin.Int32) // id: %23
bb9: // Preds: bb4
%24 = struct $Int32 (%12 : $Builtin.Int32) // user: %32
%25 = integer_literal $Builtin.Int32, 1 // user: %28
%27 = integer_literal $Builtin.Int1, -1 // user: %28
%28 = builtin "sadd_with_overflow_Word"(%12 : $Builtin.Int32, %25 : $Builtin.Int32, %27 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %29, %30
%29 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 0 // user: %33
%30 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 1 // user: %31
cond_fail %30 : $Builtin.Int1 // id: %31
%32 = enum $Optional<Int32>, #Optional.some!enumelt, %24 : $Int32 // user: %33
br bb6(%29 : $Builtin.Int32, %32 : $Optional<Int32>) // id: %33
bb10: // Preds: bb1
%34 = tuple () // user: %35
return %34 : $() // id: %35
}
// CHECK-LABEL: dont_looprotate_objc
// CHECK: bb0{{.*}}:
// CHECK: br bb1
// CHECK: bb1{{.*}}:
// CHECK: cond_br {{.*}}, bb3, bb2
// CHECK: bb2:
// CHECK: br bb1
// CHECK: bb3:
// CHECK: return
sil @dont_looprotate_objc : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: $Bar):
%100 = alloc_ref $Bar
%1 = struct_extract %0 : $Int32, #Int32._value
%2 = integer_literal $Builtin.Int32, 0
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32, %25: $Bar)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $Bar):
%101 = objc_method %100 : $Bar, #Bar.foo!foreign : (Bar) -> () -> (), $@convention(objc_method) (Bar) -> ()
%6 = struct $Int32 (%5 : $Builtin.Int32)
%8 = builtin "cmp_eq_Word"(%5 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb3, bb2
bb2:
%102 = apply %101(%100) : $@convention(objc_method) (Bar) -> ()
%10 = integer_literal $Builtin.Int32, 1
%12 = integer_literal $Builtin.Int1, -1
%13 = builtin "sadd_with_overflow_Word"(%5 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
%15 = enum $Optional<Int32>, #Optional.some!enumelt, %6 : $Int32
%16 = unchecked_enum_data %15 : $Optional<Int32>, #Optional.some!enumelt
%17 = struct_extract %16 : $Int32, #Int32._value
%19 = integer_literal $Builtin.Int1, -1
%20 = builtin "sadd_with_overflow_Word"(%4 : $Builtin.Int32, %17 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
br bb1(%21 : $Builtin.Int32, %14 : $Builtin.Int32, %26: $Bar)
bb3:
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
sil @readInt : $@convention(thin) (Int32) -> () {
bb0(%a0 : $Int32):
%t1 = tuple ()
return %t1 : $()
}
// Test the SSA Updater utility: replaceBBArgWithCast().
//
// CHECK-LABEL: struct_arg
// CHECK: bb0:
// CHECK: cond_br
// CHECK: bb1:
// CHECK: br bb2
// CHECK: bb2({{%.*}} : $Builtin.Int32, [[WORD:%.*]] : $Builtin.Int32
// CHECK: [[STRUCT:%[0-9]+]] = struct $Int32 ([[WORD]]
// CHECK: apply {{.*}}([[STRUCT]])
// CHECK: cond_br
// CHECK: bb3({{.*}}):
// CHECK: return
sil @struct_arg : $@convention(thin) () -> () {
bb0:
%c0 = integer_literal $Builtin.Int32, 0
%c100 = integer_literal $Builtin.Int32, 100
br bb1(%c0 : $Builtin.Int32, %c0 : $Builtin.Int32)
bb1(%a1 : $Builtin.Int32, %a0 : $Builtin.Int32):
%s0 = struct $Int32 (%a0 : $Builtin.Int32)
%z1 = builtin "cmp_eq_Word"(%a0 : $Builtin.Int32, %c100 : $Builtin.Int32) : $Builtin.Int1
cond_br %z1, bb2, bb3
bb3:
%c1 = integer_literal $Builtin.Int32, 1
%z2 = integer_literal $Builtin.Int1, 0
%d1 = builtin "sadd_with_overflow_Word"(%a0 : $Builtin.Int32, %c1 : $Builtin.Int32, %z2 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%t1 = tuple_extract %d1 : $(Builtin.Int32, Builtin.Int1), 0
%d2 = builtin "sadd_with_overflow_Word"(%a1 : $Builtin.Int32, %c1 : $Builtin.Int32, %z2 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%t2 = tuple_extract %d2 : $(Builtin.Int32, Builtin.Int1), 0
%f1 = function_ref @readInt : $@convention(thin) (Int32) -> ()
%l1 = apply %f1(%s0) : $@convention(thin) (Int32) -> ()
br bb1(%t2 : $Builtin.Int32, %t1 : $Builtin.Int32)
bb2:
%14 = struct $Int32 (%a1 : $Builtin.Int32)
%t3 = tuple ()
return %t3 : $()
}
// Test LoopRotate insertBackedgeBlock.
//
// CHECK-LABEL: insert_backedge_block
// PreLoop Check
// CHECK: bb0(%
// CHECK: cond_br
// Loop Header
// CHECK: bb1:
// CHECK-NEXT: br bb2
// CHECK: bb2:
// CHECK: cond_br %{{.*}}, bb3, bb5
// CHECK: bb3:
// CHECK: apply
// CHECK: br bb4(
// CHECK: bb4(%[[ARG:[0-9]*]]
// CHECK-NEXT: cond_br %{{.*}}, bb6, bb2
// CHECK: bb5:
// CHECK: apply
// CHECK: br bb4(%
// CHECK: bb6
// CHECK: return
sil @insert_backedge_block : $@convention(thin) (@owned @callee_owned () -> Builtin.Int32) -> () {
bb0(%0 : $@callee_owned () -> Builtin.Int32):
%r0 = apply %0() : $@callee_owned () -> Builtin.Int32
br bb1(%r0: $Builtin.Int32)
bb1(%a1 : $Builtin.Int32):
%z1 = integer_literal $Builtin.Int1, 0
cond_br %z1, bb5, bb2
bb2:
%z2 = integer_literal $Builtin.Int1, 0
cond_br %z2, bb3, bb4
bb3:
%r1 = apply %0() : $@callee_owned () -> Builtin.Int32
br bb1(%r1: $Builtin.Int32)
bb4:
%r2 = apply %0() : $@callee_owned () -> Builtin.Int32
br bb1(%r2: $Builtin.Int32)
bb5:
%r3 = tuple ()
return %r3 : $()
}
// CHECK-LABEL: sil @dont_rotate_single_basic_block_loop
// CHECK: bb0({{.*}}):
// CHECK: br bb1
// CHECK: bb1:
// CHECK: cond_br {{.*}}, bb1, bb2
// CHECK: bb2:
// CHECK: return
sil @dont_rotate_single_basic_block_loop : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
br bb1
bb1:
cond_br %0, bb1, bb2
bb2:
%1 = tuple ()
return %1 : $()
}
// CHECK-LABEL: sil @dont_rotate_single_basic_block_loop_split_backedge
// CHECK: bb0({{.*}}):
// CHECK: br bb1
// CHECK: bb1:
// CHECK: cond_br {{.*}}, bb2, bb3
// CHECK: bb2:
// CHECK: br bb1
// CHECK: bb3:
// CHECK: return
sil @dont_rotate_single_basic_block_loop_split_backedge : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
br bb1
bb1:
cond_br %0, bb2, bb3
bb2:
br bb1
bb3:
%1 = tuple ()
return %1 : $()
}