| // 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' |