Files
swift-mirror/test/SILOptimizer/allocstack_hoisting.sil
2022-11-30 17:25:53 -08:00

283 lines
6.7 KiB
Plaintext

// RUN: %target-sil-opt -enable-sil-verify-all %s -alloc-stack-hoisting | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all %s -alloc-stack-hoisting -sil-merge-stack-slots=false | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
import SwiftShims
protocol P {
}
struct Generic<T> {
var x : T
}
struct FixedSize {
var x : Builtin.Int8
}
// CHECK-LABEL: sil @hoist_generic
// CHECK: bb0({{.*}}):
// CHECK: [[AS:%.*]] = alloc_stack $T
// CHECK: bb1:
// CHECK-NOT: alloc_stack
// CHECK-NOT: dealloc_stack
// CHECK: bb2
// CHECK: bb3:
// CHECK: dealloc_stack [[AS]]
// CHECK: return
sil @hoist_generic : $@convention(thin) <T> (@in T, Builtin.Int1) -> () {
bb0(%0 : $*T, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = alloc_stack $T
copy_addr [take] %0 to [init] %2 : $*T
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
%3 = tuple ()
return %3 : $()
}
sil @throwing_fun : $@convention(thin) () -> @error any Error
// CHECK-LABEL: sil @hoist_generic
// CHECK: bb0({{.*}}):
// CHECK: [[AS:%.*]] = alloc_stack $T
// CHECK: bb1:
// CHECK-NOT: alloc_stack
// CHECK-NOT: dealloc_stack
// CHECK: bb2
// CHECK: bb3:
// CHECK: try_apply
// CHECK: bb4({{.*}}:
// CHECK: dealloc_stack [[AS]]
// CHECK: return
// CHECK: bb5({{.*}}):
// CHECK: dealloc_stack [[AS]]
// CHECK: throw
sil @hoist_generic_throwing : $@convention(thin) <T> (@in T, Builtin.Int1) -> @error any Error {
bb0(%0 : $*T, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = alloc_stack $T
copy_addr [take] %0 to [init] %2 : $*T
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
%3 = function_ref @throwing_fun : $@convention(thin) () -> @error any Error
try_apply %3() : $@convention(thin) () -> @error any Error, normal bb4, error bb5
bb4(%6: $()):
%4 = tuple ()
return %4 : $()
bb5(%5: $Error):
throw %5: $Error
}
// CHECK-LABEL: sil @hoist_generic
// CHECK: bb0({{.*}}):
// CHECK: [[AS:%.*]] = alloc_stack $Generic<T>
// CHECK: bb1:
// CHECK-NOT: alloc_stack
// CHECK-NOT: dealloc_stack
// CHECK: bb2
// CHECK: bb3:
// CHECK: dealloc_stack [[AS]]
// CHECK: return
sil @hoist_generic_type : $@convention(thin) <T> (@in Generic<T>, Builtin.Int1) -> () {
bb0(%0 : $*Generic<T>, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = alloc_stack $Generic<T>
copy_addr [take] %0 to [init] %2 : $*Generic<T>
destroy_addr %2 : $*Generic<T>
dealloc_stack %2 : $*Generic<T>
br bb3
bb2:
destroy_addr %0 : $*Generic<T>
br bb3
bb3:
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil @hoist_generic_nesting
// CHECK: bb0({{.*}}):
// CHECK: [[AS:%.*]] = alloc_stack $T
// CHECK: [[AS2:%.*]] = alloc_stack $T
// CHECK: [[FIXED:%.*]] = alloc_stack $FixedSize
// CHECK: bb1:
// CHECK-NOT: alloc_stack
// CHECK-NOT: dealloc_stack
// CHECK: bb2
// CHECK: bb3:
// CHECK: dealloc_stack [[FIXED]]
// CHECK: dealloc_stack [[AS2]]
// CHECK: dealloc_stack [[AS]]
// CHECK: return
sil @hoist_generic_nesting : $@convention(thin) <T> (@in T, Builtin.Int1) -> () {
bb0(%0 : $*T, %1: $Builtin.Int1):
%2 = alloc_stack $FixedSize
cond_br %1, bb1, bb2
bb1:
%3 = alloc_stack $T
%4 = alloc_stack $T
copy_addr [take] %0 to [init] %3 : $*T
destroy_addr %3 : $*T
dealloc_stack %4: $*T
dealloc_stack %3 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
dealloc_stack %2: $*FixedSize
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil @dont_hoist_opened_generic
// CHECK: bb0({{.*}}):
// CHECK-NOT: alloc_stack
// CHECK: bb1:
// CHECK: alloc_stack
// CHECK: bb2:
// CHECK: bb3:
// CHECK-NOT: dealloc_stack
// CHECK: return
sil @dont_hoist_opened_generic : $@convention(thin) (@in P, Builtin.Int1) -> () {
bb0(%0 : $*P, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = open_existential_addr mutable_access %0 : $*P to $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60", P) Self
%3 = alloc_stack $@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60", P) Self
copy_addr [take] %2 to [init] %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60", P) Self
destroy_addr %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60", P) Self
dealloc_stack %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60", P) Self
br bb3
bb2:
destroy_addr %0 : $*P
br bb3
bb3:
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: sil @dont_hoist_protocol
// CHECK: bb0({{.*}}):
// CHECK-NOT: alloc_stack
// CHECK: bb1:
// CHECK: alloc_stack
// CHECK: bb2:
// CHECK: bb3:
// CHECK-NOT: dealloc_stack
// CHECK: return
sil @dont_hoist_protocol : $@convention(thin) (@in P, Builtin.Int1) -> () {
bb0(%0 : $*P, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = alloc_stack $P
copy_addr [take] %0 to [init] %2 : $*P
destroy_addr %2 : $*P
dealloc_stack %2 : $*P
br bb3
bb2:
destroy_addr %0 : $*P
br bb3
bb3:
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil @dont_crash_on_unreachable
// CHECK: bb0({{.*}}):
// CHECK: alloc_stack
// CHECK: bb1:
// CHECK-NOT: alloc_stack
// CHECK: bb2:
// CHECK: bb3:
// CHECK: unreachable
sil @dont_crash_on_unreachable : $@convention(thin) <T> (@in T, Builtin.Int1) -> Never {
bb0(%0 : $*T, %1: $Builtin.Int1):
cond_br %1, bb1, bb2
bb1:
%2 = alloc_stack $T
copy_addr [take] %0 to [init] %2 : $*T
destroy_addr %2 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
%3 = builtin "int_trap"() : $()
unreachable
}
// CHECK-LABEL: sil @dont_hoist_with_availability_checks
// CHECK-NOT: alloc_stack
// CHECK: cond_br
// CHECK: bb1:
// CHECK: alloc_stack
// CHECK: } // end sil function 'dont_hoist_with_availability_checks'
sil @dont_hoist_with_availability_checks : $@convention(thin) <T> (@in T, Builtin.Int1) -> () {
bb0(%0 : $*T, %1: $Builtin.Int1):
%5 = integer_literal $Builtin.Int32, 15
%7 = builtin "targetOSVersionAtLeast"(%5 : $Builtin.Int32, %5 : $Builtin.Int32, %5 : $Builtin.Int32) : $Builtin.Int32
%8 = builtin "cmp_eq_Int32"(%7 : $Builtin.Int32, %5 : $Builtin.Int32) : $Builtin.Int1
cond_br %8, bb1, bb2
bb1:
%2 = alloc_stack $T
copy_addr [take] %0 to [init] %2 : $*T
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil @dont_hoist_with_has_symbol_checks
// CHECK-NOT: alloc_stack
// CHECK: cond_br
// CHECK: bb1:
// CHECK: alloc_stack
// CHECK: } // end sil function 'dont_hoist_with_has_symbol_checks'
sil @dont_hoist_with_has_symbol_checks : $@convention(thin) <T> (@in T, Builtin.Int1) -> () {
bb0(%0 : $*T, %1: $Builtin.Int1):
%5 = has_symbol #FixedSize.init
cond_br %5, bb1, bb2
bb1:
%2 = alloc_stack $T
copy_addr [take] %0 to [init] %2 : $*T
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
br bb3
bb2:
destroy_addr %0 : $*T
br bb3
bb3:
%3 = tuple ()
return %3 : $()
}