mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This does not belong to loop-rotate and does not work with OSSA. This peephole is covered by other optimizations.
462 lines
19 KiB
Plaintext
462 lines
19 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -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 {{.*}}, 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)
|
|
|
|
// CHECK: bb6({{.*}} : $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>)
|
|
|
|
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <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>)
|
|
|
|
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>)
|
|
|
|
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %26: $Bar, %31 : $<τ_0_0> { var τ_0_0 } <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>)
|
|
|
|
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) Self
|
|
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32, %30 : $<τ_0_0> { var τ_0_0 } <Bool>)
|
|
|
|
bb1(%4 : $Builtin.Int32, %5 : $Builtin.Int32, %31 : $<τ_0_0> { var τ_0_0 } <Bool>):
|
|
%111 = witness_method $@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83", P) Self, #P.boo, %40 : $*@opened("C22498FA-CABF-11E5-B9A9-685B35C48C83", P) Self : $@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) Self>(%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:
|
|
%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 LoopRotate insertBackedgeBlock.
|
|
//
|
|
// CHECK-LABEL: 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
|
|
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 : $()
|
|
}
|
|
|
|
struct Wrapper : Sendable {
|
|
let id: Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_open_pack_element :
|
|
// CHECK: bb0{{.*}}:
|
|
// CHECK-NOT: open_pack_element
|
|
// CHECK: br bb2
|
|
// CHECK: } // end sil function 'test_open_pack_element'
|
|
sil @test_open_pack_element : $@convention(thin) (@pack_guaranteed Pack{KeyPath<Wrapper, Wrapper>}) -> () {
|
|
bb0(%0 : $*Pack{KeyPath<Wrapper, Wrapper>}):
|
|
%5 = alloc_stack $KeyPath<Wrapper, Wrapper>
|
|
%6 = integer_literal $Builtin.Word, 0 // user: %8
|
|
br bb2(%6 : $Builtin.Word)
|
|
|
|
bb1:
|
|
dealloc_stack %5 : $*KeyPath<Wrapper, Wrapper>
|
|
%35 = tuple ()
|
|
return %35 : $()
|
|
|
|
bb2(%37 : $Builtin.Word):
|
|
%38 = dynamic_pack_index %37 of $Pack{KeyPath<Wrapper, Wrapper>}
|
|
%39 = open_pack_element %38 of <Topic, each Value where Topic : AnyObject, repeat each Value : Sendable> at <Wrapper, Pack{Wrapper}>, shape $each Value, uuid "94218A22-3595-11EF-8496-4EA2A866E4C5"
|
|
%40 = pack_element_get %38 of %0 : $*Pack{KeyPath<Wrapper, Wrapper>} as $*KeyPath<Wrapper, @pack_element("94218A22-3595-11EF-8496-4EA2A866E4C5") each Value>
|
|
%41 = unchecked_addr_cast %5 : $*KeyPath<Wrapper, Wrapper> to $*KeyPath<Wrapper, @pack_element("94218A22-3595-11EF-8496-4EA2A866E4C5") each Value>
|
|
%42 = load %40 : $*KeyPath<Wrapper, @pack_element("94218A22-3595-11EF-8496-4EA2A866E4C5") each Value>
|
|
store %42 to %41 : $*KeyPath<Wrapper, @pack_element("94218A22-3595-11EF-8496-4EA2A866E4C5") each Value>
|
|
%7 = integer_literal $Builtin.Word, 1 // users: %45, %44
|
|
%44 = builtin "add_Word"(%37 : $Builtin.Word, %7 : $Builtin.Word) : $Builtin.Word // users: %48, %45
|
|
cond_br undef, bb1, bb3
|
|
|
|
bb3:
|
|
strong_retain %42 : $KeyPath<Wrapper, @pack_element("94218A22-3595-11EF-8496-4EA2A866E4C5") each Value>
|
|
br bb2(%44 : $Builtin.Word)
|
|
}
|