Commit Graph

35 Commits

Author SHA1 Message Date
Anton Korobeynikov
bc94ac3342 [AutoDiff] Better diagnose non-differentiability for throwing functions (#81669)
Fixes #81608
2025-05-21 09:13:18 -07:00
Daniil Kovalev
83a028d105 [AutoDiff] Allow closure differentiation when used as default arg val (#78373)
If the default argument generator (and, consequently, the function taking this default argument) has public visibility, it's OK to have a closure (which always has private visibility) as the default value of the argument.
2025-02-19 22:34:56 -08:00
Daniil Kovalev
1a42a0ce5f [AutoDiff] Support curry thunks differentiation in fragile funcs (#77615)
Inside fragile functions, we expect function derivatives to be public, which could be achieved by either explicitly marking the functions as differentiable or having a public explicit derivative defined for them. This is obviously not
possible for single and double curry thunks which are a special case of `AutoClosureExpr`.

Instead of looking at the thunk itself, we unwrap it and look at the function being wrapped. While the thunk itself and its differentiability witness will not have public visibility, it's not an issue for the case where the function being wrapped (and its witness) have public visibility.

Fixes #54819
Fixes #75776
2025-02-17 14:43:50 -08:00
Daniil Kovalev
c50dcae216 [AutoDiff][test] Enable previously disabled tests related to issue 55492 (#77759)
A couple of tests were disabled due to crash described in
https://github.com/swiftlang/swift/issues/55492. Now the crash is fixed
and the issue is resolved, so tests could be enabled.
2024-11-21 08:02:09 -08:00
Anton Korobeynikov
97ba96b8d8 [AutoDiff] Implement active Optional differentiation (#74977)
Fixes #74972
2024-07-04 22:27:23 -07:00
Anton Korobeynikov
c7a216058f [AutoDiff] First cut of coroutines differentiation (#71461)
This PR implements first set of changes required to support autodiff for coroutines. It mostly targeted to `_modify` accessors in standard library (and beyond), but overall implementation is quite generic.

There are some specifics of implementation and known limitations:
 - Only `@yield_once` coroutines are naturally supported
 - VJP is a coroutine itself: it yields the results *and* returns a pullback closure as a normal return. This allows us to capture values produced in resume part of a coroutine (this is required for defers and other cleanups / commits)
 - Pullback is a coroutine, we assume that coroutine cannot abort and therefore we execute the original coroutine in reverse from return via yield and then back to the entry
 - It seems there is no semantically sane way to support `_read` coroutines (as we will need to "accept" adjoints via yields), therefore only coroutines with inout yields are supported (`_modify` accessors). Pullbacks of such coroutines take adjoint buffer as input argument, yield this buffer (to accumulate adjoint values in the caller) and finally return the adjoints indirectly.
 - Coroutines (as opposed to normal functions) are not first-class values: there is no AST type for them, one cannot e.g. store them into tuples, etc. So, everywhere where AST type is required, we have to hack around.
 - As there is no AST type for coroutines, there is no way one could register custom derivative for coroutines. So far only compiler-produced derivatives are supported
 - There are lots of common things wrt normal function apply's, but still there are subtle but important differences. I tried to organize the code to enable code reuse, still it was not always possible, so some code duplication could be seen
 - The order of how pullback closures are produced in VJP is a bit different: for normal apply's VJP produces both value and pullback closure via a single nested VJP apply. This is not so anymore with coroutine VJP's: yielded values are produced at `begin_apply` site and pullback closure is available only from `end_apply`, so we need to track the order in which pullbacks are produced (and arrange consumption of the values accordingly – effectively delay them)
 - On the way some complementary changes were required in e.g. mangler / demangler

This patch covers the generation of derivatives up to SIL level, however, it is not enough as codegen of `partial_apply` of a coroutine is completely broken. The fix for this will be submitted separately as it is not directly autodiff-related.

---------

Co-authored-by: Andrew Savonichev <andrew.savonichev@gmail.com>
Co-authored-by: Richard Wei <rxwei@apple.com>
2024-04-04 17:24:55 -07:00
Anton Korobeynikov
03334a8f92 [AutoDiff] Generalize handling of semantic result parameters (#67230)
Introduce the notion of "semantic result parameter". Handle differentiation of inouts via semantic result parameter abstraction. Do not consider non-wrt semantic result parameters as semantic results

Fixes #67174
2023-08-03 09:33:11 -07:00
Andrew Savonichev
b6acb6fbef [AutoDiff] Check @noDerivative for function type comparison (#67121)
As described in the issue #62922, the compiler should not allow to discard @noDerivative attribute and keep @differentiable. The patch adds a diagnostic for this case.

Resolves #62922.
2023-07-06 15:21:30 -07:00
Nate Chandler
cda365ca8d [stdlib] Collection types are eagerMove.
Types that have "value semantics" should not have lexical lifetimes.
Value types are not expected to have custom deinits. Are not expected to
expose unsafe interior pointers. And cannot have weak references because
they are structs. Therefore, deinitialization barriers are irrelevant.

rdar://107076869
2023-03-30 11:04:47 -07:00
Anthony Latsis
549a6a9d7f Gardening: Migrate test suite to GH issues: AutoDiff/SILOptimizer 2022-09-19 02:44:03 +03:00
Richard Wei
a1cb9bbcc9 [AutoDiff] Move differentiable curry thunk bug reproducer to an XFAIL test.
Due to rdar://87429620, test/AutoDiff/SILOptimizer/differentiation_diagnostics.swift is still using `-requirement-machine=off`. This patch moves the reproducer to a standalone XFAIL test, and removes `-requirement-machine=off` from differentiation_diagnostics.swift.
2022-01-11 18:01:43 -08:00
Michael Gottesman
785153045b [move-operator] Start having SILGen emit lexical lifetimes and teach the optimizer how to maintain lexical lifetimes until the lexical lifetime elimination.
I am doing this so that I can use lexical lifetimes to emit diagnostics such as
the move operator diagnostics.
2021-11-29 18:02:13 -08:00
Richard Wei
9bcba98213 Revert "Revert "[AutoDiff] Fix two derivative type calculation bugs caught by RequirementMachine""
This reverts commit 262965418f.
2021-11-05 10:29:08 -07:00
Doug Gregor
262965418f Revert "[AutoDiff] Fix two derivative type calculation bugs caught by RequirementMachine" 2021-11-04 15:56:48 -07:00
Richard Wei
808c7ec783 [AutoDiff] Fix two derivative type calculation bugs caught by RequirementMachine.
1. When calculating the differential type of an original function with an inout parameter and when the inout parameter has a type parameter, the inout parameter should get a generic parameter in the subst generic signature of the differential but it currently doesn't. This causes SILGen to attempt to reabstract the differential value in the JVP protocol witness thunk, whilst the generic signature is lacking requirements, leading to a requirement machine error. This patch fixes the calculation so that the JVP's result type (the differential type) always matches the witness thunk's result type.

    Wrong type:
    ```swift
             sil private [transparent] [thunk] [ossa] @... <τ_0_0 where τ_0_0 : Differentiable> (...) -> @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <τ_0_0.TangentVector, τ_0_0.TangentVector> {
               %6 = differentiable_function_extract [jvp] %5 : $@differentiable(reverse) @convention(method) <τ_0_0 where τ_0_0 : Differentiable> (@in_guaranteed τ_0_0, @noDerivative @inout τ_0_0, @noDerivative SR_13305_Struct) -> () // user: %7
    HERE ====> %7 = apply %6<τ_0_0>(%0, %1, %3) : $@convention(method) <τ_0_0 where τ_0_0 : Differentiable> (@in_guaranteed τ_0_0, @inout τ_0_0, SR_13305_Struct) -> @owned @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0 for <τ_0_0.TangentVector>
    ```

    Should be:
    ```swift
      %7 = apply %6<τ_0_0>(%0, %1, %3) : $@convention(method) <τ_0_0 where τ_0_0 : Differentiable> (@in_guaranteed τ_0_0, @inout τ_0_0, SR_13305_Struct) -> @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <τ_0_0.TangentVector, τ_0_0.TangentVector>
    ```

2. `TypeConverter::makeConstantInterfaceType` is not passing down the derivative generic signature to `SILFunctionType::getAutoDiffDerivativeFunctionType` for class methods, and this was caught by RequirementMachine during vtable emission. This patch fixes that.

Partially resolves rdar://82549134. The only remaining tests that require `-requirement-machine=off` are SILOptimizer/semantic_member_accessors_sil.swift and SILOptimizer/differentiation_diagnostics.swift which I will fix next. Then I'll do a proper fix for workaround #39416.
2021-09-30 20:51:36 -07:00
Slava Pestov
4f6ba29715 AutoDiff: Disable requirement machine when building or testing Differentiation library
The SIL type lowering logic for AutoDiff gets the substituted generic signature
mixed up with the invocation generic signature, so it tries to ask questions
about DependentMemberTypes in a signature with no requirements. This triggers
assertions when the requirement machine is enabled.

Disable the requirement machine until this is fixed.
2021-07-30 19:42:31 -04:00
Luciano Almeida
ddeb1929c4 [DiagnosticQol][SR-14505] Use DeclDescriptive kind in missing return data flow diagnostics (#36952)
* [Diagnostics] Use DeclDescriptiveKind on data flow diagnostics to improve diagnostic message

* [tests] Add regression tests to SILOptimizer/return.swift

* [tests] Adapt other tests to changes of SR-14505

* [Diagnostics] Adapt message for missing return diagnostics, remove article

* [Diagnostics] Adapt message for missing return diagnostics to have a note with fix

* [tests] Adjust tests in validation suit
2021-04-20 08:16:32 -03:00
Richard Wei
0b53a02544 [AutoDiff] Rename 'in:' to 'of:' in differential operators.
Rename the argument label `in:` in `gradient(at:in:)`, `pullback(at:in:)`, etc to `of:`, as suggested in the [pitch thread](https://forums.swift.org/t/differentiable-programming-for-gradient-based-machine-learning/42147).
2021-02-24 01:33:42 -05:00
Richard Wei
8bc6143a4c [AutoDiff] Rename 'move(along:)' to 'move(by:)'.
Rename `move(along:)` to `move(by:)` based on the proposal feedback. The main argument for the change is that tangent vectors specify both a direction and a magnitude, whereas `along:` does not indicate that `self` is being moved by the specified magnitude.
2021-02-23 21:45:01 -05:00
Richard Wei
af8942d940 [AutoDiff] Rename '@differentiable' to '@differentiable(reverse)'.
Compiler:
- Add `Forward` and `Reverse` to `DifferentiabilityKind`.
- Expand `DifferentiabilityMask` in `ExtInfo` to 3 bits so that it now holds all 4 cases of `DifferentiabilityKind`.
- Parse `@differentiable(reverse)` and `@differentiable(_forward)` declaration attributes and type attributes.
- Emit a warning for `@differentiable` without `reverse`.
- Emit an error for `@differentiable(_forward)`.
- Rename `@differentiable(linear)` to `@differentiable(_linear)`.
- Make `@differentiable(reverse)` type lowering go through today's `@differentiable` code path. We will specialize it to reverse-mode in a follow-up patch.

ABI:
- Add `Forward` and `Reverse` to `FunctionMetadataDifferentiabilityKind`.
- Extend `TargetFunctionTypeFlags` by 1 bit to store the highest bit of differentiability kind (linear). Note that there is a 2-bit gap in `DifferentiabilityMask` which is reserved for `AsyncMask` and `ConcurrentMask`; `AsyncMask` is ABI-stable so we cannot change that.

_Differentiation module:
- Replace all occurrences of `@differentiable` with `@differentiable(reverse)`.
- Delete `_transpose(of:)`.

Resolves rdar://69980056.
2021-02-07 14:09:46 -08:00
Michael Gottesman
ec71713fb0 [ownership] Teach CanonicalizeInstruction how to eliminate trivial copies/borrows.
I am going to be using in inst-simplify/sil-combine/canonicalize instruction a
RAUW everything against everything API (*). This creates some extra ARC
traffic/borrows. It is going to be useful to have some simple peepholes that
gets rid of some of the extraneous traffic.

(*) Noting that we are not going to support replacing non-trivial
OwnershipKind::None values with non-trivial OwnershipKind::* values. This is a
corner case that only comes up with non-trivial enums that have a non-payloaded
or trivial enum case. It is much more complex to implement that transform, but
it is an edge case, so we are just not going to support those for now.

----

I also eliminated the dependence of SILGenCleanup on Swift/SwiftShims. This
speeds up iterating on the test case with a debug compiler since we don't need
those modules.
2020-12-02 17:25:13 -08:00
Dan Zheng
83b50cd8e3 [AutoDiff] Add missing withoutDerivative(at:) fix-its. (#33660)
Add `withoutDerivative(at:)` fix-its for errors regarding non-differentiable
arguments and results.
2020-08-27 11:53:33 -07:00
Alex Efremov
40c448514a [AutoDiff] Support differentiation of non-active try_apply. (#33483)
Add differentiation support for non-active `try_apply` SIL instructions.

Notable pullback generation changes:
* Original basic blocks are now visited in a different order:
* starting from the original basic block, all its predecessors
* are visited in a breadth-first search order. This ensures that
* all successors of any block are visited before the block itself.

Resolves TF-433.
2020-08-15 10:22:28 -07:00
Alex Efremov
ccca08b7f7 [AutoDiff] Add reverse-mode switch_enum support for Optional. (#33218)
Pullback generation now supports `switch_enum` and `switch_enum_addr`
instructions for `Optional`-typed operands.

Currently, the logic is special-cased to `Optional`, but may be generalized in
the future to support enums following general rules.
2020-08-07 17:56:15 -07:00
Dan Zheng
d4bbcf9a2a [AutoDiff] Fix unexpected non-differentiable property access error. (#32670)
Add base type parameter to `TangentStoredPropertyRequest`.

Use `TypeBase::getTypeOfMember` instead of `VarDecl::getType` to correctly
compute the member type of original stored properties, using the base type.

Resolves SR-13134.
2020-07-05 14:27:48 -07:00
Dan Zheng
1bc9159e4f [AutoDiff] Support differentiation of functions with multiple results in SIL. (#32629)
Reverse-mode differentiation now supports `apply` instructions with multiple
active "semantic results" (formal results or `inout` parameters).

The "cannot differentiate through multiple results" non-differentiability error
is lifted.

Resolves TF-983.
2020-06-30 17:33:25 -07:00
Dan Zheng
46c2073784 [AutoDiff] Start supporting loadable types with address-only tangents. (#32540)
Previously, PullbackEmitter assumed that original values' value category
matches their `TangentVector` types' value category. This was problematic
for loadable types with address-only `TangentVector` types.

Now, PullbackEmitter starts to support differentiation of loadable types with
address-only `TangentVector` types. This patch focuses on supporting and testing
class types, more support can be added incrementally.

Resolves TF-1149.
2020-06-25 08:27:03 -07:00
Dan Zheng
c690ac87d6 [AutoDiff] Improve invalid stored property projection diagnostics.
Use TangentStoredPropertyRequest in differentiation transform.

Improve non-differentiability diagnostics regarding invalid stored
property projection instructions:
`struct_extract`, `struct_element_addr`, `ref_element_addr`.

Diagnose the following cases:
- Original property's type does not conform to `Differentiable`.
- Base type's `TangentVector` is not a struct.
- Tangent property not found: base type's `TangentVector` does not have a
  stored property with the same name as the original property.
- Tangent property's type is not equal to the original property's
  `TangentVector` type.
- Tangent property is not a stored property.

Resolves TF-969 and TF-970.
2020-06-22 10:21:44 -07:00
Dan Zheng
a14acdbd15 [AutoDiff upstream] Upstream remaining differentiation diagnostics tests. 2020-06-18 20:54:20 +00:00
Dan Zheng
96f3f6fbcb [AutoDiff] Finish wrapped property differentiation support.
Add special-case VJP generation support for "semantic member accessors".
This is necessary to avoid activity analysis related diagnostics and simplifies
generated code.

Fix "wrapped property mutability" check in `Differentiable` derived conformnances.
This resolves SR-12642.

Add e2e test using real world property wrappers (`@Lazy` and `@Clamping`).
2020-05-10 15:55:29 -07:00
Dan Zheng
1f5818a5e9 [AutoDiff] Support property wrapper differentiation.
Support differentiation of property wrapper wrapped value getters and setters.

Create new pullback generation code path for "semantic member accessors".
"Semantic member accessors" are attached to member properties that have a
corresponding tangent stored property in the parent `TangentVector` type.

These accessors have special-case pullback generation based on their semantic
behavior. Currently, only getters and setters are supported.

This special-case pullback generation is currently used for stored property
accessors and property wrapper wrapped value accessors. In the future, it can
also be used to support `@differentiable(useInTangentVector)` computed
properties: SR-12636.

User-defined accesors cannot use this code path because they may use custom
logic that does not semantically perform a member access.

Resolves SR-12639.
2020-05-09 16:43:06 -07:00
marcrasi
bc0dd81950 [AutoDiff upstream] SILOptimizer tests (#31114) 2020-04-17 20:46:47 -07:00
Dan Zheng
b833271215 Simplify test before stdlib derivatives are upstreamed. 2020-04-05 20:35:35 -07:00
Dan Zheng
146c11ec80 [AutoDiff upstream] Add differentiable_function canonicalization. (#30818)
Canonicalizes `differentiable_function` instructions by filling in missing
derivative function operands.

Derivative function emission rules, based on the original function value:

- `function_ref`: look up differentiability witness with the exact or a minimal
  superset derivative configuration. Emit a `differentiability_witness_function`
  for the derivative function.
- `witness_method`: emit a `witness_method` with the minimal superset derivative
  configuration for the derivative function.
- `class_method`: emit a `class_method` with the minimal superset derivative
  configuration for the derivative function.

If an *actual* emitted derivative function has a superset derivative
configuration versus the *desired* derivative configuration, create a "subset
parameters thunk" to thunk the actual derivative to the desired type.

For `differentiable_function` instructions formed from curry thunk applications:
clone the curry thunk (with type `(Self) -> (T, ...) -> U`) and create a new
version with type `(Self) -> @differentiable (T, ...) -> U`.

Progress towards TF-1211.
2020-04-05 20:19:10 -07:00
Dan Zheng
aa66cce808 [AutoDiff upstream] Add differentiation transform.
The differentiation transform does the following:
- Canonicalizes differentiability witnesses by filling in missing derivative
  function entries.
- Canonicalizes `differentiable_function` instructions by filling in missing
  derivative function operands.
- If necessary, performs automatic differentiation: generating derivative
  functions for original functions.
  - When encountering non-differentiability code, produces a diagnostic and
    errors out.

Partially resolves TF-1211: add the main canonicalization loop.

To incrementally stage changes, derivative functions are currently created
with empty bodies that fatal error with a nice message.

Derivative emitters will be upstreamed separately.
2020-04-02 15:43:57 -07:00