Replace avx2_backend with simd_backend (autoselects AVX2/IFMA)

This commit is contained in:
Henry de Valence 2018-11-24 13:12:20 -08:00
parent 9ed2128a10
commit 47a164da4d
6 changed files with 60 additions and 65 deletions

View file

@ -69,10 +69,10 @@ yolocrypto = []
u32_backend = [] u32_backend = []
# The u64 backend uses u64s with u128 products. # The u64 backend uses u64s with u128 products.
u64_backend = [] u64_backend = []
# The AVX2 backend uses u32x8s with u64x4 products. # The SIMD backend uses parallel formulas, using either AVX2 or AVX512-IFMA.
# It uses the u64 code for serial operations. simd_backend = ["nightly", "u64_backend", "packed_simd"]
avx2_backend = ["nightly", "u64_backend", "packed_simd"] # Old name for the SIMD backend, preserved for compatibility
ifma_backend = ["nightly", "u64_backend", "packed_simd", "yolocrypto"] avx2_backend = ["simd_backend"]
# Signals that we're in the main build stage. This is off by default, # Signals that we're in the main build stage. This is off by default,
# to signal stage 1 of the build, where build.rs loads the library # to signal stage 1 of the build, where build.rs loads the library

View file

@ -1,5 +1,11 @@
#![cfg_attr(feature = "ifma_backend", feature(simd_ffi))] #![cfg_attr(
#![cfg_attr(feature = "ifma_backend", feature(link_llvm_intrinsics))] all(feature = "simd_backend", target_feature = "avx512ifma"),
feature(simd_ffi)
)]
#![cfg_attr(
all(feature = "simd_backend", target_feature = "avx512ifma"),
feature(link_llvm_intrinsics)
)]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))] #![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
#![allow(unused_variables)] #![allow(unused_variables)]
@ -15,7 +21,7 @@ extern crate digest;
extern crate rand; extern crate rand;
extern crate subtle; extern crate subtle;
#[cfg(all(feature = "nightly", any(feature = "avx2_backend", feature = "ifma_backend")))] #[cfg(all(feature = "nightly", feature = "packed_simd"))]
extern crate packed_simd; extern crate packed_simd;
use std::env; use std::env;

View file

@ -24,17 +24,17 @@
#[cfg(not(any( #[cfg(not(any(
feature = "u32_backend", feature = "u32_backend",
feature = "u64_backend", feature = "u64_backend",
feature = "avx2_backend" feature = "simd_backend",
)))] )))]
compile_error!( compile_error!(
"no curve25519-dalek backend cargo feature enabled! \ "no curve25519-dalek backend cargo feature enabled! \
please enable one of: u32_backend, u64_backend, avx2_backend" please enable one of: u32_backend, u64_backend, simd_backend"
); );
pub mod serial; pub mod serial;
#[cfg(any( #[cfg(all(
all(feature = "ifma_backend", target_feature = "avx512ifma"), feature = "simd_backend",
all(feature = "avx2_backend", target_feature = "avx2"), any(target_feature = "avx2", target_feature = "avx512ifma")
))] ))]
pub mod vector; pub mod vector;

View file

@ -21,15 +21,17 @@
//! `32bit` since identifiers can't start with letters, and the backends //! `32bit` since identifiers can't start with letters, and the backends
//! do use `u32`/`u64`, so this seems like a least-bad option. //! do use `u32`/`u64`, so this seems like a least-bad option.
#[cfg(all(feature = "avx2_backend", target_feature = "avx2"))] #[cfg(not(any(target_feature = "avx2", target_feature = "avx512ifma",)))]
compile_error!("simd_backend selected without target_feature=+avx2 or +avx512ifma");
#[cfg(all(target_feature = "avx2", not(target_feature = "avx512ifma")))]
pub mod avx2; pub mod avx2;
#[cfg(all(feature = "avx2_backend", target_feature = "avx2"))] #[cfg(all(target_feature = "avx2", not(target_feature = "avx512ifma")))]
pub(crate) use self::avx2::{ pub(crate) use self::avx2::{
constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint, constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint,
}; };
#[cfg(all(feature = "ifma_backend", target_feature = "avx512ifma"))] #[cfg(all(target_feature = "avx512ifma"))]
pub mod ifma; pub mod ifma;
pub mod scalar_mul; pub mod scalar_mul;

View file

