blob: 994bac4dbc2f77d2f5733990d3502981b42b4d32 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -global-opt | %FileCheck %s
//
// ginit.cold has a hammock with an initializer call on the slow path.
// ginit.loop has a loop containing an initializer call.
sil_stage canonical
import Builtin
import Swift
// globalinit_token0
sil_global private @globalinit_token0 : $Builtin.Word
sil_global @MyConst : $Int32
// globalinit_func0
sil private @globalinit_func0 : $@convention(c) () -> () {
bb0:
%0 = global_addr @MyConst : $*Int32 // user: %3
%1 = integer_literal $Builtin.Int32, 0 // user: %2
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %3
store %2 to %0 : $*Int32 // id: %3
%4 = tuple () // user: %5
return %4 : $() // id: %5
}
// ginit.MyConst.mutableAddressor : Swift.Int32
sil [global_init] @_TF5ginita7MyConstSi : $@convention(thin) () -> Builtin.RawPointer {
bb0:
%1 = global_addr @globalinit_token0 : $*Builtin.Word // user: %2
%2 = address_to_pointer %1 : $*Builtin.Word to $Builtin.RawPointer // user: %5
// function_ref globalinit_func0
%3 = function_ref @globalinit_func0 : $@convention(c) () -> () // user: %4
%5 = builtin "once"(%2 : $Builtin.RawPointer, %3 : $@convention(c) () -> ()) : $()
%6 = global_addr @MyConst : $*Int32 // user: %7
%7 = address_to_pointer %6 : $*Int32 to $Builtin.RawPointer // user: %8
return %7 : $Builtin.RawPointer // id: %8
}
// Don't hoist this initializer call.
// ginit.cold (Swift.Int32) -> Swift.Int32
// CHECK-LABEL: sil @_TF5ginit4coldFSiSi
// CHECK-NOT: 5ginita7MyConst
// CHECK: bb1:
// CHECK: 5ginita7MyConst
// CHECK: {{^bb2}}
sil @_TF5ginit4coldFSiSi : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%1 = integer_literal $Builtin.Int32, 0 // users: %4, %5, %13
%3 = struct_extract %0 : $Int32, #Int32._value // user: %4
%4 = builtin "cmp_sgt_Int32"(%3 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1 // user: %5
cond_br %4, bb1, bb2(%1 : $Builtin.Int32) // id: %5
bb1: // Preds: bb0
// function_ref ginit.MyConst.mutableAddressor : Swift.Int32
%6 = function_ref @_TF5ginita7MyConstSi : $@convention(thin) () -> Builtin.RawPointer // user: %7
%7 = apply %6() : $@convention(thin) () -> Builtin.RawPointer // user: %8
%8 = pointer_to_address %7 : $Builtin.RawPointer to [strict] $*Int32 // user: %9
%9 = struct_element_addr %8 : $*Int32, #Int32._value // user: %10
%10 = load %9 : $*Builtin.Int32 // user: %13
%12 = integer_literal $Builtin.Int1, -1 // user: %13
%13 = builtin "sadd_with_overflow_Int32"(%1 : $Builtin.Int32, %10 : $Builtin.Int32, %12 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %14
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0 // user: %15
br bb2(%14 : $Builtin.Int32) // id: %15
bb2(%16 : $Builtin.Int32): // Preds: bb0 bb1
%17 = struct $Int32 (%16 : $Builtin.Int32) // user: %18
return %17 : $Int32 // id: %18
}
// Do hoist this initializer call.
// ginit.loop (Swift.Int32) -> Swift.Int32
// CHECK-LABEL: sil @_TF5ginit4loopFSiSi
// CHECK: {{^bb0}}
// CHECK: 5ginita7MyConst
// CHECK: {{^bb1}}
// CHECK-NOT: 5ginita7MyConst
sil @_TF5ginit4loopFSiSi : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%1 = integer_literal $Builtin.Int32, 0 // user: %8
%2 = integer_literal $Builtin.Int32, 1 // users: %6, %8, %22
%3 = struct_extract %0 : $Int32, #Int32._value // user: %6
%5 = integer_literal $Builtin.Int1, -1 // users: %6, %22, %37
%6 = builtin "sadd_with_overflow_Int32"(%3 : $Builtin.Int32, %2 : $Builtin.Int32, %5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %7
%7 = tuple_extract %6 : $(Builtin.Int32, Builtin.Int1), 0 // user: %13
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32) // id: %8
bb1(%9 : $Builtin.Int32, %10 : $Builtin.Int32): // Preds: bb0 bb5
%11 = struct $Int32 (%10 : $Builtin.Int32) // user: %24
%13 = builtin "cmp_eq_Int32"(%10 : $Builtin.Int32, %7 : $Builtin.Int32) : $Builtin.Int1 // user: %14
cond_br %13, bb2, bb4 // id: %14
bb2: // Preds: bb1
%15 = enum $Optional<Int32>, #Optional.none!enumelt // user: %16
br bb3(%10 : $Builtin.Int32, %15 : $Optional<Int32>) // id: %16
bb3(%17 : $Builtin.Int32, %18 : $Optional<Int32>): // Preds: bb2 bb4
%19 = alloc_stack $Optional<Int32> // users: %20, %26, %27, %40
store %18 to %19 : $*Optional<Int32> // id: %20
switch_enum %18 : $Optional<Int32>, case #Optional.some!enumelt.1: bb5, case #Optional.none!enumelt: bb6 // id: %21
bb4: // Preds: bb1
%22 = builtin "sadd_with_overflow_Int32"(%10 : $Builtin.Int32, %2 : $Builtin.Int32, %5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %23
%23 = tuple_extract %22 : $(Builtin.Int32, Builtin.Int1), 0 // user: %25
%24 = enum $Optional<Int32>, #Optional.some!enumelt.1, %11 : $Int32 // user: %25
br bb3(%23 : $Builtin.Int32, %24 : $Optional<Int32>) // id: %25
bb5: // Preds: bb3
%26 = unchecked_take_enum_data_addr %19 : $*Optional<Int32>, #Optional.some!enumelt.1
dealloc_stack %19 : $*Optional<Int32> // id: %27
%28 = alloc_stack $Optional<Int32> // users: %29, %30, %31
store %18 to %28 : $*Optional<Int32> // id: %29
%30 = unchecked_take_enum_data_addr %28 : $*Optional<Int32>, #Optional.some!enumelt.1
dealloc_stack %28 : $*Optional<Int32> // id: %31
// function_ref ginit.MyConst.mutableAddressor : Swift.Int32
%32 = function_ref @_TF5ginita7MyConstSi : $@convention(thin) () -> Builtin.RawPointer // user: %33
%33 = apply %32() : $@convention(thin) () -> Builtin.RawPointer // user: %34
%34 = pointer_to_address %33 : $Builtin.RawPointer to [strict] $*Int32 // user: %35
%35 = struct_element_addr %34 : $*Int32, #Int32._value // user: %36
%36 = load %35 : $*Builtin.Int32 // user: %37
%37 = builtin "sadd_with_overflow_Int32"(%9 : $Builtin.Int32, %36 : $Builtin.Int32, %5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %38
%38 = tuple_extract %37 : $(Builtin.Int32, Builtin.Int1), 0 // user: %39
br bb1(%38 : $Builtin.Int32, %17 : $Builtin.Int32) // id: %39
bb6: // Preds: bb3
dealloc_stack %19 : $*Optional<Int32> // id: %40
%41 = struct $Int32 (%9 : $Builtin.Int32) // user: %42
return %41 : $Int32 // id: %42
}
// libg.MyGlobal.mutableAddressor : Swift.Int32
sil [global_init] @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
// Hoist this initializer call out of a loop, but not into the function entry.
// ginit.loop (Swift.Int32) -> Swift.Int32
// CHECK-LABEL: sil @_TF10ginitloops3runFSiSi
// CHECK: {{^bb2}}
// CHECK: function_ref @_TF4libga8MyGlobalSi
// CHECK-NEXT: apply
// CHECK: {{^bb6}}
// CHECK-NOT: addressor
// CHECK-NOT: mutableAddressor
// CHECK: pointer_to_address
// CHECK: {{br bb6}}
//
// ginitloops.run (Swift.Int32) -> Swift.Int32
sil @_TF10ginitloops3runFSiSi : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%1 = integer_literal $Builtin.Int32, 1000 // user: %4
%3 = struct_extract %0 : $Int32, #Int32._value // users: %4, %16, %29
%4 = builtin "cmp_sgt_Int32"(%3 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1 // user: %5
cond_br %4, bb1, bb2 // id: %5
bb1: // Preds: bb0
%6 = integer_literal $Builtin.Int32, -1 // user: %7
%7 = struct $Int32 (%6 : $Builtin.Int32) // user: %8
br bb9(%7 : $Int32) // id: %8
bb2: // Preds: bb0
%9 = integer_literal $Builtin.Int32, 0 // user: %11
%10 = integer_literal $Builtin.Int32, 1 // users: %11, %22, %25, %34
br bb3(%9 : $Builtin.Int32, %10 : $Builtin.Int32) // id: %11
bb3(%12 : $Builtin.Int32, %13 : $Builtin.Int32): // Preds: bb2 bb7
%14 = struct $Int32 (%13 : $Builtin.Int32) // user: %24
%16 = builtin "cmp_eq_Int32"(%13 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // user: %17
cond_br %16, bb4, bb5 // id: %17
bb4: // Preds: bb3
%18 = struct $Int32 (%12 : $Builtin.Int32) // user: %19
br bb9(%18 : $Int32) // id: %19
bb5: // Preds: bb3
%21 = integer_literal $Builtin.Int1, -1 // user: %22
%22 = builtin "sadd_with_overflow_Int32"(%13 : $Builtin.Int32, %10 : $Builtin.Int32, %21 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %23
%23 = tuple_extract %22 : $(Builtin.Int32, Builtin.Int1), 0 // user: %31
%24 = enum $Optional<Int32>, #Optional.some!enumelt.1, %14 : $Int32
br bb6(%12 : $Builtin.Int32, %10 : $Builtin.Int32) // id: %25
bb6(%26 : $Builtin.Int32, %27 : $Builtin.Int32): // Preds: bb5 bb8
%28 = struct $Int32 (%27 : $Builtin.Int32) // user: %36
%29 = builtin "cmp_eq_Int32"(%27 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // user: %30
cond_br %29, bb7, bb8 // id: %30
bb7: // Preds: bb6
br bb3(%26 : $Builtin.Int32, %23 : $Builtin.Int32) // id: %31
bb8: // Preds: bb6
%33 = integer_literal $Builtin.Int1, -1 // user: %34
%34 = builtin "sadd_with_overflow_Int32"(%27 : $Builtin.Int32, %10 : $Builtin.Int32, %33 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %35
%35 = tuple_extract %34 : $(Builtin.Int32, Builtin.Int1), 0 // user: %46
%36 = enum $Optional<Int32>, #Optional.some!enumelt.1, %28 : $Int32
// function_ref libg.MyGlobal.mutableAddressor : Swift.Int32
%37 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer // user: %38
%38 = apply %37() : $@convention(thin) () -> Builtin.RawPointer // user: %39
%39 = pointer_to_address %38 : $Builtin.RawPointer to [strict] $*Int32 // user: %40
%40 = struct_element_addr %39 : $*Int32, #Int32._value // user: %41
%41 = load %40 : $*Builtin.Int32 // user: %44
%43 = integer_literal $Builtin.Int1, -1 // user: %44
%44 = builtin "sadd_with_overflow_Int32"(%26 : $Builtin.Int32, %41 : $Builtin.Int32, %43 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %45
%45 = tuple_extract %44 : $(Builtin.Int32, Builtin.Int1), 0 // user: %46
br bb6(%45 : $Builtin.Int32, %35 : $Builtin.Int32) // id: %46
bb9(%47 : $Int32): // Preds: bb1 bb4
return %47 : $Int32 // id: %48
}
// Do NOT hoist this initializer out of a cold block.
// CHECK-LABEL: sil @_TF9ginitcold3runFSiSi
// CHECK-NOT: addressor
// CHECK-NOT: mutableAddressor
// CHECK: {{^bb3}}
// CHECK: cond_br
// CHECK: {{^bb4}}
// CHECK: function_ref @_TF4libga8MyGlobalSi
// CHECK-NEXT: apply
// CHECK: pointer_to_address
// CHECK: br
sil @_TF9ginitcold3runFSiSi : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
%1 = integer_literal $Builtin.Int32, 0 // users: %4, %19
%2 = integer_literal $Builtin.Int32, 1 // users: %4, %14
%3 = struct_extract %0 : $Int32, #Int32._value // user: %8
br bb1(%1 : $Builtin.Int32, %2 : $Builtin.Int32) // id: %4
bb1(%5 : $Builtin.Int32, %6 : $Builtin.Int32): // Preds: bb0 bb5
%8 = builtin "cmp_eq_Int32"(%6 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // user: %9
cond_br %8, bb2, bb3 // id: %9
bb2: // Preds: bb1
%10 = struct $Int32 (%5 : $Builtin.Int32) // user: %11
return %10 : $Int32 // id: %11
bb3: // Preds: bb1
%13 = integer_literal $Builtin.Int1, -1 // users: %14, %29
%14 = builtin "sadd_with_overflow_Int32"(%6 : $Builtin.Int32, %2 : $Builtin.Int32, %13 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %15
%15 = tuple_extract %14 : $(Builtin.Int32, Builtin.Int1), 0 // user: %33
%16 = integer_literal $Builtin.Int32, 10 // user: %18
%18 = builtin "srem_Int32"(%5 : $Builtin.Int32, %16 : $Builtin.Int32) : $Builtin.Int32 // user: %19
%19 = builtin "cmp_eq_Int32"(%18 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1 // user: %22
%20 = integer_literal $Builtin.Int1, 0 // user: %22
%22 = builtin "int_expect_Int1"(%19 : $Builtin.Int1, %20 : $Builtin.Int1) : $Builtin.Int1 // user: %23
cond_br %22, bb4, bb5(%5 : $Builtin.Int32) // id: %23
bb4: // Preds: bb3
// function_ref libg.MyGlobal.mutableAddressor : Swift.Int32
%24 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer // user: %25
%25 = apply %24() : $@convention(thin) () -> Builtin.RawPointer // user: %26
%26 = pointer_to_address %25 : $Builtin.RawPointer to [strict] $*Int32 // user: %27
%27 = struct_element_addr %26 : $*Int32, #Int32._value // user: %28
%28 = load %27 : $*Builtin.Int32 // user: %29
%29 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %28 : $Builtin.Int32, %13 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // user: %30
%30 = tuple_extract %29 : $(Builtin.Int32, Builtin.Int1), 0 // user: %31
br bb5(%30 : $Builtin.Int32) // id: %31
bb5(%32 : $Builtin.Int32): // Preds: bb3 bb4
br bb1(%32 : $Builtin.Int32, %15 : $Builtin.Int32) // id: %33
}
// Combine two init calls into one in the common dominator
// CHECK-LABEL: sil @test_common_dominator
// CHECK: bb0(%0 : $Builtin.Int1):
// CHECK: apply
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: return
sil @test_common_dominator : $@convention(thin) (Builtin.Int1) -> Int64 {
bb0(%0 : $Builtin.Int1):
%1 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
%2 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int64
%4 = struct_element_addr %3 : $*Int64, #Int64._value
%5 = load %4 : $*Builtin.Int64
cond_br %0, bb1, bb2(%5 : $Builtin.Int64)
bb1:
%8 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
%9 = pointer_to_address %8 : $Builtin.RawPointer to [strict] $*Int64
%10 = struct_element_addr %9 : $*Int64, #Int64._value
%11 = load %10 : $*Builtin.Int64
br bb2(%11 : $Builtin.Int64)
bb2(%18 : $Builtin.Int64):
%19 = struct $Int64 (%18 : $Builtin.Int64)
return %19 : $Int64
}
// Combine two init calls into one in the common dominator
// CHECK-LABEL: sil @test_common_dominator2
// CHECK: bb0(%0 : $Builtin.Int1):
// CHECK: apply
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: return
sil @test_common_dominator2 : $@convention(thin) (Builtin.Int1) -> Int64 {
bb0(%0 : $Builtin.Int1):
cond_br %0, bb1, bb2
bb1:
%1 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
%2 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int64
%4 = struct_element_addr %3 : $*Int64, #Int64._value
%5 = load %4 : $*Builtin.Int64
br bb3(%5 : $Builtin.Int64)
bb2:
%11 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
%12 = apply %11() : $@convention(thin) () -> Builtin.RawPointer
%13 = pointer_to_address %12 : $Builtin.RawPointer to [strict] $*Int64
%14 = struct_element_addr %13 : $*Int64, #Int64._value
%15 = load %14 : $*Builtin.Int64
br bb3(%15 : $Builtin.Int64)
bb3(%18 : $Builtin.Int64):
%19 = struct $Int64 (%18 : $Builtin.Int64)
return %19 : $Int64
}
// Test a special case: If there is a call in a loop and in its exit block, which is located
// before the loop, the init-call should still be hoisted out of the loop.
// CHECK-LABEL: sil @test_loopexit_and_loop
// CHECK: bb0(%0 : $Builtin.Int1):
// CHECK: apply
// CHECK: bb1:
// CHECK-NOT: apply
// CHECK: return
sil @test_loopexit_and_loop : $@convention(thin) (Builtin.Int1) -> Int64 {
bb0(%0 : $Builtin.Int1):
br bb2
bb1:
%1 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
%2 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int64
%4 = struct_element_addr %3 : $*Int64, #Int64._value
%5 = load %4 : $*Builtin.Int64
%r1 = struct $Int64 (%5 : $Builtin.Int64)
return %r1 : $Int64
bb2:
%11 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
%12 = apply %11() : $@convention(thin) () -> Builtin.RawPointer
%13 = pointer_to_address %12 : $Builtin.RawPointer to [strict] $*Int64
%14 = struct_element_addr %13 : $*Int64, #Int64._value
%15 = load %14 : $*Builtin.Int64
cond_br %0, bb2, bb1
}
// libg.MyGlobal.mutableAddressor : Swift.Int32
sil [global_init] [dynamically_replacable] @_TF4libga8MyGlobalSi_dynamic : $@convention(thin) () -> Builtin.RawPointer
// Don't hoist dynamic_function_ref calls.
// CHECK-LABEL: sil @test_loopexit_and_loop_dynamic
// CHECK: bb0(%0 : $Builtin.Int1):
// CHECK: bb1:
// CHECK: apply
// CHECK: return
// CHECK: bb2:
// CHECK: apply
// CHECK: cond_br
sil @test_loopexit_and_loop_dynamic : $@convention(thin) (Builtin.Int1) -> Int64 {
bb0(%0 : $Builtin.Int1):
br bb2
bb1:
%1 = dynamic_function_ref @_TF4libga8MyGlobalSi_dynamic : $@convention(thin) () -> Builtin.RawPointer
%2 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int64
%4 = struct_element_addr %3 : $*Int64, #Int64._value
%5 = load %4 : $*Builtin.Int64
%r1 = struct $Int64 (%5 : $Builtin.Int64)
return %r1 : $Int64
bb2:
%11 = dynamic_function_ref @_TF4libga8MyGlobalSi_dynamic : $@convention(thin) () -> Builtin.RawPointer
%12 = apply %11() : $@convention(thin) () -> Builtin.RawPointer
%13 = pointer_to_address %12 : $Builtin.RawPointer to [strict] $*Int64
%14 = struct_element_addr %13 : $*Int64, #Int64._value
%15 = load %14 : $*Builtin.Int64
cond_br %0, bb2, bb1
}
// An init-call, which is guarded by an availability-check may not be speculated.
// In this test it may not be hoisted out of the loop.
// CHECK-LABEL: sil @test_availability_loop
// CHECK: [[INIT:%[0-9]+]] = function_ref @_TF4libga8MyGlobalSi
// CHECK: {{^bb2:}}
// CHECK-NEXT: apply [[INIT]]()
sil @test_availability_loop : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
%f1 = function_ref @test_availability : $@convention(thin) () -> Builtin.Int1
%f2 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%a1 = apply %f1() : $@convention(thin) () -> Builtin.Int1
cond_br %a1, bb2, bb4
bb2:
%a2 = apply %f2() : $@convention(thin) () -> Builtin.RawPointer
br bb3
bb3:
cond_br %0, bb1, bb4
bb4:
%r = tuple ()
return %r : $()
}
// The init-call should be hoisted out of the inner loop, but not out of the
// outer loop, because of the availability check around the inner loop.
// CHECK-LABEL: sil @test_availability_loop_nest
// CHECK: [[INIT:%[0-9]+]] = function_ref @_TF4libga8MyGlobalSi
// CHECK: {{^bb2:}}
// CHECK-NEXT: apply [[INIT]]()
sil @test_availability_loop_nest : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
%f1 = function_ref @test_availability : $@convention(thin) () -> Builtin.Int1
%f2 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%a1 = apply %f1() : $@convention(thin) () -> Builtin.Int1
cond_br %a1, bb2, bb4
bb2:
br bb3
bb3:
%a2 = apply %f2() : $@convention(thin) () -> Builtin.RawPointer
cond_br %0, bb3, bb4
bb4:
cond_br %0, bb1, bb5
bb5:
%r = tuple ()
return %r : $()
}
// The init-calls may not be moved to their common dominator because of
// availability guards.
// CHECK-LABEL: sil @test_availability_common_dominator
// CHECK: [[INIT:%[0-9]+]] = function_ref @_TF4libga8MyGlobalSi
// CHECK: {{^bb2:}}
// CHECK-NEXT: apply [[INIT]]()
// CHECK: {{^bb4:}}
// CHECK-NEXT: apply [[INIT]]()
sil @test_availability_common_dominator : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
%f1 = function_ref @test_availability : $@convention(thin) () -> Builtin.Int1
%f2 = function_ref @_TF4libga8MyGlobalSi : $@convention(thin) () -> Builtin.RawPointer
cond_br %0, bb1, bb3
bb1:
%a1 = apply %f1() : $@convention(thin) () -> Builtin.Int1
cond_br %a1, bb2, bb5
bb2:
%a2 = apply %f2() : $@convention(thin) () -> Builtin.RawPointer
br bb5
bb3:
%a3 = apply %f1() : $@convention(thin) () -> Builtin.Int1
cond_br %0, bb4, bb5
bb4:
%a4 = apply %f2() : $@convention(thin) () -> Builtin.RawPointer
br bb5
bb5:
%r = tuple ()
return %r : $()
}
sil [_semantics "availability.test"] @test_availability : $@convention(thin) () -> Builtin.Int1