Files
swift-mirror/test/SILOptimizer/looprotate_ossa.sil
Erik Eckstein 45f08bd7c4 MemoryLifetime: support init_existential_addr and open_existential_addr
Also, relax the check for enums a bit. Instead of only accepting single-payload enums, just require that the payload type is the same for an enum location.
2021-03-07 09:10:22 +01:00

530 lines
21 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 [ossa] @_TFC4main3Bar3foofS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> ()
sil [ossa] @_TFC4main3Bar3boofS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> Int64
sil [ossa] @_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: sil [ossa] @looprotate :
// CHECK: bb0(%0 : $Int32, %1 : @owned $Bar):
// CHECK: class_method
// CHECK: apply
// CHECK: cond_br {{.*}}, bb2, bb1
// CHECK: bb1:
// CHECK-NEXT: br bb3({{.*}} : $Builtin.Int32, {{.*}} : $Builtin.Int32, {{.*}}: $Int32)
// CHECK: bb3({{.*}}: $Builtin.Int32, {{.*}} : $Builtin.Int32, {{.*}} : $Int32):
// CHECK: class_method
// CHECK: apply
// CHECK: cond_br {{%.*}}, bb5, bb4
// CHECK: bb5:
// CHECK-NEXT: br bb6({{.*}} : $Builtin.Int32, {{.*}} : $Bar, {{.*}} : $<τ_0_0> { var τ_0_0 } <Bool>)
// CHECK: bb6({{.*}} : $Builtin.Int32, {{.*}} : @owned $Bar, {{.*}} : @owned $<τ_0_0> { var τ_0_0 } <Bool>):
// CHECK: [[STRUCT:%.*]] = struct $Int32 ({{%.*}} : $Builtin.Int32)
// CHECK: return [[STRUCT]] : $Int32
// CHECK: } // end sil function 'looprotate'
sil [ossa] @looprotate : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: @owned $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>)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: @owned $Bar, %31 : @owned $<τ_0_0> { var τ_0_0 } <Bool>):
%24 = class_method %26 : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %6
%27 = apply %24(%26) : $@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>)
bb3:
destroy_value %26 : $Bar
destroy_value %31 : $<τ_0_0> { var τ_0_0 } <Bool>
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
// CHECK-LABEL: sil [ossa] @dont_duplicate_large_block :
// CHECK: bb0(%0 : $Int32, %1 : @owned $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 [ossa] @dont_duplicate_large_block : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: @owned $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>)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: @owned $Bar, %31 : @owned $<τ_0_0> { var τ_0_0 } <Bool>):
%24 = class_method %26 : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %6
%27 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%28 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%29 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%33 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%34 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%35 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%36 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%37 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%38 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%39 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%40 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%41 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%42 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%43 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%44 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%45 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%46 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%47 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%48 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%49 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%50 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%51 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%52 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%53 = apply %24(%26) : $@convention(method) (@guaranteed Bar) -> ()
%54 = apply %24(%26) : $@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>)
bb3:
destroy_value %26 : $Bar
destroy_value %31 : $<τ_0_0> { var τ_0_0 } <Bool>
%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: sil [ossa] @looprotate2 :
// CHECK: return
// CHECK-LABEL: } // end sil function 'looprotate2'
sil [ossa] @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, 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:
%24 = struct $Int32 (%4 : $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 [ossa] @looprotate_with_opened_archetype :
// CHECK: return
// CHECK-LABEL: } // end sil function 'looprotate_with_opened_archetype'
sil [ossa] @looprotate_with_opened_archetype : $@convention(thin) (Int32, @in_guaranteed 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, %30 : $<τ_0_0> { var τ_0_0 } <Bool>)
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %31 : @owned $<τ_0_0> { var τ_0_0 } <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, %31 : $<τ_0_0> { var τ_0_0 } <Bool>)
bb3:
destroy_value %31 : $<τ_0_0> { var τ_0_0 } <Bool>
%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: sil [ossa] @testnested :
// CHECK: return
// CHECK-LABEL: } // end sil function 'testnested'
sil [ossa] @testnested : $@convention(thin) () -> () {
bb0:
br bb1(undef : $Builtin.Int32, undef : $Builtin.Int32)
bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32):
%3 = integer_literal $Builtin.Int1, 0
cond_br %3, bb1a, bb10
bb1a:
br bb2(%1 : $Builtin.Int32, %2 : $Builtin.Int32)
bb2(%5 : $Builtin.Int32, %6 : $Builtin.Int32):
%7 = integer_literal $Builtin.Int1, -1
cond_br %7, bb3, bb2a
bb2a:
br bb1(%5 : $Builtin.Int32, %6 : $Builtin.Int32)
bb3:
%9 = integer_literal $Builtin.Int32, 0
%10 = integer_literal $Builtin.Int32, 1
br bb4(%9 : $Builtin.Int32)
bb4(%12 : $Builtin.Int32):
%14 = builtin "cmp_eq_Word"(%12 : $Builtin.Int32, %10 : $Builtin.Int32) : $Builtin.Int1
cond_br %14, bb5, bb9
bb5:
%16 = enum $Optional<Int32>, #Optional.none!enumelt
br bb6(%12 : $Builtin.Int32, %16 : $Optional<Int32>)
bb6(%18 : $Builtin.Int32, %19 : $Optional<Int32>):
switch_enum %19 : $Optional<Int32>, case #Optional.some!enumelt: bb7, case #Optional.none!enumelt: bb8
bb7(%arg : $Int32):
%21 = unchecked_enum_data %19 : $Optional<Int32>, #Optional.some!enumelt
br bb4(%18 : $Builtin.Int32)
bb8:
br bb2(%18 : $Builtin.Int32, %10 : $Builtin.Int32)
bb9:
%24 = struct $Int32 (%12 : $Builtin.Int32)
%25 = integer_literal $Builtin.Int32, 1
%27 = integer_literal $Builtin.Int1, -1
%28 = builtin "sadd_with_overflow_Word"(%12 : $Builtin.Int32, %25 : $Builtin.Int32, %27 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
%29 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 0
%30 = tuple_extract %28 : $(Builtin.Int32, Builtin.Int1), 1
cond_fail %30 : $Builtin.Int1
%32 = enum $Optional<Int32>, #Optional.some!enumelt, %24 : $Int32
br bb6(%29 : $Builtin.Int32, %32 : $Optional<Int32>)
bb10:
%34 = tuple ()
return %34 : $()
}
// CHECK-LABEL: sil [ossa] @dont_looprotate_objc :
// CHECK: bb0{{.*}}:
// CHECK: br bb1
// CHECK: bb1{{.*}}:
// CHECK: cond_br {{.*}}, bb3, bb2
// CHECK: bb2:
// CHECK: br bb1
// CHECK: bb3:
// CHECK: return
// CHECK-LABEL: } // end sil function 'dont_looprotate_objc'
sil [ossa] @dont_looprotate_objc : $@convention(thin) (Int32, @owned Bar) -> Int32 {
bb0(%0 : $Int32, %25: @owned $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: @owned $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:
destroy_value %100 : $Bar
destroy_value %26 : $Bar
%23 = struct $Int32 (%4 : $Builtin.Int32)
return %23 : $Int32
}
sil [ossa] @readInt : $@convention(thin) (Int32) -> () {
bb0(%a0 : $Int32):
%t1 = tuple ()
return %t1 : $()
}
// Test the SSA Updater utility: replaceBBArgWithCast().
//
// CHECK-LABEL: sil [ossa] @struct_arg :
// CHECK: bb0:
// CHECK: cond_br
// CHECK: bb1:
// CHECK: br bb3
// CHECK: bb3({{%.*}} : $Builtin.Int32, [[WORD:%.*]] : $Builtin.Int32
// CHECK: [[STRUCT:%[0-9]+]] = struct $Int32 ([[WORD]]
// CHECK: apply {{.*}}([[STRUCT]])
// CHECK: cond_br
// CHECK: bb6({{.*}}):
// CHECK: return
// CHECK-LABEL: } // end sil function 'struct_arg'
sil [ossa] @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: sil [ossa] @insert_backedge_block :
// PreLoop Check
// CHECK: bb0(%
// CHECK: cond_br
// Loop Header
// CHECK: bb1:
// CHECK-NEXT: br bb3
// CHECK: bb3:
// CHECK: cond_br %{{.*}}, bb4, bb8
// CHECK: bb4:
// CHECK: apply
// CHECK: br bb5(
// CHECK: bb5(%[[ARG:[0-9]*]]
// CHECK-NEXT: cond_br %{{.*}}, bb7, bb6
// CHECK: bb8:
// CHECK: apply
// CHECK: br bb5(%
// CHECK: bb9
// CHECK: return
// CHECK-LABEL: } // end sil function 'insert_backedge_block'
sil [ossa] @insert_backedge_block : $@convention(thin) (@owned @callee_owned () -> Builtin.Int32) -> () {
bb0(%0 : @owned $@callee_owned () -> Builtin.Int32):
%copy0 = copy_value %0 : $@callee_owned () -> Builtin.Int32
%r0 = apply %copy0() : $@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:
%copy1 = copy_value %0 : $@callee_owned () -> Builtin.Int32
%r1 = apply %copy1() : $@callee_owned () -> Builtin.Int32
br bb1(%r1: $Builtin.Int32)
bb4:
%copy2 = copy_value %0 : $@callee_owned () -> Builtin.Int32
%r2 = apply %copy2() : $@callee_owned () -> Builtin.Int32
br bb1(%r2: $Builtin.Int32)
bb5:
destroy_value %0 : $@callee_owned () -> Builtin.Int32
%r3 = tuple ()
return %r3 : $()
}
// CHECK-LABEL: sil [ossa] @dont_rotate_single_basic_block_loop :
// CHECK: bb0({{.*}}):
// CHECK: br bb1
// CHECK: bb1:
// CHECK: cond_br {{.*}}, bb2, bb3
// CHECK: bb2:
// CHECK: br bb1
// CHECK: bb3:
// CHECK: return
// CHECK-LABEL: } // end sil function 'dont_rotate_single_basic_block_loop'
sil [ossa] @dont_rotate_single_basic_block_loop : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
br bb1
bb1:
cond_br %0, bb1a, bb2
bb1a:
br bb1
bb2:
%1 = tuple ()
return %1 : $()
}
// Make sure that we do not create address phis.
//
// CHECK-LABEL: sil [ossa] @addressPhiFixUp : $@convention(thin) (Builtin.RawPointer) -> Builtin.RawPointer {
// CHECK: bb1:
// CHECK: [[NEXT:%.*]] = address_to_pointer {{%.*}} : $*UInt8 to $Builtin.RawPointer
// CHECK: cond_br {{%.*}}, bb3, bb2
//
// CHECK: bb2:
// CHECK-NEXT: br bb7(%0 : $Builtin.RawPointer)
//
// CHECK: bb3:
// CHECK-NEXT: br bb4([[NEXT]] : $Builtin.RawPointer)
//
// CHECK: bb4([[ARG:%.*]] :
// CHECK: [[CAST_BACK:%.*]] = pointer_to_address [[ARG]] : $Builtin.RawPointer to [strict] $*UInt8
// CHECK: [[GEP:%.*]] = index_addr [[CAST_BACK]] :
// CHECK: [[CAST_ROUND_TRIP_START:%.*]] = address_to_pointer [[GEP]]
// CHECK: [[CAST_ROUND_TRIP_END:%.*]] = pointer_to_address [[CAST_ROUND_TRIP_START]] : $Builtin.RawPointer to [strict] $*UInt8
// CHECK: [[BACK_TO_RAWPOINTER:%.*]] = address_to_pointer [[CAST_ROUND_TRIP_END]]
// CHECK: cond_br {{%.*}}, bb6, bb5
//
// CHECK: bb5:
// CHECK-NEXT: br bb7([[CAST_ROUND_TRIP_START]] :
//
// CHECK: bb6:
// CHECK-NEXT: br bb4([[BACK_TO_RAWPOINTER]] :
//
// CHECK: bb7([[RESULT:%.*]] :
// CHECK-NEXT: return [[RESULT]]
// CHECK: } // end sil function 'addressPhiFixUp'
sil [ossa] @addressPhiFixUp : $@convention(thin) (Builtin.RawPointer) -> Builtin.RawPointer {
bb0(%0 : $Builtin.RawPointer):
br bb1
bb1:
br bb2(%0 : $Builtin.RawPointer)
bb2(%1 : $Builtin.RawPointer):
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*UInt8
%3 = load [trivial] %2 : $*UInt8
%4 = destructure_struct %3 : $UInt8
%5 = integer_literal $Builtin.Int64, 0
%6 = builtin "zextOrBitCast_Int8_Int64"(%4 : $Builtin.Int8) : $Builtin.Int64
%7 = builtin "cmp_eq_Int64"(%6 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
cond_br %7, bb3, bb4
bb3:
%8 = integer_literal $Builtin.Word, 1
%9 = index_addr %2 : $*UInt8, %8 : $Builtin.Word
%10 = address_to_pointer %9 : $*UInt8 to $Builtin.RawPointer
br bb2(%10 : $Builtin.RawPointer)
bb4:
return %1 : $Builtin.RawPointer
}