mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
283 lines
6.7 KiB
Plaintext
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 : $()
|
|
}
|