blob: e54a119105a8023e1f73418696aa766ac3f3266a [file] [log] [blame]
// RUN: %target-swift-emit-sil %s -verify
// REQUIRES: asserts
// TF-1039: Cloned curry thunks generated by differentiation should create a
// `differentiable_function` instruction before any `dealloc_stack` instructions
// to prevent `alloc_stack`/`dealloc_stack` ordering issues.
protocol P {
@differentiable
func foo(_ x: Float) -> Float
}
struct S: P {
@differentiable
func foo(_ x: Float) -> Float { x }
}
func foo<T: P>(_ x: T) {
// Curry thunk emitted here for `x.foo`.
_ = gradient(at: 1, in: x.foo)
}
// SIL verification failed: stack dealloc does not match most recent stack alloc: op == state.Stack.back()
// Verifying instruction:
// %2 = alloc_stack $τ_0_0 // users: %7, %5, %9, %8, %3
// -> dealloc_stack %2 : $*τ_0_0 // id: %9
// In function:
// // AD__$s5curry1PP3fooyS2fFTc__differentiable_curry_thunk_src_0_wrt_0
// sil shared [thunk] @AD__$s5curry1PP3fooyS2fFTc__differentiable_curry_thunk_src_0_wrt_0 : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @differentiable @callee_guaranteed (Float) -> Float {
// // %0 // user: %3
// bb0(%0 : $*τ_0_0):
// %1 = witness_method $τ_0_0, #P.foo!1 : <Self where Self : P> (Self) -> (Float) -> Float : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> Float // user: %8
// %2 = alloc_stack $τ_0_0 // users: %7, %5, %9, %8, %3
// copy_addr %0 to [initialization] %2 : $*τ_0_0 // id: %3
// %4 = alloc_stack $τ_0_0 // users: %15, %11, %5
// copy_addr %2 to [initialization] %4 : $*τ_0_0 // id: %5
// %6 = alloc_stack $τ_0_0 // users: %14, %13, %7
// copy_addr %2 to [initialization] %6 : $*τ_0_0 // id: %7
// %8 = partial_apply [callee_guaranteed] %1<τ_0_0>(%2) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> Float // user: %16
// dealloc_stack %2 : $*τ_0_0 // id: %9
// %10 = witness_method $τ_0_0, #P.foo!1.jvp.SU : <Self where Self : P> (Self) -> (Float) -> Float : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> (Float, @owned @callee_guaranteed (Float) -> Float) // user: %11
// %11 = partial_apply [callee_guaranteed] %10<τ_0_0>(%4) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> (Float, @owned @callee_guaranteed (Float) -> Float) // user: %16
// %12 = witness_method $τ_0_0, #P.foo!1.vjp.SU : <Self where Self : P> (Self) -> (Float) -> Float : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> (Float, @owned @callee_guaranteed (Float) -> Float) // user: %13
// %13 = partial_apply [callee_guaranteed] %12<τ_0_0>(%6) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (Float, @in_guaranteed τ_0_0) -> (Float, @owned @callee_guaranteed (Float) -> Float) // user: %16
// dealloc_stack %6 : $*τ_0_0 // id: %14
// dealloc_stack %4 : $*τ_0_0 // id: %15
// %16 = differentiable_function [parameters 0] %8 : $@callee_guaranteed (Float) -> Float with_derivative {%11 : $@callee_guaranteed (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float), %13 : $@callee_guaranteed (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float)} // user: %17
// return %16 : $@differentiable @callee_guaranteed (Float) -> Float // id: %17
// } // end sil function 'AD__$s5curry1PP3fooyS2fFTc__differentiable_curry_thunk_src_0_wrt_0'