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 = []
# The u64 backend uses u64s with u128 products.
u64_backend = []
# The AVX2 backend uses u32x8s with u64x4 products.
# It uses the u64 code for serial operations.
avx2_backend = ["nightly", "u64_backend", "packed_simd"]
ifma_backend = ["nightly", "u64_backend", "packed_simd", "yolocrypto"]
# The SIMD backend uses parallel formulas, using either AVX2 or AVX512-IFMA.
simd_backend = ["nightly", "u64_backend", "packed_simd"]
# Old name for the SIMD backend, preserved for compatibility
avx2_backend = ["simd_backend"]
# 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

View file

@ -1,5 +1,11 @@
#![cfg_attr(feature = "ifma_backend", feature(simd_ffi))]
#![cfg_attr(feature = "ifma_backend", feature(link_llvm_intrinsics))]
#![cfg_attr(
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(feature = "nightly", feature(cfg_target_feature))]
#![allow(unused_variables)]
@ -15,7 +21,7 @@ extern crate digest;
extern crate rand;
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;
use std::env;

View file

@ -24,17 +24,17 @@
#[cfg(not(any(
feature = "u32_backend",
feature = "u64_backend",
feature = "avx2_backend"
feature = "simd_backend",
)))]
compile_error!(
"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;
#[cfg(any(
all(feature = "ifma_backend", target_feature = "avx512ifma"),
all(feature = "avx2_backend", target_feature = "avx2"),
#[cfg(all(
feature = "simd_backend",
any(target_feature = "avx2", target_feature = "avx512ifma")
))]
pub mod vector;

View file

@ -21,15 +21,17 @@
//! `32bit` since identifiers can't start with letters, and the backends
//! 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;
#[cfg(all(feature = "avx2_backend", target_feature = "avx2"))]
#[cfg(all(target_feature = "avx2", not(target_feature = "avx512ifma")))]
pub(crate) use self::avx2::{
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 scalar_mul;

View file

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

View file

@ -9,14 +9,18 @@
// - Henry de Valence <hdevalence@hdevalence.ca>
#![no_std]
#![cfg_attr(feature = "ifma_backend", feature(simd_ffi))]
#![cfg_attr(feature = "ifma_backend", feature(link_llvm_intrinsics))]
#![cfg_attr(
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(feature = "nightly", feature(test))]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
#![cfg_attr(feature = "nightly", feature(external_doc))]
// 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
@ -41,21 +45,21 @@ extern crate alloc;
#[macro_use]
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 rand;
extern crate clear_on_drop;
extern crate byteorder;
extern crate clear_on_drop;
pub extern crate digest;
extern crate rand;
// Used for traits related to constant-time code.
extern crate subtle;
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate bincode;
#[cfg(feature = "serde")]
extern crate serde;
// Internal macros. Must come first!
#[macro_use]