Skip to content

x86-64 Ed25519: fold sums of products once in every field program - #1472

Merged
reaperhulk merged 1 commit into
mainfrom
ed25519-auto-lazy
Oct 9, 2026
Merged

reaperhulk merged 1 commit into
mainfrom
ed25519-auto-lazy

Conversation

@alex

@alex alex commented Oct 9, 2026

Copy link
Copy Markdown
Member

#1398 folded the comb's additions' sums and differences once (addL, subL) where an operand is at most 2p, as every product is. This applies the same rule to every x86-64 Ed25519 field program, automatically: fieldCode now tracks, through the program, which slots it last wrote with a product or a constant (bndStep), and folds each sum once if one of its operands is such a slot, and each difference once if its subtrahend is (fieldCodeFrom, opOk). Programs read nothing about earlier blocks, so a slot written before the program counts as unbounded.

That covers the doublings of verification and of the comb (dblOps: B - A and A + B, with A, B squares) and four of the six sums and differences of verification's cached addition (pointAddCachedOps, whose last four read its products). The two that read the accumulator, and C - (B - A) in the doubling, keep both folds.

Proof

No change to Spec/ or TCB/.

  • Impl/Ed25519/X86_64/Field.lean: FieldOp.out, FieldOp.bnd, bndStep, opOk and bndOut (moved from Proof/.../FieldLazy.lean, since code generation now uses them; bndStep is an if, not Mathlib's Function.update), fieldCodeFrom, and fieldCode as fieldCodeFrom from no bounded slot.
  • Proof/Ed25519/X86_64/Field.lean: Bnd, EdArith.mulBnd/sqrBnd, bnd_after and fieldOpB_ok (moved from FieldLazy.lean), opOk_self, and fieldCodeFrom_ok, the program under any initial bounds, with the bounds after it. fieldCode_ok keeps its statement and follows from it, so fieldCodeWide_ok and every user are unchanged.
  • Proof/Ed25519/X86_64/FieldLazy.lean: fieldCodeFromWide_ok lifts it to the wide scratch; fieldCodeWide_acc and fieldCodeWide_accKeep (the comb's accumulator bounds from x86-64 Ed25519/X25519: the comb's sums and differences folded once #1398) use it.

Measurements

On a Sapphire Rapids Xeon, against main, fastest of eleven interleaved runs of each side (ci/bench_compare.py --rounds 11 --measurement-time 2), VG_CPU_FEATURES=avx,avx2,bmi1,bmi2,adx:

Benchmark Base Head Change
ed25519_keygen/32 8.83 µs 8.79 µs 0.4% faster
ed25519_sign/64 10.05 µs 9.99 µs 0.6% faster
ed25519_verify/64 37.42 µs 36.30 µs 3.0% faster
ed25519_verify/1024 39.49 µs 38.11 µs 3.5% faster
ed25519_verify/16384 65.67 µs 65.08 µs 0.9% faster

With the baseline and with all of this CPU's features (the _ifma variants, whose verification multiplies in vector lanes), fastest of five, everything moved by under 2% either way except baseline ed25519_verify/16384 (3.8% slower in one run of five, which SHA-512 over 16 KiB dominates; the code it runs there is unchanged). X25519's key generation uses the comb's doublings too.

Why

From the analysis of the rustls provider in #991: after the signing work (#1360, #1377, #1398, #1421), verification without AVX512_IFMA was next.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RLVbycsRXKPfaW1swVZejG


Generated by Claude Code

fieldCode now folds the carry of a sum, or the borrow of a difference,
once (addL, subL) wherever one operand of the sum, or the subtrahend, is
bounded by 2p, as products and constants are: it tracks, through the
program, which slots it last wrote with one (bndStep), and chooses each
operation's code by it (fieldCodeFrom). The doublings of verification
and of the comb, and four of the six sums and differences of
verification's cached addition, read products of the same block.

The proofs: the tracking and the per-operation lemmas move from
FieldLazy.lean to Field.lean, where fieldCodeFrom_ok proves the program
under any initial bounds; fieldCode_ok follows, so its users are
unchanged.

From the analysis of the rustls provider in #991.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLVbycsRXKPfaW1swVZejG
@reaperhulk
reaperhulk added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 8abb959 Oct 9, 2026
39 checks passed
@reaperhulk
reaperhulk deleted the ed25519-auto-lazy branch October 9, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants