mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
268 lines
10 KiB
Plaintext
268 lines
10 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -predictable-deadalloc-elim | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Swift
|
|
import Builtin
|
|
|
|
// CHECK-LABEL: sil @simple_trivial_stack : $@convention(thin) (Builtin.Int32) -> () {
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: } // end sil function 'simple_trivial_stack'
|
|
sil @simple_trivial_stack : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = alloc_stack $Builtin.Int32
|
|
store %0 to %1 : $*Builtin.Int32
|
|
dealloc_stack %1 : $*Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simple_trivial_init_box : $@convention(thin) (Builtin.Int32) -> () {
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: } // end sil function 'simple_trivial_init_box'
|
|
sil @simple_trivial_init_box : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = alloc_box ${ var Builtin.Int32 }
|
|
%2 = project_box %1 : ${ var Builtin.Int32 }, 0
|
|
store %0 to %2 : $*Builtin.Int32
|
|
strong_release %1 : ${ var Builtin.Int32 }
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simple_trivial_uninit_box : $@convention(thin) (Builtin.Int32) -> () {
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: } // end sil function 'simple_trivial_uninit_box'
|
|
sil @simple_trivial_uninit_box : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = alloc_box ${ var Builtin.Int32 }
|
|
%2 = project_box %1 : ${ var Builtin.Int32 }, 0
|
|
store %0 to %2 : $*Builtin.Int32
|
|
dealloc_box %1 : ${ var Builtin.Int32 }
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simple_nontrivial_stack : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NEXT: strong_release [[ARG]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'simple_nontrivial_stack'
|
|
sil @simple_nontrivial_stack : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %1 : $*Builtin.NativeObject
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We do not handle this today, since we do not understand that we need to treat
|
|
// the strong_release of the alloc_box as a destroy_addr of the entire value.
|
|
//
|
|
// FIXME: We should be able to handle this.
|
|
//
|
|
// CHECK-LABEL: sil @simple_nontrivial_init_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_box
|
|
// CHECK: } // end sil function 'simple_nontrivial_init_box'
|
|
sil @simple_nontrivial_init_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject):
|
|
%1 = alloc_box ${ var Builtin.NativeObject }
|
|
%2 = project_box %1 : ${ var Builtin.NativeObject }, 0
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
strong_release %1 : ${ var Builtin.NativeObject }
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simple_nontrivial_uninit_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NEXT: strong_release [[ARG]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'simple_nontrivial_uninit_box'
|
|
sil @simple_nontrivial_uninit_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject):
|
|
%1 = alloc_box ${ var Builtin.NativeObject }
|
|
%2 = project_box %1 : ${ var Builtin.NativeObject }, 0
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_box %1 : ${ var Builtin.NativeObject }
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
//////////////////
|
|
// Assign Tests //
|
|
//////////////////
|
|
|
|
// Make sure that we do eliminate this allocation
|
|
// CHECK-LABEL: sil @simple_assign_take_trivial : $@convention(thin) (Builtin.Int32, @in Builtin.Int32) -> () {
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: } // end sil function 'simple_assign_take_trivial'
|
|
sil @simple_assign_take_trivial : $@convention(thin) (Builtin.Int32, @in Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32, %1 : $*Builtin.Int32):
|
|
%2 = alloc_stack $Builtin.Int32
|
|
store %0 to %2 : $*Builtin.Int32
|
|
copy_addr [take] %1 to %2 : $*Builtin.Int32
|
|
dealloc_stack %2 : $*Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// In this case, we perform an init, copy. Since we do not want to lose the +1
|
|
// on the argument, we do not eliminate this (even though with time perhaps we
|
|
// could).
|
|
// CHECK-LABEL: sil @simple_init_copy : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_stack
|
|
// CHECK: copy_addr
|
|
// CHECK: } // end sil function 'simple_init_copy'
|
|
sil @simple_init_copy : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
copy_addr %1 to [initialization] %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// This we can promote successfully.
|
|
// CHECK-LABEL: sil @simple_init_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $*Builtin.NativeObject):
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: strong_release [[ARG0]]
|
|
// CHECK: [[ARG1_LOADED:%.*]] = load [[ARG1]]
|
|
// CHECK: strong_release [[ARG1_LOADED]]
|
|
// CHECK: } // end sil function 'simple_init_take'
|
|
sil @simple_init_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
copy_addr [take] %1 to [initialization] %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Since we are copying the input argument, we can not get rid of the copy_addr,
|
|
// meaning we shouldn't eliminate the allocation here.
|
|
// CHECK-LABEL: sil @simple_assign_no_take : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_stack
|
|
// CHECK: copy_addr
|
|
// CHECK: } // end sil function 'simple_assign_no_take'
|
|
sil @simple_assign_no_take : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
copy_addr %1 to %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// If PMO understood how to promote assigns, we should be able to handle this
|
|
// case.
|
|
// CHECK-LABEL: sil @simple_assign_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_stack
|
|
// CHECK: copy_addr
|
|
// CHECK: } // end sil function 'simple_assign_take'
|
|
sil @simple_assign_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
copy_addr [take] %1 to %2 : $*Builtin.NativeObject
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @simple_diamond_without_assign : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK-NOT: store
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: strong_release [[ARG]]
|
|
// CHECK: } // end sil function 'simple_diamond_without_assign'
|
|
sil @simple_diamond_without_assign : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %1 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We should not promote this due to this being an assign to %2.
|
|
// CHECK-LABEL: sil @simple_diamond_with_assign : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_stack
|
|
// CHECK: copy_addr
|
|
// CHECK: } // end sil function 'simple_diamond_with_assign'
|
|
sil @simple_diamond_with_assign : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
copy_addr [take] %1 to %2 : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Today PMO can not handle different available values coming from different
|
|
// BBs. With time it can be taught to do that if necessary. That being said,
|
|
// this test shows that we /tried/ and failed with the available value test
|
|
// instead of failing earlier due to the copy_addr being an assign since we
|
|
// explode the copy_addr.
|
|
// CHECK-LABEL: sil @simple_diamond_with_assign_remove : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
// CHECK: alloc_stack
|
|
// CHECK-NOT: copy_addr
|
|
// CHECK: } // end sil function 'simple_diamond_with_assign_remove'
|
|
sil @simple_diamond_with_assign_remove : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
|
|
%2 = alloc_stack $Builtin.NativeObject
|
|
store %0 to %2 : $*Builtin.NativeObject
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
copy_addr [take] %1 to [initialization] %2 : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_addr %2 : $*Builtin.NativeObject
|
|
dealloc_stack %2 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|