You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Encode reverse-mode early returns with a named lambda
The reverse-mode early-return encoding emitted a label inside the master
reverse and a goto into it from each early-return point. That violates
[stmt.dcl]/2 whenever a local with a non-trivial initializer or
destructor sits between the goto and its target, which is why
DifferentiateWithClad had to bypass Sema::ActOnFinishFunctionBody on the
generated function.
Materialise the master reverse as a `[&]` lambda bound to an `auto`
VarDecl instead, called at each early return and at the tail. The body
is assembled outside the closure scope, so its references to captured
variables are rebuilt in scope (rebuildLambdaCaptures) where the `[&]`
default registers the capture; the reverse statements are emitted into
the closure directly. An early return is a NullStmt marker in the
forward block, patched with `{ _rev(); return; }` at finalization so no
subtree gains a second parent.
Whether a function has a non-tail return is a fact about the primal, so
DiffRequest carries it as HasEarlyReturns; the encoder reads it to pick
the lambda vs plain shape up front. A branch condition read by the
master reverse is zero-initialized so an early return that skips its
forward store leaves it false -- the same zero-initialized additive
state clad already relies on for adjoints and loop counters.
Fixes#367
0 commit comments