Files
swift-mirror/test/SILOptimizer/allocbox_to_stack_noncopyable.sil
2024-07-23 11:05:33 -07:00

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 : $()
}