Motivation
#66 moves Pasta multiplication and squaring to register-only AArch64 inline
assembly. The current implementation improves proving and the exact standalone
MSM workloads, but the batch-64 Orchard verifier screen did not show the
expected corresponding improvement.
This is worth revisiting, but it is lower priority than the next verifier
optimization. The goal is to preserve the inline-ASM benefits while finding a
better register-pressure/code-size boundary for large-batch verification.
What we already tried
The experiments were isolated so that compiler effects were attributable:
- specializing the full per-field
P0, P1, and INV constants;
- deriving
INV from P0 - 2 to remove an input operand;
- reusing the dead first RHS limb as the Montgomery quotient register;
- streaming RHS limbs to shorten their live ranges;
- reusing the low accumulator as the quotient register;
- further quotient/scratch-register coalescing;
- rolling the squaring reduction through dead product registers;
- combinations of the multiplication and squaring changes;
- forcing only multiplication or only squaring inline;
- forcing both raw field operations out of line; and
- removing the two
#[inline(always)] hints.
Several variants reduced static instructions or stack references, but none
produced a consistent full-workload win. Streaming operands and globally
outlining the raw field leaves were clearly worse. Removing the forced-inline
hints was codegen-neutral in focused binaries and is useful source hygiene, but
is not a performance optimization.
Important current-code observation
In the batch-verifier binary, both best_multiexp and
BoothBuckets::sum are already emitted as separate functions. Adding
#[inline(never)] around the batch verifier, best_multiexp, or the entire
window sum is therefore unlikely to change the relevant code generation.
Bucket::add_assign, including the mixed projective-affine formula beneath
it, is currently inlined into BoothBuckets::sum. That is the narrowest
plausible boundary to investigate.
Proposed follow-up
-
Instrument the real Orchard batch verifier with a fixed authenticated corpus
and separately time:
- per-proof decoding/transcript/aggregation;
- batch scaling and merging; and
- the final
MSM::eval / best_multiexp.
First confirm whether the B64 difference is actually inside the final MSM.
The exact 5,678-term standalone MSM already improves, so the discrepancy may
instead be elsewhere in verification or simply screen noise.
-
If the final MSM is the source, prototype a large-MSM-only out-of-line mixed
add:
- retain the inline field-ASM leaves unchanged;
- select the large-MSM loop once, outside the digit loop;
- avoid a per-digit runtime branch;
- keep the existing inline path for the prover and smaller MSMs; and
- compare instruction count, stack traffic, text size, and call overhead.
At B64 this may introduce roughly 164,000 calls, so it should only survive if
reduced spills or instruction-cache pressure more than repay that cost.
-
If the slowdown is in per-proof verifier work, place an out-of-line boundary
around the specific high-level curve formula identified by the phase timing,
rather than outlining multiplication and squaring globally.
-
As the deeper option, implement a Pasta-specific fused mixed-add leaf for
large MSM buckets. This would provide explicit register allocation and one
call boundary while leaving the existing inline field ASM available
elsewhere. Mixed addition is a more relevant B64 target than fused point
doubling.
-
If none of those work, revisit the Montgomery kernel as a lower-live-range
CIOS schedule rather than continuing local operand renames.
Benchmark gate
Use the standard laptop method:
- one authenticated corpus of 64 distinct valid proofs, loaded outside timing;
- short field, curve, exact MSM 2,150/5,678, prover, B1, and B64 screens;
- phase timing from the real Orchard verifier, not standalone MSM alone; and
- a balanced full-workload confirmation before claiming a speedup.
Do not promote a change that only improves static counts or a standalone
microbenchmark. Preserve the prover gain and require a reproducible B64
improvement or neutrality.
Motivation
#66 moves Pasta multiplication and squaring to register-only AArch64 inline
assembly. The current implementation improves proving and the exact standalone
MSM workloads, but the batch-64 Orchard verifier screen did not show the
expected corresponding improvement.
This is worth revisiting, but it is lower priority than the next verifier
optimization. The goal is to preserve the inline-ASM benefits while finding a
better register-pressure/code-size boundary for large-batch verification.
What we already tried
The experiments were isolated so that compiler effects were attributable:
P0,P1, andINVconstants;INVfromP0 - 2to remove an input operand;#[inline(always)]hints.Several variants reduced static instructions or stack references, but none
produced a consistent full-workload win. Streaming operands and globally
outlining the raw field leaves were clearly worse. Removing the forced-inline
hints was codegen-neutral in focused binaries and is useful source hygiene, but
is not a performance optimization.
Important current-code observation
In the batch-verifier binary, both
best_multiexpandBoothBuckets::sumare already emitted as separate functions. Adding#[inline(never)]around the batch verifier,best_multiexp, or the entirewindow sum is therefore unlikely to change the relevant code generation.
Bucket::add_assign, including the mixed projective-affine formula beneathit, is currently inlined into
BoothBuckets::sum. That is the narrowestplausible boundary to investigate.
Proposed follow-up
Instrument the real Orchard batch verifier with a fixed authenticated corpus
and separately time:
MSM::eval/best_multiexp.First confirm whether the B64 difference is actually inside the final MSM.
The exact 5,678-term standalone MSM already improves, so the discrepancy may
instead be elsewhere in verification or simply screen noise.
If the final MSM is the source, prototype a large-MSM-only out-of-line mixed
add:
At B64 this may introduce roughly 164,000 calls, so it should only survive if
reduced spills or instruction-cache pressure more than repay that cost.
If the slowdown is in per-proof verifier work, place an out-of-line boundary
around the specific high-level curve formula identified by the phase timing,
rather than outlining multiplication and squaring globally.
As the deeper option, implement a Pasta-specific fused mixed-add leaf for
large MSM buckets. This would provide explicit register allocation and one
call boundary while leaving the existing inline field ASM available
elsewhere. Mixed addition is a more relevant B64 target than fused point
doubling.
If none of those work, revisit the Montgomery kernel as a lower-live-range
CIOS schedule rather than continuing local operand renames.
Benchmark gate
Use the standard laptop method:
Do not promote a change that only improves static counts or a standalone
microbenchmark. Preserve the prover gain and require a reproducible B64
improvement or neutrality.