@ -130,6 +130,17 @@ use traits::MultiscalarMul;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
use traits::VartimeMultiscalarMul; use traits::VartimeMultiscalarMul;
#[cfg(not(all(
feature = "simd_backend",
any(target_feature = "avx2", target_feature = "avx512ifma")
)))]
use backend::serial::scalar_mul;
#[cfg(all(
feature = "simd_backend",
any(target_feature = "avx2", target_feature = "avx512ifma")
))]
use backend::vector::scalar_mul;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Compressed points // Compressed points
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -572,18 +583,7 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint {
/// For scalar multiplication of a basepoint, /// For scalar multiplication of a basepoint,
/// `EdwardsBasepointTable` is approximately 4x faster. /// `EdwardsBasepointTable` is approximately 4x faster.
fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
// If we built with AVX2, use the AVX2 backend. scalar_mul::variable_base::mul(self, scalar)
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
{
use backend::vector::scalar_mul::variable_base::mul;
mul(self, scalar)
}
// Otherwise, use the serial backend:
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
{
use backend::serial::scalar_mul::variable_base::mul;
mul(self, scalar)
}
} }
} }
@ -609,7 +609,7 @@ impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar {
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
impl MultiscalarMul for EdwardsPoint { impl MultiscalarMul for EdwardsPoint {
type Point = EdwardsPoint; type Point = EdwardsPoint;
fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
where where
I: IntoIterator, I: IntoIterator,
@ -634,21 +634,14 @@ impl MultiscalarMul for EdwardsPoint {
// size-dependent algorithm dispatch, use this as the hint. // size-dependent algorithm dispatch, use this as the hint.
let _size = s_lo; let _size = s_lo;
// If we built with AVX2, use the AVX2 backend. scalar_mul::straus::Straus::multiscalar_mul(scalars, points)
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
use backend::vector::scalar_mul::straus::Straus;
// Otherwise, proceed as normal:
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
use backend::serial::scalar_mul::straus::Straus;
Straus::multiscalar_mul(scalars, points)
} }
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
impl VartimeMultiscalarMul for EdwardsPoint { impl VartimeMultiscalarMul for EdwardsPoint {
type Point = EdwardsPoint; type Point = EdwardsPoint;
fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint> fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
where where
I: IntoIterator, I: IntoIterator,
@ -672,29 +665,19 @@ impl VartimeMultiscalarMul for EdwardsPoint {
// size-dependent algorithm dispatch, use this as the hint. // size-dependent algorithm dispatch, use this as the hint.
let _size = s_lo; let _size = s_lo;
// If we built with AVX2, use the AVX2 backend. scalar_mul::straus::Straus::optional_multiscalar_mul(scalars, points)
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
use backend::vector::scalar_mul::straus::Straus;
// Otherwise, proceed as normal:
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
use backend::serial::scalar_mul::straus::Straus;
Straus::optional_multiscalar_mul(scalars, points)
} }
} }
impl EdwardsPoint { impl EdwardsPoint {
/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
#[cfg(feature = "stage2_build")] #[cfg(feature = "stage2_build")]
pub fn vartime_double_scalar_mul_basepoint(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { pub fn vartime_double_scalar_mul_basepoint(
// If we built with AVX2, use the AVX2 backend. a: &Scalar,
#[cfg(all(feature="avx2_backend", target_feature="avx2"))] A: &EdwardsPoint,
use backend::vector::scalar_mul::vartime_double_base; b: &Scalar,
// Otherwise, use the serial backend: ) -> EdwardsPoint {
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))] scalar_mul::vartime_double_base::mul(a, A, b)
use backend::serial::scalar_mul::vartime_double_base;
vartime_double_base::mul(a, A, b)
} }
} }

View file

@ -9,14 +9,18 @@
// - Henry de Valence <hdevalence@hdevalence.ca> // - Henry de Valence <hdevalence@hdevalence.ca>
#![no_std] #![no_std]
#![cfg_attr(
#![cfg_attr(feature = "ifma_backend", feature(simd_ffi))] all(feature = "simd_backend", target_feature = "avx512ifma"),
#![cfg_attr(feature = "ifma_backend", feature(link_llvm_intrinsics))] feature(simd_ffi)
)]
#![cfg_attr(
all(feature = "simd_backend", target_feature = "avx512ifma"),
feature(link_llvm_intrinsics)
)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))] #![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
#![cfg_attr(feature = "nightly", feature(external_doc))] #![cfg_attr(feature = "nightly", feature(external_doc))]
// Refuse to compile if documentation is missing, but only on nightly. // Refuse to compile if documentation is missing, but only on nightly.
// //
// This means that missing docs will still fail CI, but means we can use // This means that missing docs will still fail CI, but means we can use
@ -41,21 +45,21 @@ extern crate alloc;
#[macro_use] #[macro_use]
extern crate std; extern crate std;
#[cfg(all(feature = "nightly", any(feature = "avx2_backend", feature = "ifma_backend")))] #[cfg(all(feature = "nightly", feature = "packed_simd"))]
extern crate packed_simd; extern crate packed_simd;
extern crate rand;
extern crate clear_on_drop;
extern crate byteorder; extern crate byteorder;
extern crate clear_on_drop;
pub extern crate digest; pub extern crate digest;
extern crate rand;
// Used for traits related to constant-time code. // Used for traits related to constant-time code.
extern crate subtle; extern crate subtle;
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(all(test, feature = "serde"))] #[cfg(all(test, feature = "serde"))]
extern crate bincode; extern crate bincode;
#[cfg(feature = "serde")]
extern crate serde;
// Internal macros. Must come first! // Internal macros. Must come first!
#[macro_use] #[macro_use]