The red - lines are produced by direct references to Tensor.dfoo, which doesn't crash.
The green + lines are produced by #adjoint(Tensor.foo), which does crashes.
| diff --git a/a1.sil b/a2.sil | |
| index 30ad601..7d92e01 100644 | |
| --- a/a1.sil | |
| +++ b/a2.sil | |
| @@ -1,128 +1,142 @@ | |
| sil_stage raw | |
| import Builtin | |
| import Swift | |
| import SwiftShims | |
| import TensorFlow | |
| extension Tensor where Scalar : Numeric, Scalar : AccelerableByTensorFlow { | |
| @differentiable(reverse, adjoint: dfoo) | |
| static func foo(_ x: Tensor<Scalar>) -> Tensor<Scalar> | |
| static func dfoo(_ x: Tensor<Scalar>, originalValue: Tensor<Scalar>, seed: Tensor<Scalar>) -> Tensor<Scalar> | |
| } | |
| let x: Tensor<Float> | |
| // x | |
| sil_global hidden [let] @$S7crasher1x10TensorFlow0B0VySfGvp : $Tensor<Float> | |
| // main | |
| sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { | |
| bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): | |
| alloc_global @$S7crasher1x10TensorFlow0B0VySfGvp // id: %2 | |
| - %3 = global_addr @$S7crasher1x10TensorFlow0B0VySfGvp : $*Tensor<Float> // users: %34, %33, %32, %29, %28, %27, %14 | |
| + %3 = global_addr @$S7crasher1x10TensorFlow0B0VySfGvp : $*Tensor<Float> // users: %37, %36, %35, %31, %30, %29, %14 | |
| %4 = metatype $@thin Tensor<Float>.Type // user: %12 | |
| %5 = metatype $@thin Float.Type // user: %8 | |
| %6 = integer_literal $Builtin.Int2048, 1 // user: %8 | |
| // function_ref Float.init(_builtinIntegerLiteral:) | |
| %7 = function_ref @$SSf22_builtinIntegerLiteralSfBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Float.Type) -> Float // user: %8 | |
| %8 = apply %7(%6, %5) : $@convention(method) (Builtin.Int2048, @thin Float.Type) -> Float // user: %10 | |
| %9 = alloc_stack $Float // users: %13, %12, %10 | |
| store %8 to [trivial] %9 : $*Float // id: %10 | |
| // function_ref Tensor.init(_:) | |
| %11 = function_ref @$S10TensorFlow0A0VyACyxGxcfC : $@convention(method) <τ_0_0 where τ_0_0 : AccelerableByTensorFlow> (@in τ_0_0, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %12 | |
| %12 = apply %11<Float>(%9, %4) : $@convention(method) <τ_0_0 where τ_0_0 : AccelerableByTensorFlow> (@in τ_0_0, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %14 | |
| dealloc_stack %9 : $*Float // id: %13 | |
| store %12 to [init] %3 : $*Tensor<Float> // id: %14 | |
| %15 = integer_literal $Builtin.Word, 1 // user: %17 | |
| // function_ref _allocateUninitializedArray<A>(_:) | |
| %16 = function_ref @$Ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %17 | |
| %17 = apply %16<Any>(%15) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // users: %23, %22, %18 | |
| %18 = begin_borrow %17 : $(Array<Any>, Builtin.RawPointer) // users: %22, %21, %19 | |
| %19 = tuple_extract %18 : $(Array<Any>, Builtin.RawPointer), 0 // user: %20 | |
| - %20 = copy_value %19 : $Array<Any> // users: %44, %41 | |
| + %20 = copy_value %19 : $Array<Any> // users: %48, %44 | |
| %21 = tuple_extract %18 : $(Array<Any>, Builtin.RawPointer), 1 // user: %24 | |
| end_borrow %18 from %17 : $(Array<Any>, Builtin.RawPointer), $(Array<Any>, Builtin.RawPointer) // id: %22 | |
| destroy_value %17 : $(Array<Any>, Builtin.RawPointer) // id: %23 | |
| %24 = pointer_to_address %21 : $Builtin.RawPointer to [strict] $*Any // user: %25 | |
| - %25 = init_existential_addr %24 : $*Any, $Tensor<Float> // user: %35 | |
| - %26 = metatype $@thin Tensor<Float>.Type // user: %31 | |
| - %27 = load_borrow %3 : $*Tensor<Float> // users: %34, %31 | |
| - %28 = load_borrow %3 : $*Tensor<Float> // users: %33, %31 | |
| - %29 = load_borrow %3 : $*Tensor<Float> // users: %32, %31 | |
| - // function_ref static Tensor<>.dfoo(_:originalValue:seed:) | |
| - %30 = function_ref @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZ : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %31 | |
| - %31 = apply %30<Float>(%27, %28, %29, %26) : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %35 | |
| - end_borrow %29 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %32 | |
| - end_borrow %28 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %33 | |
| - end_borrow %27 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %34 | |
| - store %31 to [init] %25 : $*Tensor<Float> // id: %35 | |
| + %25 = init_existential_addr %24 : $*Any, $Tensor<Float> // user: %38 | |
| + // function_ref curry thunk of static Tensor<>.dfoo(_:originalValue:seed:) | |
| + %26 = function_ref @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZTc : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@thin Tensor<τ_0_0>.Type) -> @owned @callee_guaranteed (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>) -> @owned Tensor<τ_0_0> // user: %28 | |
| + %27 = metatype $@thin Tensor<Float>.Type // user: %28 | |
| + %28 = apply %26<Float>(%27) : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@thin Tensor<τ_0_0>.Type) -> @owned @callee_guaranteed (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>) -> @owned Tensor<τ_0_0> // users: %47, %34, %32 | |
| + %29 = load_borrow %3 : $*Tensor<Float> // users: %37, %33 | |
| + %30 = load_borrow %3 : $*Tensor<Float> // users: %36, %33 | |
| + %31 = load_borrow %3 : $*Tensor<Float> // users: %35, %33 | |
| + %32 = begin_borrow %28 : $@callee_guaranteed (@guaranteed Tensor<Float>, @guaranteed Tensor<Float>, @guaranteed Tensor<Float>) -> @owned Tensor<Float> // users: %34, %33 | |
| + %33 = apply %32(%29, %30, %31) : $@callee_guaranteed (@guaranteed Tensor<Float>, @guaranteed Tensor<Float>, @guaranteed Tensor<Float>) -> @owned Tensor<Float> // user: %38 | |
| + end_borrow %32 from %28 : $@callee_guaranteed (@guaranteed Tensor<Float>, @guaranteed Tensor<Float>, @guaranteed Tensor<Float>) -> @owned Tensor<Float>, $@callee_guaranteed (@guaranteed Tensor<Float>, @guaranteed Tensor<Float>, @guaranteed Tensor<Float>) -> @owned Tensor<Float> // id: %34 | |
| + end_borrow %31 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %35 | |
| + end_borrow %30 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %36 | |
| + end_borrow %29 from %3 : $Tensor<Float>, $*Tensor<Float> // id: %37 | |
| + store %33 to [init] %25 : $*Tensor<Float> // id: %38 | |
| // function_ref default argument 1 of print(_:separator:terminator:) | |
| - %36 = function_ref @$Ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %37 | |
| - %37 = apply %36() : $@convention(thin) () -> @owned String // users: %43, %41 | |
| + %39 = function_ref @$Ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %40 | |
| + %40 = apply %39() : $@convention(thin) () -> @owned String // users: %46, %44 | |
| // function_ref default argument 2 of print(_:separator:terminator:) | |
| - %38 = function_ref @$Ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %39 | |
| - %39 = apply %38() : $@convention(thin) () -> @owned String // users: %42, %41 | |
| + %41 = function_ref @$Ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %42 | |
| + %42 = apply %41() : $@convention(thin) () -> @owned String // users: %45, %44 | |
| // function_ref print(_:separator:terminator:) | |
| - %40 = function_ref @$Ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %41 | |
| - %41 = apply %40(%20, %37, %39) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () | |
| - destroy_value %39 : $String // id: %42 | |
| - destroy_value %37 : $String // id: %43 | |
| - destroy_value %20 : $Array<Any> // id: %44 | |
| - %45 = integer_literal $Builtin.Int32, 0 // user: %46 | |
| - %46 = struct $Int32 (%45 : $Builtin.Int32) // user: %47 | |
| - return %46 : $Int32 // id: %47 | |
| + %43 = function_ref @$Ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %44 | |
| + %44 = apply %43(%20, %40, %42) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () | |
| + destroy_value %42 : $String // id: %45 | |
| + destroy_value %40 : $String // id: %46 | |
| + destroy_value %28 : $@callee_guaranteed (@guaranteed Tensor<Float>, @guaranteed Tensor<Float>, @guaranteed Tensor<Float>) -> @owned Tensor<Float> // id: %47 | |
| + destroy_value %20 : $Array<Any> // id: %48 | |
| + %49 = integer_literal $Builtin.Int32, 0 // user: %50 | |
| + %50 = struct $Int32 (%49 : $Builtin.Int32) // user: %51 | |
| + return %50 : $Int32 // id: %51 | |
| } // end sil function 'main' | |
| // static Tensor<>.foo(_:) | |
| sil hidden [reverse_differentiable source 0 wrt 0 primal @$S10TensorFlow0A0V7crashers7NumericRzrlE3fooyACyxGAGFZ adjoint @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZ] @$S10TensorFlow0A0V7crashers7NumericRzrlE3fooyACyxGAGFZ : $@convention(method) <Scalar where Scalar : Numeric, Scalar : AccelerableByTensorFlow> (@guaranteed Tensor<Scalar>, @thin Tensor<Scalar>.Type) -> @owned Tensor<Scalar> { | |
| // %0 // users: %4, %2 | |
| // %1 // user: %3 | |
| bb0(%0 : $Tensor<Scalar>, %1 : $@thin Tensor<Scalar>.Type): | |
| debug_value %0 : $Tensor<Scalar>, let, name "x", argno 1 // id: %2 | |
| debug_value %1 : $@thin Tensor<Scalar>.Type, let, name "self", argno 2 // id: %3 | |
| %4 = copy_value %0 : $Tensor<Scalar> // user: %5 | |
| return %4 : $Tensor<Scalar> // id: %5 | |
| } // end sil function '$S10TensorFlow0A0V7crashers7NumericRzrlE3fooyACyxGAGFZ' | |
| // static Tensor<>.dfoo(_:originalValue:seed:) | |
| sil hidden @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZ : $@convention(method) <Scalar where Scalar : Numeric, Scalar : AccelerableByTensorFlow> (@guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>, @thin Tensor<Scalar>.Type) -> @owned Tensor<Scalar> { | |
| // %0 // users: %9, %4 | |
| // %1 // user: %5 | |
| // %2 // users: %9, %6 | |
| // %3 // user: %7 | |
| bb0(%0 : $Tensor<Scalar>, %1 : $Tensor<Scalar>, %2 : $Tensor<Scalar>, %3 : $@thin Tensor<Scalar>.Type): | |
| debug_value %0 : $Tensor<Scalar>, let, name "x", argno 1 // id: %4 | |
| debug_value %1 : $Tensor<Scalar>, let, name "originalValue", argno 2 // id: %5 | |
| debug_value %2 : $Tensor<Scalar>, let, name "seed", argno 3 // id: %6 | |
| debug_value %3 : $@thin Tensor<Scalar>.Type, let, name "self", argno 4 // id: %7 | |
| // function_ref Tensor<>.unbroadcast<A>(like:) | |
| %8 = function_ref @$S10TensorFlow0A0VAAs7NumericRzrlE11unbroadcast4likeACyxGACyqd__G_tAA013AccelerableByaB0Rd__lF : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow><τ_1_0 where τ_1_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_1_0>, @guaranteed Tensor<τ_0_0>) -> @owned Tensor<τ_0_0> // user: %9 | |
| %9 = apply %8<Scalar, Scalar>(%0, %2) : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow><τ_1_0 where τ_1_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_1_0>, @guaranteed Tensor<τ_0_0>) -> @owned Tensor<τ_0_0> // user: %10 | |
| return %9 : $Tensor<Scalar> // id: %10 | |
| } // end sil function '$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZ' | |
| // Tensor<>.unbroadcast<A>(like:) | |
| sil [serialized] [always_inline] @$S10TensorFlow0A0VAAs7NumericRzrlE11unbroadcast4likeACyxGACyqd__G_tAA013AccelerableByaB0Rd__lF : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow><τ_1_0 where τ_1_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_1_0>, @guaranteed Tensor<τ_0_0>) -> @owned Tensor<τ_0_0> | |
| // Float.init(_builtinIntegerLiteral:) | |
| sil [transparent] [serialized] @$SSf22_builtinIntegerLiteralSfBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Float.Type) -> Float | |
| // Tensor.init(_:) | |
| sil [serialized] [always_inline] @$S10TensorFlow0A0VyACyxGxcfC : $@convention(method) <τ_0_0 where τ_0_0 : AccelerableByTensorFlow> (@in τ_0_0, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> | |
| // _allocateUninitializedArray<A>(_:) | |
| sil [serialized] [always_inline] @$Ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) | |
| +// curry thunk of static Tensor<>.dfoo(_:originalValue:seed:) | |
| +sil shared [thunk] @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZTc : $@convention(thin) <Scalar where Scalar : Numeric, Scalar : AccelerableByTensorFlow> (@thin Tensor<Scalar>.Type) -> @owned @callee_guaranteed (@guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>) -> @owned Tensor<Scalar> { | |
| +// %0 // user: %2 | |
| +bb0(%0 : $@thin Tensor<Scalar>.Type): | |
| + // function_ref static Tensor<>.dfoo(_:originalValue:seed:) | |
| + %1 = function_ref @$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZ : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %2 | |
| + %2 = partial_apply [callee_guaranteed] %1<Scalar>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : Numeric, τ_0_0 : AccelerableByTensorFlow> (@guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @guaranteed Tensor<τ_0_0>, @thin Tensor<τ_0_0>.Type) -> @owned Tensor<τ_0_0> // user: %3 | |
| + return %2 : $@callee_guaranteed (@guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>, @guaranteed Tensor<Scalar>) -> @owned Tensor<Scalar> // id: %3 | |
| +} // end sil function '$S10TensorFlow0A0V7crashers7NumericRzrlE4dfoo_13originalValue4seedACyxGAI_A2ItFZTc' | |
| + | |
| // default argument 1 of print(_:separator:terminator:) | |
| sil [noinline] @$Ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String | |
| // default argument 2 of print(_:separator:terminator:) | |
| sil [noinline] @$Ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String | |
| // print(_:separator:terminator:) | |
| sil [noinline] @$Ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () |
| import TensorFlow | |
| extension Tensor where Scalar : Numeric { | |
| @differentiable(reverse, adjoint: dfoo) | |
| static func foo(_ x: Tensor) -> Tensor { | |
| return x | |
| } | |
| static func dfoo( | |
| _ x: Tensor, originalValue: Tensor, seed: Tensor | |
| ) -> Tensor { | |
| return seed.unbroadcast(like: x) | |
| } | |
| } | |
| let x = Tensor<Float>(1) | |
| // Line 1: This works. | |
| // print(Tensor<Float>.dfoo(x, originalValue: x, seed: x)) | |
| // Line 2: This crashes when uncommented. | |
| print(#adjoint(Tensor<Float>.foo)(x, originalValue: x, seed: x)) |