Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,10 @@ jobs:
strategy:
fail-fast: false
matrix:
# `--all-features` includes `x86_64-asm`, so this lane (and the
# platform-smoke jobs below) executes the assembly field backend,
# which requires ADX/BMI2 on the runner's CPU — true of GitHub's
# current fleet. A SIGILL here means the runner lacks ADX.
features: [--all-features, --no-default-features]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down
18 changes: 18 additions & 0 deletions pasta_curves/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ and this project adheres to Rust's notion of
- Moved the portable (pure Rust) `Fp` and `Fq` wide-squaring routine into a
shared `fields::portable` module. Both fields delegate to the same limb-array
implementation; the algorithm and generated operations are unchanged.
- Added an `x86_64-asm` feature: MULX/ADCX/ADOX Montgomery multiplication
and a dedicated squaring for the Pasta fields on x86-64, a
transcription of the `aarch64-asm` backend's five-limb CIOS rounds with
the same canonicity contract. Requires BMI2 and ADX (Intel Broadwell /
AMD Zen or newer; enabling it on an older CPU faults at runtime), and is
a no-op on other architectures. Measured on Skylake-X: field
multiplication ~1.25x faster than the portable path and a dedicated
assembly squaring ~1.05-1.10x (2-5% ahead of squaring through the
multiplication, mirroring the AArch64 backend's own square-over-mul
margin). Two slower schedulings are pinned in the module docs so they
are not retried: squaring routed through the multiplication, and
interleaved-ADCX/ADOX Montgomery reduction sweeps (~10% slower than the
two short sequential sweeps on Skylake-X).
- Fixed the `fp`/`fq` benches' `square` cell to call `Field::square`
explicitly: the inherent (always-portable) `square` shadowed the
runtime-dispatched trait method, so the cell measured the portable path
even under the assembly features and once mis-sized an assembly squaring
decision.
- All of this release's new MSM machinery — the Eisenstein-orbit backend
(`glv::orbit`), the magnitude-profiled backend planner, the prepared
zero-checks (`glv::zero`), and the `arithmetic::PreparedZeroCheck` /
Expand Down
5 changes: 5 additions & 0 deletions pasta_curves/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ rustdoc-args = [

[features]
aarch64-asm = ["dep:cc"]
# MULX/ADCX/ADOX Montgomery multiplication for the Pasta fields on x86-64.
# Requires a CPU with the BMI2 and ADX extensions (Intel Broadwell / AMD Zen
# or later); enabling it on an older CPU faults at runtime. A no-op on other
# architectures.
x86_64-asm = ["dep:cc"]
alloc = [
"group/alloc",
"blake2b_simd",
Expand Down
7 changes: 6 additions & 1 deletion pasta_curves/benches/fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,12 @@ fn bench_fp_square(b: &mut Bencher) {
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
tmp = tmp.square();
// The inherent (always-portable) `Fp::square` shadows
// `Field::square`, the runtime-dispatched production path; call the
// trait method explicitly so the assembly backends are what gets
// measured. A shadowed cell here once mis-sized an assembly
// squaring decision.
tmp = Field::square(&tmp);
count = (count + 1) % SAMPLES;
tmp
});
Expand Down
7 changes: 6 additions & 1 deletion pasta_curves/benches/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,12 @@ fn bench_fq_square(b: &mut Bencher) {
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
tmp = tmp.square();
// The inherent (always-portable) `Fq::square` shadows
// `Field::square`, the runtime-dispatched production path; call the
// trait method explicitly so the assembly backends are what gets
// measured. A shadowed cell here once mis-sized an assembly
// squaring decision.
tmp = Field::square(&tmp);
count = (count + 1) % SAMPLES;
tmp
});
Expand Down
18 changes: 17 additions & 1 deletion pasta_curves/build.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
#[cfg(feature = "aarch64-asm")]
#[cfg(any(feature = "aarch64-asm", feature = "x86_64-asm"))]
use std::env;

fn main() {
println!("cargo:rerun-if-changed=src/asm/pasta_mul-armv8.S");
println!("cargo:rerun-if-changed=src/asm/pasta_lazy_square-x86_64.S");

#[cfg(feature = "aarch64-asm")]
build_aarch64_asm();

#[cfg(feature = "x86_64-asm")]
build_x86_64_asm();
}

#[cfg(feature = "x86_64-asm")]
fn build_x86_64_asm() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_family = env::var("CARGO_CFG_TARGET_FAMILY").unwrap();

if target_arch == "x86_64" && target_family == "unix" {
cc::Build::new()
.file("src/asm/pasta_lazy_square-x86_64.S")
.compile("pasta_curves_x86_64_lazy_square");
}
}

#[cfg(feature = "aarch64-asm")]
Expand Down
Loading
Loading