Files
swift-mirror/test/SILOptimizer/devirt_release.sil

218 lines
5.9 KiB
Plaintext

// Legacy passes are tested with the Windows PR tests. So no need to test them on macOS/Linux
// (they don't run on these platforms anyway). Thus we don't test both new Swift and legacy passes
// on the same platform at the same time.
// RUN: %target-sil-opt -enable-sil-verify-all %s -release-devirtualizer -module-name=test | %FileCheck %s
// REQUIRES: swift_in_compiler
sil_stage canonical
import Builtin
import Swift
class B {
@_hasStorage var next: B
}
struct Str {
@_hasStorage var b: B
}
// CHECK-LABEL: sil @devirtualize_object
// CHECK: [[A:%[0-9]+]] = alloc_ref
// CHECK-NEXT: set_deallocating [[A]]
// CHECK-NOT: strong_release
// CHECK: [[D:%[0-9]+]] = function_ref @$s4test1BCfD
// CHECK-NEXT: apply [[D]]([[A]])
// CHECK-NEXT: dealloc_stack_ref [[A]]
// CHECK: } // end sil function 'devirtualize_object'
sil @devirtualize_object : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
strong_release %1 : $B
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_heap_allocated
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK-NEXT: dealloc_ref
// CHECK: return
// CHECK: } // end sil function 'dont_devirtualize_heap_allocated'
sil @dont_devirtualize_heap_allocated : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref $B
strong_release %1 : $B
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_devirtualized
// CHECK: alloc_ref
// CHECK-NEXT: strong_retain
// CHECK-NEXT: strong_release
// CHECK-NEXT: set_deallocating
// CHECK-NEXT: dealloc_ref
// CHECK-NEXT: dealloc_stack_ref
// CHECK-NEXT: tuple
// CHECK: } // end sil function 'dont_devirtualize_devirtualized'
sil @dont_devirtualize_devirtualized : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
strong_retain %1 : $B
strong_release %1 : $B
set_deallocating %1 : $B
dealloc_ref %1 : $B
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_wrong_release
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK-NEXT: strong_release
// CHECK-NEXT: dealloc_ref
// CHECK: return
// CHECK: } // end sil function 'dont_devirtualize_wrong_release'
sil @dont_devirtualize_wrong_release : $@convention(thin) (@owned B) -> () {
bb0(%0 : $B):
%1 = alloc_ref $B
strong_release %1 : $B
strong_release %0 : $B
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_unknown_release
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK: [[F:%[0-9]+]] = function_ref @unknown_func
// CHECK-NEXT: apply [[F]]()
// CHECK-NEXT: dealloc_ref
// CHECK: } // end sil function 'dont_devirtualize_unknown_release'
sil @dont_devirtualize_unknown_release : $@convention(thin) (@owned B) -> () {
bb0(%0 : $B):
%1 = alloc_ref $B
strong_release %1 : $B
%f = function_ref @unknown_func : $@convention(thin) () -> ()
%a = apply %f() : $@convention(thin) () -> ()
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_crash_with_missing_release
// CHECK: [[A:%[0-9]+]] = alloc_ref
// CHECK-NEXT: set_deallocating [[A]]
// CHECK-NOT: strong_release
// CHECK: [[D:%[0-9]+]] = function_ref @$s4test1BCfD
// CHECK-NEXT: apply [[D]]([[A]])
// CHECK-NEXT: dealloc_stack_ref [[A]]
// CHECK: } // end sil function 'dont_crash_with_missing_release'
sil @dont_crash_with_missing_release : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
strong_release %1 : $B
dealloc_stack_ref %1 : $B
%2 = alloc_ref [stack] $B
dealloc_stack_ref %2 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @long_chain_from_alloc_to_release
// CHECK: set_deallocating
// CHECK-NOT: release_value
// CHECK: } // end sil function 'long_chain_from_alloc_to_release'
sil @long_chain_from_alloc_to_release : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
%2 = struct $Str(%1 : $B)
%3 = struct_extract %2 : $Str, #Str.b
cond_br undef, bb1, bb2
bb1:
br bb3(%3 : $B)
bb2:
br bb3(%3 : $B)
bb3(%a : $B):
%s = struct $Str (%a : $B)
%i = integer_literal $Builtin.Int64, 0
%t = tuple (%s : $Str, %i : $Builtin.Int64)
%o = enum $Optional<(Str, Builtin.Int64)>, #Optional.some!enumelt, %t : $(Str, Builtin.Int64)
release_value %o : $Optional<(Str, Builtin.Int64)>
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_double_release
// CHECK-NOT: set_deallocating
// CHECK: release_value
// CHECK: } // end sil function 'dont_devirtualize_double_release'
sil @dont_devirtualize_double_release : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
%t = tuple (%1 : $B, %1 : $B)
release_value %t : $(B, B)
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_release_of_load
// CHECK-NOT: set_deallocating
// CHECK: strong_release
// CHECK: } // end sil function 'dont_devirtualize_release_of_load'
sil @dont_devirtualize_release_of_load : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
%2 = ref_element_addr %1 : $B, #B.next
%3 = load %2 : $*B
strong_release %3 : $B
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_release_of_different_allocations
// CHECK-NOT: set_deallocating
// CHECK: strong_release
// CHECK: } // end sil function 'dont_devirtualize_release_of_different_allocations'
sil @dont_devirtualize_release_of_different_allocations : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
%2 = alloc_ref [stack] $B
cond_br undef, bb1, bb2
bb1:
br bb3(%1 : $B)
bb2:
br bb3(%2 : $B)
bb3(%a : $B):
strong_release %a : $B
dealloc_stack_ref %2 : $B
dealloc_stack_ref %1 : $B
%r = tuple ()
return %r : $()
}
sil @unknown_func : $@convention(thin) () -> ()
sil @$s4test1BCfD : $@convention(method) (@owned B) -> ()
sil_vtable B {
#B.deinit!deallocator: @$s4test1BCfD
}