Repository navigation
PPC64LE Montgomery multiplication of up to four words: [b] and m in registers, rows as two carry chains - #4774
Merged
Merged
Conversation
… registers, rows as two carry chains Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKUFHH4GefHP3pmPRSL4N4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKUFHH4GefHP3pmPRSL4N4
This was referenced Nov 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4141 (PPC64LE audit, finding 1: per-operation cost). Follows #4757.
For curves of at most four words (P-192, P-224, P-256, secp256k1, brainpoolP256r1, and their
n),vg_<curve>_mul_mod_<p|n>now runsrmul4in place of #4757'srmul:[b]andmin registers.[b]sits in the registers after the accumulator,r(16 + n)up (bReg), and the modulus inr6,r7,r10,r0(mReg), each loaded once per call. A row step no longer loads either.pass): the low words ofx · y_jgo into the accumulator withadde, then the high words one word up. A product's words no longer need carries of their own, so a step is a multiplication and anadde, two instructions where it was seven.m'is at[M.tmp]until the reduction, which subtractsmstraight from its registers (qcsub, reusingrcsub's selection).For P-256 the function now runs 284 instructions instead of 357, with a loop body of 46 instead of 67. Moduli of more words keep
rmul.rmulSelputs the choice between the two inside the code blocks, so the program's shape (noFrames) does not depend on it, and the callers'rflproofs of it are unchanged.Proofs
Proof/Mont/PPC64LE/Ops.lean:pass_ok: the chain lemma, built ongval/pvandpv_split,x · B = lo + 2⁶⁴ hi.qrowB_okandqrowM_ok: the two rows. The second shows the dropped low word is zero, frommont_low.qrow_okandqloop_ok: the iteration, with invariantQLoopInv, and the loop.qsubs_okandqcsub_ok: the reduction.qloadB_okandqloadM_ok: the loads of[b]andm.rmul4_ok: the whole function, withrmul_ok's statement butKp (.r6 :: opClob). That is still insidefnClob, somulFn_ok's statement is unchanged and no caller's proof changes.The registers saved and restored are now
r15–r(15 + 2n), at mostr23, so #4757's rule for callers still holds: keep public values inr14orr25–r31.No TCB or Spec change.
Testing
lake build,Emit.leanand the static checks pass. The crate changes are the internalvg_*_mul_mod_{p,n}of every curve of at most four words.check_lean_public_imports.pypasses.taint_decideagain.Benchmark
POWER9, run 42533245411 against main (85135ee),
arches=powerpc64:ecdh_p256/32ecdh_p224/28ecdh_secp256k1/32ecdh_brainpoolp256r1/32ec_p256_public_key/65ec_p224_public_key/57ecdsa_p256_sha256_sign/64ecdsa_p256_sha256_verify/64ecdsa_p224_sha224_sign/64ecdsa_p224_sha224_verify/64Every other row of the run (the 1024- and 16384-byte messages, and SHA-384 with P-256) is 9.3–12.4% faster.
An earlier run, 42531318690, against #4757's head, measured
ecdh_p2564% slower but verification 10% faster. This run, on the rebased branch, does not reproduce the slowdown: every row is faster by a similar margin.Generated by Claude Code