Skip to content

Instantly share code, notes, and snippets.

@rxwei
Last active January 22, 2019 11:15
Show Gist options
  • Save rxwei/5730d0e89985df09c5847795cc587c79 to your computer and use it in GitHub Desktop.
Save rxwei/5730d0e89985df09c5847795cc587c79 to your computer and use it in GitHub Desktop.
differentiating load/store
func f(x: Float) -> Float {
return x + x + x
}
print(pullback(at: 1, in: f)(2))
// AD__$s11sideeffects1f1xS2f_tF__adjoint_src_0_wrt_0
sil hidden @AD__$s11sideeffects1f1xS2f_tF__adjoint_src_0_wrt_0 : $@convention(thin) (Float, AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0, Float, Float) -> Float {
// %0 // user: %8
// %1 // users: %18, %4
bb0(%0 : $Float, %1 : $AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0, %2 : $Float, %3 : $Float):
%4 = struct_extract %1 : $AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0, #AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0.pullback_1 // user: %14
%5 = alloc_stack $Float // users: %15, %11, %6
%6 = begin_access [init] [static] [no_nested_conflict] %5 : $*Float // users: %10, %7
%7 = begin_access [init] [static] [no_nested_conflict] %6 : $*Float // users: %9, %8
store %0 to %7 : $*Float // id: %8
end_access %7 : $*Float // id: %9
end_access %6 : $*Float // id: %10
%11 = begin_access [read] [static] [no_nested_conflict] %5 : $*Float // users: %13, %12
%12 = load %11 : $*Float // user: %14
end_access %11 : $*Float // id: %13
%14 = apply %4(%12) : $@callee_guaranteed (Float) -> (Float, Float) // users: %17, %16
dealloc_stack %5 : $*Float // id: %15
%16 = tuple_extract %14 : $(Float, Float), 0 // user: %22
%17 = tuple_extract %14 : $(Float, Float), 1 // user: %37
%18 = struct_extract %1 : $AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0, #AD__$s11sideeffects1f1xS2f_tF__Type__src_0_wrt_0.pullback_0 // user: %28
%19 = alloc_stack $Float // users: %29, %25, %20
%20 = begin_access [init] [static] [no_nested_conflict] %19 : $*Float // users: %24, %21
%21 = begin_access [init] [static] [no_nested_conflict] %20 : $*Float // users: %23, %22
store %16 to %21 : $*Float // id: %22
end_access %21 : $*Float // id: %23
end_access %20 : $*Float // id: %24
%25 = begin_access [read] [static] [no_nested_conflict] %19 : $*Float // users: %27, %26
%26 = load %25 : $*Float // user: %28
end_access %25 : $*Float // id: %27
%28 = apply %18(%26) : $@callee_guaranteed (Float) -> (Float, Float) // users: %31, %30
dealloc_stack %19 : $*Float // id: %29
%30 = tuple_extract %28 : $(Float, Float), 0 // user: %38
%31 = tuple_extract %28 : $(Float, Float), 1 // user: %62
%32 = alloc_stack $Float // users: %55, %52, %41
%33 = alloc_stack $Float // users: %51, %42, %35
%34 = alloc_stack $Float // users: %50, %43, %36
%35 = begin_access [init] [static] [no_nested_conflict] %33 : $*Float // users: %39, %37
%36 = begin_access [init] [static] [no_nested_conflict] %34 : $*Float // users: %40, %38
store %17 to %35 : $*Float // id: %37
store %30 to %36 : $*Float // id: %38
end_access %35 : $*Float // id: %39
end_access %36 : $*Float // id: %40
%41 = begin_access [init] [static] [no_nested_conflict] %32 : $*Float // users: %47, %46
%42 = begin_access [read] [static] [no_nested_conflict] %33 : $*Float // users: %49, %46
%43 = begin_access [read] [static] [no_nested_conflict] %34 : $*Float // users: %48, %46
%44 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %46
%45 = metatype $@thick Float.Type // user: %46
%46 = apply %44<Float>(%41, %43, %42, %45) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %41 : $*Float // id: %47
end_access %43 : $*Float // id: %48
end_access %42 : $*Float // id: %49
dealloc_stack %34 : $*Float // id: %50
dealloc_stack %33 : $*Float // id: %51
%52 = begin_access [read] [static] [no_nested_conflict] %32 : $*Float // users: %54, %53
%53 = load %52 : $*Float // user: %61
end_access %52 : $*Float // id: %54
dealloc_stack %32 : $*Float // id: %55
%56 = alloc_stack $Float // users: %79, %76, %65
%57 = alloc_stack $Float // users: %75, %66, %59
%58 = alloc_stack $Float // users: %74, %67, %60
%59 = begin_access [init] [static] [no_nested_conflict] %57 : $*Float // users: %63, %61
%60 = begin_access [init] [static] [no_nested_conflict] %58 : $*Float // users: %64, %62
store %53 to %59 : $*Float // id: %61
store %31 to %60 : $*Float // id: %62
end_access %59 : $*Float // id: %63
end_access %60 : $*Float // id: %64
%65 = begin_access [init] [static] [no_nested_conflict] %56 : $*Float // users: %71, %70
%66 = begin_access [read] [static] [no_nested_conflict] %57 : $*Float // users: %73, %70
%67 = begin_access [read] [static] [no_nested_conflict] %58 : $*Float // users: %72, %70
%68 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %70
%69 = metatype $@thick Float.Type // user: %70
%70 = apply %68<Float>(%65, %67, %66, %69) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %65 : $*Float // id: %71
end_access %67 : $*Float // id: %72
end_access %66 : $*Float // id: %73
dealloc_stack %58 : $*Float // id: %74
dealloc_stack %57 : $*Float // id: %75
%76 = begin_access [read] [static] [no_nested_conflict] %56 : $*Float // users: %78, %77
%77 = load %76 : $*Float // user: %80
end_access %76 : $*Float // id: %78
dealloc_stack %56 : $*Float // id: %79
return %77 : $Float // id: %80
} // end sil function 'AD__$s11sideeffects1f1xS2f_tF__adjoint_src_0_wrt_0'
func foo(x: Float) -> Float {
var a = x
a = a + x
return a + x
}
// AD__$s11sideeffects3foo1xS2f_tF__primal_src_0_wrt_0
sil hidden @AD__$s11sideeffects3foo1xS2f_tF__primal_src_0_wrt_0 : $@convention(thin) (Float) -> (@owned AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, Float) {
// %0 // users: %20, %9, %3, %1
bb0(%0 : $Float):
debug_value %0 : $Float, let, name "x", argno 1 // id: %1
%2 = alloc_stack $Float // users: %23, %16, %12, %5, %3
store %0 to %2 : $*Float // id: %3
%4 = metatype $@thin Float.Type // user: %9
%5 = begin_access [read] [static] %2 : $*Float // users: %7, %6
%6 = load %5 : $*Float // user: %9
end_access %5 : $*Float // id: %7
// function_ref static Float._vjpAdd(lhs:rhs:)
%8 = function_ref @$sSf7_vjpAdd3lhs3rhsSf_Sf_SftSfctSf_SftFZ : $@convention(method) (Float, Float, @thin Float.Type) -> (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) // user: %9
%9 = apply %8(%6, %0, %4) : $@convention(method) (Float, Float, @thin Float.Type) -> (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) // users: %11, %10
%10 = tuple_extract %9 : $(Float, @callee_guaranteed (Float) -> (Float, Float)), 0 // user: %13
%11 = tuple_extract %9 : $(Float, @callee_guaranteed (Float) -> (Float, Float)), 1 // user: %24
%12 = begin_access [modify] [static] %2 : $*Float // users: %14, %13
store %10 to %12 : $*Float // id: %13
end_access %12 : $*Float // id: %14
%15 = metatype $@thin Float.Type // user: %20
%16 = begin_access [read] [static] %2 : $*Float // users: %18, %17
%17 = load %16 : $*Float // user: %20
end_access %16 : $*Float // id: %18
// function_ref static Float._vjpAdd(lhs:rhs:)
%19 = function_ref @$sSf7_vjpAdd3lhs3rhsSf_Sf_SftSfctSf_SftFZ : $@convention(method) (Float, Float, @thin Float.Type) -> (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) // user: %20
%20 = apply %19(%17, %0, %15) : $@convention(method) (Float, Float, @thin Float.Type) -> (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) // users: %22, %21
%21 = tuple_extract %20 : $(Float, @callee_guaranteed (Float) -> (Float, Float)), 0 // user: %25
%22 = tuple_extract %20 : $(Float, @callee_guaranteed (Float) -> (Float, Float)), 1 // user: %24
dealloc_stack %2 : $*Float // id: %23
%24 = struct $AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0 (%11 : $@callee_guaranteed (Float) -> (Float, Float), %22 : $@callee_guaranteed (Float) -> (Float, Float)) // user: %25
%25 = tuple (%24 : $AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, %21 : $Float) // user: %26
return %25 : $(AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, Float) // id: %26
} // end sil function 'AD__$s11sideeffects3foo1xS2f_tF__primal_src_0_wrt_0'
// AD__$s11sideeffects3foo1xS2f_tF__adjoint_src_0_wrt_0
sil hidden @AD__$s11sideeffects3foo1xS2f_tF__adjoint_src_0_wrt_0 : $@convention(thin) (Float, AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, Float, Float) -> Float {
// %0 // user: %9
// %1 // users: %45, %5
bb0(%0 : $Float, %1 : $AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, %2 : $Float, %3 : $Float):
%4 = alloc_stack $Float // users: %131, %106, %83, %42, %19
%5 = struct_extract %1 : $AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, #AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0.pullback_1 // user: %15
%6 = alloc_stack $Float // users: %16, %12, %7
%7 = begin_access [init] [static] [no_nested_conflict] %6 : $*Float // users: %11, %8
%8 = begin_access [init] [static] [no_nested_conflict] %7 : $*Float // users: %10, %9
store %0 to %8 : $*Float // id: %9
end_access %8 : $*Float // id: %10
end_access %7 : $*Float // id: %11
%12 = begin_access [read] [static] [no_nested_conflict] %6 : $*Float // users: %14, %13
%13 = load %12 : $*Float // user: %15
end_access %12 : $*Float // id: %14
%15 = apply %5(%13) : $@callee_guaranteed (Float) -> (Float, Float) // users: %18, %17
dealloc_stack %6 : $*Float // id: %16
%17 = tuple_extract %15 : $(Float, Float), 0 // user: %22
%18 = tuple_extract %15 : $(Float, Float), 1 // user: %64
%19 = begin_access [read] [static] %4 : $*Float // users: %41, %35, %26
%20 = alloc_stack $Float // users: %40, %21
%21 = begin_access [init] [static] [no_nested_conflict] %20 : $*Float // users: %27, %23, %22
store %17 to %21 : $*Float // id: %22
end_access %21 : $*Float // id: %23
%24 = alloc_stack $Float // users: %39, %34, %25
%25 = begin_access [init] [static] [no_nested_conflict] %24 : $*Float // users: %31, %30
%26 = begin_access [read] [static] [no_nested_conflict] %19 : $*Float // users: %33, %30
%27 = begin_access [read] [static] [no_nested_conflict] %21 : $*Float // users: %32, %30
%28 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %30
%29 = metatype $@thick Float.Type // user: %30
%30 = apply %28<Float>(%25, %27, %26, %29) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %25 : $*Float // id: %31
end_access %27 : $*Float // id: %32
end_access %26 : $*Float // id: %33
%34 = begin_access [read] [static] [no_nested_conflict] %24 : $*Float // users: %38, %36
%35 = begin_access [modify] [static] [no_nested_conflict] %19 : $*Float // users: %37, %36
copy_addr [take] %34 to %35 : $*Float // id: %36
end_access %35 : $*Float // id: %37
end_access %34 : $*Float // id: %38
dealloc_stack %24 : $*Float // id: %39
dealloc_stack %20 : $*Float // id: %40
end_access %19 : $*Float // id: %41
%42 = begin_access [modify] [static] %4 : $*Float // users: %44, %43
%43 = load %42 : $*Float // user: %49
end_access %42 : $*Float // id: %44
%45 = struct_extract %1 : $AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0, #AD__$s11sideeffects3foo1xS2f_tF__Type__src_0_wrt_0.pullback_0 // user: %55
%46 = alloc_stack $Float // users: %56, %52, %47
%47 = begin_access [init] [static] [no_nested_conflict] %46 : $*Float // users: %51, %48
%48 = begin_access [init] [static] [no_nested_conflict] %47 : $*Float // users: %50, %49
store %43 to %48 : $*Float // id: %49
end_access %48 : $*Float // id: %50
end_access %47 : $*Float // id: %51
%52 = begin_access [read] [static] [no_nested_conflict] %46 : $*Float // users: %54, %53
%53 = load %52 : $*Float // user: %55
end_access %52 : $*Float // id: %54
%55 = apply %45(%53) : $@callee_guaranteed (Float) -> (Float, Float) // users: %58, %57
dealloc_stack %46 : $*Float // id: %56
%57 = tuple_extract %55 : $(Float, Float), 0 // user: %86
%58 = tuple_extract %55 : $(Float, Float), 1 // user: %65
%59 = alloc_stack $Float // users: %82, %79, %68
%60 = alloc_stack $Float // users: %78, %69, %62
%61 = alloc_stack $Float // users: %77, %70, %63
%62 = begin_access [init] [static] [no_nested_conflict] %60 : $*Float // users: %66, %64
%63 = begin_access [init] [static] [no_nested_conflict] %61 : $*Float // users: %67, %65
store %18 to %62 : $*Float // id: %64
store %58 to %63 : $*Float // id: %65
end_access %62 : $*Float // id: %66
end_access %63 : $*Float // id: %67
%68 = begin_access [init] [static] [no_nested_conflict] %59 : $*Float // users: %74, %73
%69 = begin_access [read] [static] [no_nested_conflict] %60 : $*Float // users: %76, %73
%70 = begin_access [read] [static] [no_nested_conflict] %61 : $*Float // users: %75, %73
%71 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %73
%72 = metatype $@thick Float.Type // user: %73
%73 = apply %71<Float>(%68, %70, %69, %72) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %68 : $*Float // id: %74
end_access %70 : $*Float // id: %75
end_access %69 : $*Float // id: %76
dealloc_stack %61 : $*Float // id: %77
dealloc_stack %60 : $*Float // id: %78
%79 = begin_access [read] [static] [no_nested_conflict] %59 : $*Float // users: %81, %80
%80 = load %79 : $*Float // user: %112
end_access %79 : $*Float // id: %81
dealloc_stack %59 : $*Float // id: %82
%83 = begin_access [read] [static] %4 : $*Float // users: %105, %99, %90
%84 = alloc_stack $Float // users: %104, %85
%85 = begin_access [init] [static] [no_nested_conflict] %84 : $*Float // users: %91, %87, %86
store %57 to %85 : $*Float // id: %86
end_access %85 : $*Float // id: %87
%88 = alloc_stack $Float // users: %103, %98, %89
%89 = begin_access [init] [static] [no_nested_conflict] %88 : $*Float // users: %95, %94
%90 = begin_access [read] [static] [no_nested_conflict] %83 : $*Float // users: %97, %94
%91 = begin_access [read] [static] [no_nested_conflict] %85 : $*Float // users: %96, %94
%92 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %94
%93 = metatype $@thick Float.Type // user: %94
%94 = apply %92<Float>(%89, %91, %90, %93) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %89 : $*Float // id: %95
end_access %91 : $*Float // id: %96
end_access %90 : $*Float // id: %97
%98 = begin_access [read] [static] [no_nested_conflict] %88 : $*Float // users: %102, %100
%99 = begin_access [modify] [static] [no_nested_conflict] %83 : $*Float // users: %101, %100
copy_addr [take] %98 to %99 : $*Float // id: %100
end_access %99 : $*Float // id: %101
end_access %98 : $*Float // id: %102
dealloc_stack %88 : $*Float // id: %103
dealloc_stack %84 : $*Float // id: %104
end_access %83 : $*Float // id: %105
%106 = load %4 : $*Float // user: %113
%107 = alloc_stack $Float // users: %130, %127, %116
%108 = alloc_stack $Float // users: %126, %117, %110
%109 = alloc_stack $Float // users: %125, %118, %111
%110 = begin_access [init] [static] [no_nested_conflict] %108 : $*Float // users: %114, %112
%111 = begin_access [init] [static] [no_nested_conflict] %109 : $*Float // users: %115, %113
store %80 to %110 : $*Float // id: %112
store %106 to %111 : $*Float // id: %113
end_access %110 : $*Float // id: %114
end_access %111 : $*Float // id: %115
%116 = begin_access [init] [static] [no_nested_conflict] %107 : $*Float // users: %122, %121
%117 = begin_access [read] [static] [no_nested_conflict] %108 : $*Float // users: %124, %121
%118 = begin_access [read] [static] [no_nested_conflict] %109 : $*Float // users: %123, %121
%119 = witness_method $Float, #AdditiveArithmetic."+"!1 : <Self where Self : AdditiveArithmetic> (Self.Type) -> (Self, Self) -> @dynamic_self Self : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %121
%120 = metatype $@thick Float.Type // user: %121
%121 = apply %119<Float>(%116, %118, %117, %120) : $@convention(witness_method: AdditiveArithmetic) <τ_0_0 where τ_0_0 : AdditiveArithmetic> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0
end_access %116 : $*Float // id: %122
end_access %118 : $*Float // id: %123
end_access %117 : $*Float // id: %124
dealloc_stack %109 : $*Float // id: %125
dealloc_stack %108 : $*Float // id: %126
%127 = begin_access [read] [static] [no_nested_conflict] %107 : $*Float // users: %129, %128
%128 = load %127 : $*Float // user: %132
end_access %127 : $*Float // id: %129
dealloc_stack %107 : $*Float // id: %130
dealloc_stack %4 : $*Float // id: %131
return %128 : $Float // id: %132
} // end sil function 'AD__$s11sideeffects3foo1xS2f_tF__adjoint_src_0_wrt_0'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment