mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Global initializers are executed only once. Therefore it's possible to hoist such an initializer call to a loop pre-header - in case there are no conflicting side-effects in the loop before the call. Also, the call must post-dominate the loop pre-header. Otherwise it would be executed speculatively.
311 lines
8.0 KiB
Plaintext
311 lines
8.0 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -licm | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
sil @unknown : $@convention(thin) () -> ()
|
|
|
|
sil @read_from_param : $@convention(thin) (@inout Int64, Int64) -> Int64 {
|
|
bb0(%0 : $*Int64, %1 : $Int64):
|
|
debug_value %1 : $Int64
|
|
%3 = struct_element_addr %0 : $*Int64, #Int64._value
|
|
%4 = load %3 : $*Builtin.Int64
|
|
return %1 : $Int64
|
|
}
|
|
|
|
//CHECK-LABEL: sil @licm_readonly_apply
|
|
//CHECK: [[V1:%[0-9]+]] = load
|
|
//CHECK: %{{[0-9]+}} = apply
|
|
//CHECK: br bb1([[V1]] : $Int64)
|
|
//CHECK: bb1({{.*}} : $Int64):
|
|
//CHECK-NOT: {{ apply}}
|
|
//CHECK-NOT: load
|
|
//CHECK-NOT: store
|
|
//CHECK: bb2:
|
|
//CHECK: store
|
|
//CHECK: return
|
|
sil @licm_readonly_apply : $@convention(thin) (Int64, @inout Int64) -> () {
|
|
bb0(%0 : $Int64, %1 : $*Int64):
|
|
%2 = alloc_stack $Int64
|
|
store %0 to %2 : $*Int64
|
|
%9 = function_ref @read_from_param : $@convention(thin) (@inout Int64, Int64) -> Int64
|
|
%10 = integer_literal $Builtin.Int64, 3
|
|
%11 = struct $Int64 (%10 : $Builtin.Int64)
|
|
%12 = struct_element_addr %1 : $*Int64, #Int64._value
|
|
%13 = integer_literal $Builtin.Int1, -1
|
|
br bb1
|
|
|
|
bb1:
|
|
%21 = apply %9(%2, %11) : $@convention(thin) (@inout Int64, Int64) -> Int64
|
|
%22 = load %12 : $*Builtin.Int64
|
|
%23 = struct_extract %21 : $Int64, #Int64._value
|
|
%24 = builtin "sadd_with_overflow_Int64"(%22 : $Builtin.Int64, %23 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%25 = tuple_extract %24 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%28 = struct $Int64 (%25 : $Builtin.Int64)
|
|
|
|
// This store does _not_ alias with the read in @read_from_param
|
|
store %28 to %1 : $*Int64
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
dealloc_stack %2 : $*Int64
|
|
return %15 : $()
|
|
}
|
|
|
|
//CHECK-LABEL: sil @dont_licm_readonly_apply
|
|
//CHECK: bb1:
|
|
//CHECK: %{{[0-9]+}} = apply
|
|
//CHECK: return
|
|
sil @dont_licm_readonly_apply : $@convention(thin) (Int64, @inout Int64) -> () {
|
|
bb0(%0 : $Int64, %1 : $*Int64):
|
|
%2 = alloc_stack $Int64
|
|
store %0 to %2 : $*Int64
|
|
%9 = function_ref @read_from_param : $@convention(thin) (@inout Int64, Int64) -> Int64
|
|
%10 = integer_literal $Builtin.Int64, 3
|
|
%11 = struct $Int64 (%10 : $Builtin.Int64)
|
|
%12 = struct_element_addr %1 : $*Int64, #Int64._value
|
|
%13 = integer_literal $Builtin.Int1, -1
|
|
br bb1
|
|
|
|
bb1:
|
|
%21 = apply %9(%2, %11) : $@convention(thin) (@inout Int64, Int64) -> Int64
|
|
%22 = load %12 : $*Builtin.Int64
|
|
%23 = struct_extract %21 : $Int64, #Int64._value
|
|
%24 = builtin "sadd_with_overflow_Int64"(%22 : $Builtin.Int64, %23 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%25 = tuple_extract %24 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%28 = struct $Int64 (%25 : $Builtin.Int64)
|
|
|
|
// This store does alias with the read in @read_from_param
|
|
store %28 to %2 : $*Int64
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
dealloc_stack %2 : $*Int64
|
|
return %15 : $()
|
|
}
|
|
|
|
class X {
|
|
}
|
|
|
|
sil_global @_static_object : $X
|
|
|
|
sil @retain_only : $@convention(thin) () -> @owned X {
|
|
bb0:
|
|
%1 = global_addr @_static_object : $*X
|
|
%2 = address_to_pointer %1 : $*X to $Builtin.RawPointer
|
|
%3 = raw_pointer_to_ref %2 : $Builtin.RawPointer to $X
|
|
strong_retain %3 : $X
|
|
return %3 : $X
|
|
}
|
|
|
|
//CHECK-LABEL: sil @dont_licm_retainonly_apply
|
|
//CHECK: bb1:
|
|
//CHECK: %{{[0-9]+}} = apply
|
|
//CHECK: return
|
|
sil @dont_licm_retainonly_apply : $@convention(thin) (Int64, @inout Int64) -> () {
|
|
bb0(%0 : $Int64, %1 : $*Int64):
|
|
%9 = function_ref @retain_only : $@convention(thin) () -> @owned X
|
|
br bb1
|
|
|
|
bb1:
|
|
%21 = apply %9() : $@convention(thin) () -> @owned X
|
|
strong_release %21 : $X
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
sil [global_init] @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
|
|
// CHECK-LABEL: sil @licm_global_init
|
|
// CHECK: apply
|
|
// CHECK: bb1:
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'licm_global_init'
|
|
sil @licm_global_init : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @dont_licm_ginit_prehead_not_pdom
|
|
// CHECK-NOT: apply
|
|
// CHECK: bb1:
|
|
// CHECK: apply
|
|
// CHECK: bb2:
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'dont_licm_ginit_prehead_not_pdom'
|
|
sil @dont_licm_ginit_prehead_not_pdom : $@convention(thin) () -> () {
|
|
bb0:
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @licm_ginit_complex_cfg
|
|
// CHECK-NOT: apply
|
|
// CHECK: bb0:
|
|
// CHECK: apply
|
|
// CHECK: bb1:
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'licm_ginit_complex_cfg'
|
|
sil @licm_ginit_complex_cfg : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
cond_br undef, bb1, bb5
|
|
|
|
bb5:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @dont_licm_ginit_apply_not_pdom
|
|
// CHECK-NOT: apply
|
|
// CHECK: bb2:
|
|
// CHECK: apply
|
|
// CHECK: bb3:
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'dont_licm_ginit_apply_not_pdom'
|
|
sil @dont_licm_ginit_apply_not_pdom : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
cond_br undef, bb1, bb5
|
|
|
|
bb5:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @dont_licm_ginit_dependency1
|
|
// CHECK: bb0:
|
|
// CHECK: [[I:%[0-9]+]] = function_ref @$s4test10testGlobalSivau
|
|
// CHECK: bb2:
|
|
// CHECK: [[U:%[0-9]+]] = function_ref @unknown
|
|
// CHECK: apply [[U]]
|
|
// CHECK: bb4:
|
|
// CHECK: apply [[I]]
|
|
// CHECK: bb5:
|
|
// CHECK: } // end sil function 'dont_licm_ginit_dependency1'
|
|
sil @dont_licm_ginit_dependency1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
%f = function_ref @unknown : $@convention(thin) () -> ()
|
|
%a = apply %f() : $@convention(thin) () -> ()
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
cond_br undef, bb1, bb5
|
|
|
|
bb5:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @dont_licm_ginit_dependency2
|
|
// CHECK: bb0:
|
|
// CHECK-DAG: [[I:%[0-9]+]] = function_ref @$s4test10testGlobalSivau
|
|
// CHECK-DAG: [[U:%[0-9]+]] = function_ref @unknown
|
|
// CHECK: bb1:
|
|
// CHECK: apply [[U]]
|
|
// CHECK: apply [[I]]
|
|
// CHECK: bb2:
|
|
// CHECK: } // end sil function 'dont_licm_ginit_dependency2'
|
|
sil @dont_licm_ginit_dependency2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
%f = function_ref @unknown : $@convention(thin) () -> ()
|
|
%a = apply %f() : $@convention(thin) () -> ()
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @licm_ginit_no_dependency
|
|
// CHECK: bb0:
|
|
// CHECK-DAG: [[I:%[0-9]+]] = function_ref @$s4test10testGlobalSivau
|
|
// CHECK-DAG: [[U:%[0-9]+]] = function_ref @unknown
|
|
// CHECK-DAG: apply [[I]]
|
|
// CHECK: bb1:
|
|
// CHECK: apply [[U]]
|
|
// CHECK: bb2:
|
|
// CHECK: } // end sil function 'licm_ginit_no_dependency'
|
|
sil @licm_ginit_no_dependency : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
%f = function_ref @unknown : $@convention(thin) () -> ()
|
|
%a = apply %f() : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb2:
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|