mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
196 lines
9.9 KiB
Plaintext
196 lines
9.9 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -allocbox-to-stack -enable-copy-propagation=requested-passes-only | %FileCheck %s
|
|
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
struct NonTrivialStruct: ~Copyable {
|
|
var i: Builtin.Int32
|
|
}
|
|
|
|
sil @use_nontrivialstruct : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
sil @consume_nontrivialstruct : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
sil @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
|
|
|
|
sil [ossa] @host_markmustcheck_closure : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> () {
|
|
bb0(%0 : @closureCapture @guaranteed ${ var NonTrivialStruct }):
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @hoist_markmustcheck : $@convention(thin) (@owned NonTrivialStruct) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @owned
|
|
// CHECK-NEXT: [[STACK1:%.*]] = alloc_stack $NonTrivialStruct
|
|
// CHECK-NEXT: [[MARKED1:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[STACK1]]
|
|
// CHECK-NEXT: store [[ARG]] to [init] [[MARKED1]]
|
|
// CHECK-NEXT: [[LOADED_VALUE:%.*]] = load [take] [[MARKED1]]
|
|
// CHECK-NEXT: [[STACK2:%.*]] = alloc_stack $NonTrivialStruct
|
|
// CHECK-NEXT: [[MARKED2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[STACK2]]
|
|
// CHECK-NEXT: store [[LOADED_VALUE]] to [init] [[MARKED2]]
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[FUNC:%.*]] = function_ref @$s26host_markmustcheck_closureTf0s_n : $@convention(thin) (@inout_aliasable NonTrivialStruct) -> ()
|
|
// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FUNC]]([[MARKED2]]) : $@convention(thin) (@inout_aliasable NonTrivialStruct) -> ()
|
|
// CHECK-NEXT: apply [[PA]]()
|
|
// CHECK-NEXT: destroy_value [[PA]]
|
|
// CHECK-NEXT: destroy_addr [[MARKED2]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK2]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK1]]
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'hoist_markmustcheck'
|
|
sil [ossa] @hoist_markmustcheck : $@convention(thin) (@owned NonTrivialStruct) -> () {
|
|
bb0(%0 : @owned $NonTrivialStruct):
|
|
%1 = alloc_box ${ var NonTrivialStruct }
|
|
%2 = project_box %1 : ${ var NonTrivialStruct }, 0
|
|
store %0 to [init] %2 : $*NonTrivialStruct
|
|
|
|
%3 = project_box %1 : ${ var NonTrivialStruct }, 0
|
|
%3a = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %3 : $*NonTrivialStruct
|
|
%3b = load [take] %3a : $*NonTrivialStruct
|
|
|
|
%4 = alloc_box ${ var NonTrivialStruct }
|
|
%4a = project_box %4 : ${ var NonTrivialStruct }, 0
|
|
%4b = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %4a : $*NonTrivialStruct
|
|
store %3b to [init] %4b : $*NonTrivialStruct
|
|
|
|
%f = function_ref @host_markmustcheck_closure : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> ()
|
|
%5c = copy_value %4 : ${ var NonTrivialStruct }
|
|
%g = partial_apply [callee_guaranteed] %f(%5c) : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> ()
|
|
apply %g() : $@callee_guaranteed () -> ()
|
|
|
|
destroy_value %g : $@callee_guaranteed () -> ()
|
|
destroy_value %4 : ${ var NonTrivialStruct }
|
|
dealloc_box %1 : ${ var NonTrivialStruct }
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// MARK: Test that we properly handle let alloc_box.
|
|
//
|
|
// CHECK-LABEL: sil hidden [ossa] @captured_let_allocstack_caller : $@convention(thin) () -> () {
|
|
// CHECK: bb0:
|
|
// CHECK: [[STACK:%.*]] = alloc_stack
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[STACK]]
|
|
// CHECK: partial_apply [callee_guaranteed] {{%.*}}([[MARK]]) : $@convention(thin) (@inout_aliasable NonTrivialStruct) -> ()
|
|
// CHECK: } // end sil function 'captured_let_allocstack_caller'
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s31captured_let_allocstack_closureTf0s_n : $@convention(thin) (@inout_aliasable NonTrivialStruct) -> () {
|
|
// CHECK: // [[ARG:.*]]{{ .*}}// user: [[MARK:%[0-9][0-9]*]]
|
|
// CHECK: bb0([[ARG]] : @closureCapture $*NonTrivialStruct):
|
|
// CHECK: [[MARK]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ARG]]
|
|
// CHECK: [[LOAD:%.*]] = load [copy] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = move_value [[LOAD]]
|
|
// CHECK: destroy_value [[VALUE]]
|
|
// CHECK: [[LOAD:%.*]] = load [copy] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = move_value [[LOAD]]
|
|
// CHECK: destroy_value [[VALUE]]
|
|
// CHECK: cond_br undef, [[LHS:bb[0-9]+]], [[RHS:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[LHS]]:
|
|
// CHECK: [[VALUE:%.*]] = load [copy] [[MARK]]
|
|
// CHECK: apply {{%.*}}([[VALUE]]) : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
// CHECK: [[VALUE:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: apply {{%.*}}([[VALUE]]) : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
// CHECK: } // end sil function 'captured_let_allocstack_closure'
|
|
sil hidden [ossa] @captured_let_allocstack_caller : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_box ${ let NonTrivialStruct }, let, name "x"
|
|
%2 = function_ref @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
|
|
%3 = apply %2() : $@convention(thin) () -> @owned NonTrivialStruct
|
|
%4 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
store %3 to [init] %4 : $*NonTrivialStruct
|
|
%6 = function_ref @captured_let_allocstack_closure : $@convention(thin) (@guaranteed { let NonTrivialStruct }) -> ()
|
|
%7 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%8 = copy_value %0 : ${ let NonTrivialStruct }
|
|
mark_function_escape %7 : $*NonTrivialStruct
|
|
%10 = partial_apply [callee_guaranteed] %6(%8) : $@convention(thin) (@guaranteed { let NonTrivialStruct }) -> ()
|
|
%11 = begin_borrow [lexical] %10 : $@callee_guaranteed () -> ()
|
|
debug_value %11 : $@callee_guaranteed () -> (), let, name "f"
|
|
%13 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%13a = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %13 : $*NonTrivialStruct
|
|
%14 = load_borrow %13a : $*NonTrivialStruct
|
|
%15 = function_ref @use_nontrivialstruct : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
%16 = apply %15(%14) : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
end_borrow %14 : $NonTrivialStruct
|
|
%18 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%18a = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %18 : $*NonTrivialStruct
|
|
%19 = load [copy] %18a : $*NonTrivialStruct
|
|
%20 = function_ref @consume_nontrivialstruct : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
%21 = apply %20(%19) : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
end_borrow %11 : $@callee_guaranteed () -> ()
|
|
destroy_value %10 : $@callee_guaranteed () -> ()
|
|
destroy_value %0 : ${ let NonTrivialStruct }
|
|
%25 = tuple ()
|
|
return %25 : $()
|
|
}
|
|
|
|
sil private [ossa] @captured_let_allocstack_closure : $@convention(thin) (@guaranteed { let NonTrivialStruct }) -> () {
|
|
bb0(%0 : @closureCapture @guaranteed ${ let NonTrivialStruct }):
|
|
%1 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%2 = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %1 : $*NonTrivialStruct
|
|
%3 = load [copy] %2 : $*NonTrivialStruct
|
|
%4 = move_value %3 : $NonTrivialStruct
|
|
destroy_value %4 : $NonTrivialStruct
|
|
%6 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%7 = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %6 : $*NonTrivialStruct
|
|
%8 = load [copy] %7 : $*NonTrivialStruct
|
|
%9 = move_value %8 : $NonTrivialStruct
|
|
destroy_value %9 : $NonTrivialStruct
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%17 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%18 = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %17 : $*NonTrivialStruct
|
|
%19 = load [copy] %18 : $*NonTrivialStruct
|
|
%20 = function_ref @consume_nontrivialstruct : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
%21 = apply %20(%19) : $@convention(thin) (@owned NonTrivialStruct) -> ()
|
|
%22 = project_box %0 : ${ let NonTrivialStruct }, 0
|
|
%23 = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %22 : $*NonTrivialStruct
|
|
%24 = load_borrow %23 : $*NonTrivialStruct
|
|
%25 = function_ref @use_nontrivialstruct : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
%26 = apply %25(%24) : $@convention(thin) (@guaranteed NonTrivialStruct) -> ()
|
|
end_borrow %24 : $NonTrivialStruct
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%30 = tuple ()
|
|
return %30 : $()
|
|
}
|
|
|
|
// CHECK: sil hidden [ossa] @earlyallocbox_to_stack_partial_apply_test_caller : $@convention(thin) (@owned NonTrivialStruct) -> () {
|
|
// CHECK: alloc_stack [lexical] $NonTrivialStruct, var, name "x"
|
|
// CHECK: } // end sil function 'earlyallocbox_to_stack_partial_apply_test_caller'
|
|
sil hidden [ossa] @earlyallocbox_to_stack_partial_apply_test_caller : $@convention(thin) (@owned NonTrivialStruct) -> () {
|
|
bb0(%arg : @owned $NonTrivialStruct):
|
|
%0 = alloc_box ${ var NonTrivialStruct }, var, name "x"
|
|
%1 = begin_borrow [lexical] %0 : ${ var NonTrivialStruct }
|
|
%2 = project_box %1 : ${ var NonTrivialStruct }, 0
|
|
store %arg to [init] %2 : $*NonTrivialStruct
|
|
%15 = function_ref @earlyallocbox_to_stack_partial_apply_test_callee : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> ()
|
|
%16 = copy_value %1 : ${ var NonTrivialStruct }
|
|
%18 = partial_apply [callee_guaranteed] %15(%16) : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> ()
|
|
destroy_value %18 : $@callee_guaranteed () -> ()
|
|
end_borrow %1 : ${ var NonTrivialStruct }
|
|
destroy_value %0 : ${ var NonTrivialStruct }
|
|
%24 = tuple ()
|
|
return %24 : $()
|
|
}
|
|
|
|
sil private [ossa] @earlyallocbox_to_stack_partial_apply_test_callee : $@convention(thin) (@guaranteed { var NonTrivialStruct }) -> () {
|
|
bb0(%0 : @closureCapture @guaranteed ${ var NonTrivialStruct }):
|
|
%1 = project_box %0 : ${ var NonTrivialStruct }, 0
|
|
debug_value %1 : $*NonTrivialStruct, var, name "x", argno 1, expr op_deref
|
|
%3 = begin_access [read] [unknown] %1 : $*NonTrivialStruct
|
|
%4 = mark_unresolved_non_copyable_value [no_consume_or_assign] %3 : $*NonTrivialStruct
|
|
%5 = load [copy] %4 : $*NonTrivialStruct
|
|
end_access %3 : $*NonTrivialStruct
|
|
%7 = move_value %5 : $NonTrivialStruct
|
|
destroy_value %7 : $NonTrivialStruct
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|