From e3971e6558c2140ea09da13b1726e573969c7950 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 30 Oct 2020 13:04:50 -0700 Subject: [PATCH] Unify addcarry probing for x86_64/x86 --- build.rs | 26 +++++++++++++++----------- src/algorithms.rs | 46 ++++++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/build.rs b/build.rs index 0aea8629..3daed5e8 100644 --- a/build.rs +++ b/build.rs @@ -11,20 +11,24 @@ fn main() { autocfg::emit("u64_digit"); } let ac = autocfg::new(); - if ac.probe_path("std::convert::TryFrom") || ac.probe_path("core::convert::TryFrom") { + let std = if ac.probe_sysroot_crate("std") { + "std" + } else { + "core" + }; + if ac.probe_path(&format!("{}::convert::TryFrom", std)) { autocfg::emit("has_try_from"); } - if u64_digit - && (ac.probe_path("core::arch::x86_64::_addcarry_u64") - || ac.probe_path("std::arch::x86_64::_addcarry_u64")) - { - autocfg::emit("use_addcarry_u64"); - } else if !u64_digit - && (ac.probe_path("core::arch::x86_64::_addcarry_u32") - || ac.probe_path("core::arch::x86::_addcarry_u32")) - { - autocfg::emit("use_addcarry_u32"); + if let Ok(target_arch) = env::var("CARGO_CFG_TARGET_ARCH") { + if target_arch == "x86_64" || target_arch == "x86" { + let digit = if u64_digit { "u64" } else { "u32" }; + + let addcarry = format!("{}::arch::{}::_addcarry_{}", std, target_arch, digit); + if ac.probe_path(&addcarry) { + autocfg::emit("use_addcarry"); + } + } } autocfg::rerun_path("build.rs"); diff --git a/src/algorithms.rs b/src/algorithms.rs index d441fb55..89fc35fe 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -5,6 +5,12 @@ use core::iter::repeat; use core::mem; use num_traits::{One, PrimInt, Zero}; +#[cfg(all(use_addcarry, target_arch = "x86_64"))] +use core::arch::x86_64 as arch; + +#[cfg(all(use_addcarry, target_arch = "x86"))] +use core::arch::x86 as arch; + use crate::biguint::biguint_from_vec; use crate::biguint::BigUint; @@ -15,31 +21,35 @@ use crate::bigint::Sign::{Minus, NoSign, Plus}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; // only needed for the fallback implementation of `sbb` -#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))] +#[cfg(not(use_addcarry))] use crate::big_digit::SignedDoubleBigDigit; -// Generic functions for add/subtract/multiply with carry/borrow. These are specialized for some platforms to take advantage of intrinsics etc +// Generic functions for add/subtract/multiply with carry/borrow. These are specialized +// for some platforms to take advantage of intrinsics, etc. // Add with carry: -#[cfg(use_addcarry_u64)] +#[cfg(all(use_addcarry, u64_digit))] #[inline] fn adc(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit { let mut out = 0; - // Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics - *acc = unsafe { core::arch::x86_64::_addcarry_u64(*acc, a, b, &mut out) }; + // Safety: There are absolutely no safety concerns with calling `_addcarry_u64`. + // It's just unsafe for API consistency with other intrinsics. + *acc = unsafe { arch::_addcarry_u64(*acc, a, b, &mut out) }; out } -#[cfg(use_addcarry_u32)] +#[cfg(all(use_addcarry, not(u64_digit)))] #[inline] fn adc(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit { let mut out = 0; - // Safety: There are absolutely no safety concerns with calling _addcarry_u32, it's just unsafe for API consistency with other intrinsics - *acc = unsafe { core::arch::x86_64::_addcarry_u32(*acc, a, b, &mut out) }; + // Safety: There are absolutely no safety concerns with calling `_addcarry_u32`. + // It's just unsafe for API consistency with other intrinsics. + *acc = unsafe { arch::_addcarry_u32(*acc, a, b, &mut out) }; out } -#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))] // fallback for environments where we don't have an addcarry intrinsic +// fallback for environments where we don't have an addcarry intrinsic +#[cfg(not(use_addcarry))] #[inline] fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { *acc += DoubleBigDigit::from(a); @@ -50,24 +60,28 @@ fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { } // Subtract with borrow: -#[cfg(use_addcarry_u64)] +#[cfg(all(use_addcarry, u64_digit))] #[inline] fn sbb(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit { let mut out = 0; - // Safety: There are absolutely no safety concerns with calling _subborrow_u64, it's just unsafe for API consistency with other intrinsics - *acc = unsafe { core::arch::x86_64::_subborrow_u64(*acc, a, b, &mut out) }; + // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. + // It's just unsafe for API consistency with other intrinsics. + *acc = unsafe { arch::_subborrow_u64(*acc, a, b, &mut out) }; out } -#[cfg(use_addcarry_u32)] + +#[cfg(all(use_addcarry, not(u64_digit)))] #[inline] fn sbb(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit { let mut out = 0; - // Safety: There are absolutely no safety concerns with calling _subborrow_u32, it's just unsafe for API consistency with other intrinsics - *acc = unsafe { core::arch::x86_64::_subborrow_u32(*acc, a, b, &mut out) }; + // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. + // It's just unsafe for API consistency with other intrinsics. + *acc = unsafe { arch::_subborrow_u32(*acc, a, b, &mut out) }; out } -#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))] // fallback for environments where we don't have an addcarry intrinsic +// fallback for environments where we don't have an addcarry intrinsic +#[cfg(not(use_addcarry))] #[inline] fn sbb(a: BigDigit, b: BigDigit, acc: &mut SignedDoubleBigDigit) -> BigDigit { *acc += SignedDoubleBigDigit::from(a);