swift
swift copied to clipboard
[AutoDiff] Correctly propagate optional adjoint through `switch_enum`
Fixes #74978
@swift-ci please test
So, the code in question looks like this:
// square2(y:)
sil hidden [ossa] @$s3opt7square21yS2dSg_tF : $@convention(thin) (Optional<Double>) -> Double {
// %0 "y" // users: %14, %3, %1
bb0(%0 : $Optional<Double>):
debug_value %0 : $Optional<Double>, let, name "y", argno 1 // id: %1
%2 = metatype $@thin Double.Type // user: %26
switch_enum %0 : $Optional<Double>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1 // id: %3
...
// %13 // user: %26
bb2(%13 : $Double): // Preds: bb0
switch_enum %0 : $Optional<Double>, case #Optional.some!enumelt: bb4, case #Optional.none!enumelt: bb3 // id: %14
...
// %24 // user: %26
bb4(%24 : $Double): // Preds: bb2
// function_ref static Double.* infix(_:_:)
%25 = function_ref @$sSd1moiyS2d_SdtFZ : $@convention(method) (Double, Double, @thin Double.Type) -> Double // user: %26
%26 = apply %25(%13, %24, %2) : $@convention(method) (Double, Double, @thin Double.Type) -> Double // user: %27
return %26 : $Double // id: %27
} // end sil function '$s3opt7square21yS2dSg_tF'
However, instead of adjoint accumulation (for %0) we just created new adjoint each time. Funny enough, adjoint buffer version for optionals of non-loadable types was correct – adjoint buffers were accumulated together.
Likely the non-optional switch_enum case is broken as well, I just do not have a testcase that directly exposes the problem.
@swift-ci please test
@swift-ci please test