mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The intent for `@inline(always)` is to act as an optimization control. The user can rely on inlining to happen or the compiler will emit an error message. Because function values can be dynamic (closures, protocol/class lookup) this guarantee can only be upheld for direct function references. In cases where the optimizer can resolve dynamic function values the attribute shall be respected. rdar://148608854
309 lines
12 KiB
Plaintext
309 lines
12 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all -inline %s | %FileCheck %s
|
|
|
|
// Check cloning of instructions.
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
|
|
class X {
|
|
}
|
|
|
|
sil [always_inline] @callee_alloc_ref_stack : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_ref [stack] $X
|
|
dealloc_stack_ref %0 : $X
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @caller_alloc_ref_stack : $@convention(thin) () -> ()
|
|
// CHECK: [[X:%[0-9]+]] = alloc_ref [stack] $X
|
|
// CHECK: dealloc_stack_ref [[X]] : $X
|
|
sil @caller_alloc_ref_stack : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @callee_alloc_ref_stack : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
sil [ossa] [always_inline] @callee_begin_borrow : $@convention(thin) () -> () {
|
|
%instance = alloc_ref $X
|
|
%guaranteed_c = begin_borrow [lexical] %instance : $X
|
|
end_borrow %guaranteed_c : $X
|
|
%guaranteed_c2 = begin_borrow [pointer_escape] %instance : $X
|
|
end_borrow %guaranteed_c2 : $X
|
|
%guaranteed_c3 = begin_borrow [var_decl] %instance : $X
|
|
end_borrow %guaranteed_c3 : $X
|
|
destroy_value %instance : $X
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_begin_borrow_lexical
|
|
// CHECK: begin_borrow [lexical]
|
|
// CHECK: begin_borrow [pointer_escape]
|
|
// CHECK: begin_borrow [var_decl]
|
|
// CHECK-LABEL: } // end sil function 'caller_begin_borrow_lexical'
|
|
sil [ossa] @caller_begin_borrow_lexical : $@convention(thin) () -> () {
|
|
%callee_begin_borrow_lexical = function_ref @callee_begin_borrow : $@convention(thin) () -> ()
|
|
%res = apply %callee_begin_borrow_lexical() : $@convention(thin) () -> ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [ossa] [always_inline] @callee_alloc_box : $@convention(thin) () -> () {
|
|
%b1 = alloc_box ${ var X }
|
|
dealloc_box %b1 : ${ var X }
|
|
%b2 = alloc_box [dynamic_lifetime] ${ var X }
|
|
dealloc_box %b2 : ${ var X }
|
|
%b3 = alloc_box [reflection] ${ var X }
|
|
dealloc_box %b3 : ${ var X }
|
|
%b4 = alloc_box [pointer_escape] ${ var X }
|
|
dealloc_box %b4 : ${ var X }
|
|
%b5 = alloc_box [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b5 : ${ var X }
|
|
%b6 = alloc_box [dynamic_lifetime] [reflection] ${ var X }
|
|
dealloc_box %b6 : ${ var X }
|
|
%b7 = alloc_box [dynamic_lifetime] [pointer_escape] ${ var X }
|
|
dealloc_box %b7 : ${ var X }
|
|
%b8 = alloc_box [dynamic_lifetime] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b8 : ${ var X }
|
|
%b9 = alloc_box [reflection] [pointer_escape] ${ var X }
|
|
dealloc_box %b9 : ${ var X }
|
|
%b10 = alloc_box [reflection] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b10 : ${ var X }
|
|
%b11 = alloc_box [pointer_escape] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b11 : ${ var X }
|
|
%b12 = alloc_box [reflection] [pointer_escape] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b12 : ${ var X }
|
|
%b13 = alloc_box [dynamic_lifetime] [pointer_escape] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b13 : ${ var X }
|
|
%b14 = alloc_box [dynamic_lifetime] [reflection] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b14 : ${ var X }
|
|
%b15 = alloc_box [dynamic_lifetime] [reflection] [pointer_escape] ${ var X }
|
|
dealloc_box %b15 : ${ var X }
|
|
%b16 = alloc_box [dynamic_lifetime] [reflection] [pointer_escape] [moveable_value_debuginfo] ${ var X }
|
|
dealloc_box %b16 : ${ var X }
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_alloc_box{{.*}} {
|
|
// CHECK: alloc_box
|
|
// CHECK: alloc_box [dynamic_lifetime]
|
|
// CHECK: alloc_box [reflection]
|
|
// CHECK: alloc_box [pointer_escape]
|
|
// CHECK: alloc_box [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [dynamic_lifetime] [reflection]
|
|
// CHECK: alloc_box [dynamic_lifetime] [pointer_escape]
|
|
// CHECK: alloc_box [dynamic_lifetime] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [reflection] [pointer_escape]
|
|
// CHECK: alloc_box [reflection] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [pointer_escape] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [reflection] [pointer_escape] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [dynamic_lifetime] [pointer_escape] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [dynamic_lifetime] [reflection] [moveable_value_debuginfo]
|
|
// CHECK: alloc_box [dynamic_lifetime] [reflection] [pointer_escape]
|
|
// CHECK: alloc_box [dynamic_lifetime] [reflection] [pointer_escape] [moveable_value_debuginfo]
|
|
// CHECK-LABEL: } // end sil function 'caller_alloc_box'
|
|
sil [ossa] @caller_alloc_box : $@convention(thin) () -> () {
|
|
%callee = function_ref @callee_alloc_box : $@convention(thin) () -> ()
|
|
%res = apply %callee() : $@convention(thin) () -> ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [ossa] @callee_alloc_stack : $@convention(thin) () -> () {
|
|
%instance = alloc_stack $Builtin.NativeObject
|
|
dealloc_stack %instance : $*Builtin.NativeObject
|
|
%instance2 = alloc_stack [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance2 : $*Builtin.NativeObject
|
|
%instance3 = alloc_stack [lexical] $Builtin.NativeObject
|
|
dealloc_stack %instance3 : $*Builtin.NativeObject
|
|
%instance5 = alloc_stack [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance5 : $*Builtin.NativeObject
|
|
%instance4 = alloc_stack [lexical] [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance4 : $*Builtin.NativeObject
|
|
%instance6 = alloc_stack [dynamic_lifetime] [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance6 : $*Builtin.NativeObject
|
|
%instance7 = alloc_stack [lexical] [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance7 : $*Builtin.NativeObject
|
|
%instance8 = alloc_stack [lexical] [var_decl] [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance8 : $*Builtin.NativeObject
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_alloc_stack_lexical
|
|
// CHECK: alloc_stack
|
|
// CHECK: alloc_stack [dynamic_lifetime]
|
|
// CHECK: alloc_stack [lexical]
|
|
// CHECK: alloc_stack [var_decl]
|
|
// CHECK: alloc_stack [dynamic_lifetime] [lexical]
|
|
// CHECK: alloc_stack [dynamic_lifetime] [var_decl]
|
|
// CHECK: alloc_stack [lexical] [var_decl]
|
|
// CHECK: alloc_stack [dynamic_lifetime] [lexical] [var_decl]
|
|
// CHECK-LABEL: } // end sil function 'caller_alloc_stack_lexical'
|
|
sil [ossa] @caller_alloc_stack_lexical : $@convention(thin) () -> () {
|
|
%callee_alloc_stack = function_ref @callee_alloc_stack : $@convention(thin) () -> ()
|
|
%res = apply %callee_alloc_stack() : $@convention(thin) () -> ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [ossa] @callee_move_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
entry(%0 : @owned $Builtin.NativeObject):
|
|
%1 = move_value %0 : $Builtin.NativeObject
|
|
%2 = move_value [allows_diagnostics] %1 : $Builtin.NativeObject
|
|
%3 = move_value [lexical] %2 : $Builtin.NativeObject
|
|
%4 = move_value [allows_diagnostics] [lexical] %3 : $Builtin.NativeObject
|
|
%5 = move_value [pointer_escape] %4 : $Builtin.NativeObject
|
|
%6 = move_value [var_decl] %5 : $Builtin.NativeObject
|
|
return %6 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_move_value {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[REGISTER_0:%[^,]+]] :
|
|
// CHECK: [[REGISTER_1:%[^,]+]] = move_value [[REGISTER_0]]
|
|
// CHECK: [[REGISTER_2:%[^,]+]] = move_value [allows_diagnostics] [[REGISTER_1]]
|
|
// CHECK: [[REGISTER_3:%[^,]+]] = move_value [lexical] [[REGISTER_2]]
|
|
// CHECK: [[REGISTER_4:%[^,]+]] = move_value [allows_diagnostics] [lexical] [[REGISTER_3]]
|
|
// CHECK: [[REGISTER_5:%[^,]+]] = move_value [pointer_escape] [[REGISTER_4]]
|
|
// CHECK: [[REGISTER_6:%[^,]+]] = move_value [var_decl] [[REGISTER_5]]
|
|
// CHECK: return [[REGISTER_6]]
|
|
// CHECK-LABEL: } // end sil function 'caller_move_value'
|
|
sil [ossa] @caller_move_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
entry(%0 : @owned $Builtin.NativeObject):
|
|
%callee_move_value = function_ref @callee_move_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%res = apply %callee_move_value(%0) : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
return %res : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] @callee_debug_value : $@convention(thin) (@owned X) -> @owned X {
|
|
entry(%0 : @owned $X):
|
|
debug_value [trace] %0 : $X
|
|
return %0 : $X
|
|
}
|
|
|
|
sil [ossa] @caller_debug_value : $@convention(thin) (@owned X) -> @owned X {
|
|
entry(%0 : @owned $X):
|
|
%callee_debug_value = function_ref @callee_debug_value : $@convention(thin) (@owned X) -> @owned X
|
|
%res = apply %callee_debug_value(%0) : $@convention(thin) (@owned X) -> @owned X
|
|
return %res : $X
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_specify_test : {{.*}} {
|
|
// CHECK: specify_test "foo bar baz"
|
|
// CHECK-LABEL: } // end sil function 'caller_specify_test'
|
|
sil [always_inline] [ossa] @callee_specify_test : $@convention(thin) () -> () {
|
|
entry:
|
|
specify_test "foo bar baz"
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
sil [ossa] @caller_specify_test : $@convention(thin) () -> () {
|
|
%callee = function_ref @callee_specify_test : $@convention(thin) () -> ()
|
|
%retval = apply %callee() : $@convention(thin) () -> ()
|
|
return %retval : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_extend_lifetime : {{.*}} {
|
|
// CHECK: bb0([[O:%[^,]+]] :
|
|
// CHECK: extend_lifetime [[O]]
|
|
// CHECK-LABEL: } // end sil function 'caller_extend_lifetime'
|
|
sil [always_inline] [ossa] @callee_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
entry(%o : @owned $Builtin.NativeObject):
|
|
br loop
|
|
loop:
|
|
extend_lifetime %o : $Builtin.NativeObject
|
|
br loop
|
|
}
|
|
|
|
sil [ossa] @caller_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
entry(%o : @owned $Builtin.NativeObject):
|
|
%callee = function_ref @callee_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%retval = apply %callee(%o) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
return %retval : $()
|
|
}
|
|
|
|
sil [ossa] [always_inline] @callee_destroy_value : $@convention(thin) (@owned X) -> () {
|
|
entry(%x : @owned $X):
|
|
cond_br undef, good, bad
|
|
good:
|
|
cond_br undef, gleft, gright
|
|
gleft:
|
|
destroy_value %x : $X
|
|
br exit
|
|
gright:
|
|
destroy_value [poison] %x : $X
|
|
br exit
|
|
exit:
|
|
%retval = tuple()
|
|
return %retval : $()
|
|
bad:
|
|
cond_br undef, bleft, bright
|
|
bleft:
|
|
destroy_value [dead_end] %x : $X
|
|
unreachable
|
|
bright:
|
|
destroy_value [poison] [dead_end] %x : $X
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_destroy_value : {{.*}} {
|
|
// CHECK: destroy_value
|
|
// CHECK: destroy_value [poison]
|
|
// CHECK: destroy_value [dead_end]
|
|
// CHECK: destroy_value [poison] [dead_end]
|
|
// CHECK-LABEL: } // end sil function 'caller_destroy_value'
|
|
sil [ossa] @caller_destroy_value : $@convention(thin) (@owned X) -> () {
|
|
entry(%x : @owned $X):
|
|
%callee = function_ref @callee_destroy_value : $@convention(thin) (@owned X) -> ()
|
|
%res = apply %callee(%x) : $@convention(thin) (@owned X) -> ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [ossa] [always_inline] @callee_dealloc_box : $@convention(thin) () -> () {
|
|
entry:
|
|
%b = alloc_box ${ var X }
|
|
cond_br undef, exit, die
|
|
|
|
exit:
|
|
dealloc_box %b : ${ var X }
|
|
%retval = tuple()
|
|
return %retval : $()
|
|
|
|
die:
|
|
dealloc_box [dead_end] %b : ${ var X }
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @caller_dealloc_box : {{.*}} {
|
|
// CHECK: dealloc_box
|
|
// CHECK: dealloc_box [dead_end]
|
|
// CHECK-LABEL: } // end sil function 'caller_dealloc_box'
|
|
sil [ossa] @caller_dealloc_box : $@convention(thin) () -> () {
|
|
entry:
|
|
%callee = function_ref @callee_dealloc_box : $@convention(thin) () -> ()
|
|
%res = apply %callee() : $@convention(thin) () -> ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @getSize : $@convention(thin) <Type> (@thick Type.Type) -> Builtin.Word {
|
|
bb0(%ty : $@thick Type.Type):
|
|
%size = builtin "sizeof"<Type>() : $Builtin.Word
|
|
return %size : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @callee_builtin_type_dep_operand : {{.*}} {
|
|
// CHECK: open_existential_metatype
|
|
// CHECK-LABEL: } // end sil function 'callee_builtin_type_dep_operand'
|
|
sil [ossa] @callee_builtin_type_dep_operand : $@convention(thin) (@thick any Any.Type) -> Builtin.Word {
|
|
bb0(%0 : $@thick any Any.Type):
|
|
%ty = open_existential_metatype %0 : $@thick any Any.Type to $@thick (@opened("00000000-0000-0000-0000-000000000000", Any) Self).Type
|
|
%getSize = function_ref @getSize : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Builtin.Word
|
|
%retval = apply %getSize<@opened("00000000-0000-0000-0000-000000000000", Any) Self>(%ty) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Builtin.Word
|
|
return %retval : $Builtin.Word
|
|
}
|