Skip to content

Commit e3971e6

Browse files
committed
Unify addcarry probing for x86_64/x86
1 parent 0cc50c9 commit e3971e6

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

build.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@ fn main() {
1111
autocfg::emit("u64_digit");
1212
}
1313
let ac = autocfg::new();
14-
if ac.probe_path("std::convert::TryFrom") || ac.probe_path("core::convert::TryFrom") {
14+
let std = if ac.probe_sysroot_crate("std") {
15+
"std"
16+
} else {
17+
"core"
18+
};
19+
if ac.probe_path(&format!("{}::convert::TryFrom", std)) {
1520
autocfg::emit("has_try_from");
1621
}
1722

18-
if u64_digit
19-
&& (ac.probe_path("core::arch::x86_64::_addcarry_u64")
20-
|| ac.probe_path("std::arch::x86_64::_addcarry_u64"))
21-
{
22-
autocfg::emit("use_addcarry_u64");
23-
} else if !u64_digit
24-
&& (ac.probe_path("core::arch::x86_64::_addcarry_u32")
25-
|| ac.probe_path("core::arch::x86::_addcarry_u32"))
26-
{
27-
autocfg::emit("use_addcarry_u32");
23+
if let Ok(target_arch) = env::var("CARGO_CFG_TARGET_ARCH") {
24+
if target_arch == "x86_64" || target_arch == "x86" {
25+
let digit = if u64_digit { "u64" } else { "u32" };
26+
27+
let addcarry = format!("{}::arch::{}::_addcarry_{}", std, target_arch, digit);
28+
if ac.probe_path(&addcarry) {
29+
autocfg::emit("use_addcarry");
30+
}
31+
}
2832
}
2933

3034
autocfg::rerun_path("build.rs");

src/algorithms.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ use core::iter::repeat;
55
use core::mem;
66
use num_traits::{One, PrimInt, Zero};
77

8+
#[cfg(all(use_addcarry, target_arch = "x86_64"))]
9+
use core::arch::x86_64 as arch;
10+
11+
#[cfg(all(use_addcarry, target_arch = "x86"))]
12+
use core::arch::x86 as arch;
13+
814
use crate::biguint::biguint_from_vec;
915
use crate::biguint::BigUint;
1016

@@ -15,31 +21,35 @@ use crate::bigint::Sign::{Minus, NoSign, Plus};
1521
use crate::big_digit::{self, BigDigit, DoubleBigDigit};
1622

1723
// only needed for the fallback implementation of `sbb`
18-
#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))]
24+
#[cfg(not(use_addcarry))]
1925
use crate::big_digit::SignedDoubleBigDigit;
2026

21-
// Generic functions for add/subtract/multiply with carry/borrow. These are specialized for some platforms to take advantage of intrinsics etc
27+
// Generic functions for add/subtract/multiply with carry/borrow. These are specialized
28+
// for some platforms to take advantage of intrinsics, etc.
2229

2330
// Add with carry:
24-
#[cfg(use_addcarry_u64)]
31+
#[cfg(all(use_addcarry, u64_digit))]
2532
#[inline]
2633
fn adc(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit {
2734
let mut out = 0;
28-
// Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics
29-
*acc = unsafe { core::arch::x86_64::_addcarry_u64(*acc, a, b, &mut out) };
35+
// Safety: There are absolutely no safety concerns with calling `_addcarry_u64`.
36+
// It's just unsafe for API consistency with other intrinsics.
37+
*acc = unsafe { arch::_addcarry_u64(*acc, a, b, &mut out) };
3038
out
3139
}
3240

33-
#[cfg(use_addcarry_u32)]
41+
#[cfg(all(use_addcarry, not(u64_digit)))]
3442
#[inline]
3543
fn adc(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit {
3644
let mut out = 0;
37-
// Safety: There are absolutely no safety concerns with calling _addcarry_u32, it's just unsafe for API consistency with other intrinsics
38-
*acc = unsafe { core::arch::x86_64::_addcarry_u32(*acc, a, b, &mut out) };
45+
// Safety: There are absolutely no safety concerns with calling `_addcarry_u32`.
46+
// It's just unsafe for API consistency with other intrinsics.
47+
*acc = unsafe { arch::_addcarry_u32(*acc, a, b, &mut out) };
3948
out
4049
}
4150

42-
#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))] // fallback for environments where we don't have an addcarry intrinsic
51+
// fallback for environments where we don't have an addcarry intrinsic
52+
#[cfg(not(use_addcarry))]
4353
#[inline]
4454
fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
4555
*acc += DoubleBigDigit::from(a);
@@ -50,24 +60,28 @@ fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
5060
}
5161

5262
// Subtract with borrow:
53-
#[cfg(use_addcarry_u64)]
63+
#[cfg(all(use_addcarry, u64_digit))]
5464
#[inline]
5565
fn sbb(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit {
5666
let mut out = 0;
57-
// Safety: There are absolutely no safety concerns with calling _subborrow_u64, it's just unsafe for API consistency with other intrinsics
58-
*acc = unsafe { core::arch::x86_64::_subborrow_u64(*acc, a, b, &mut out) };
67+
// Safety: There are absolutely no safety concerns with calling `_subborrow_u64`.
68+
// It's just unsafe for API consistency with other intrinsics.
69+
*acc = unsafe { arch::_subborrow_u64(*acc, a, b, &mut out) };
5970
out
6071
}
61-
#[cfg(use_addcarry_u32)]
72+
73+
#[cfg(all(use_addcarry, not(u64_digit)))]
6274
#[inline]
6375
fn sbb(a: BigDigit, b: BigDigit, acc: &mut u8) -> BigDigit {
6476
let mut out = 0;
65-
// Safety: There are absolutely no safety concerns with calling _subborrow_u32, it's just unsafe for API consistency with other intrinsics
66-
*acc = unsafe { core::arch::x86_64::_subborrow_u32(*acc, a, b, &mut out) };
77+
// Safety: There are absolutely no safety concerns with calling `_subborrow_u32`.
78+
// It's just unsafe for API consistency with other intrinsics.
79+
*acc = unsafe { arch::_subborrow_u32(*acc, a, b, &mut out) };
6780
out
6881
}
6982

70-
#[cfg(not(any(use_addcarry_u64, use_addcarry_u32)))] // fallback for environments where we don't have an addcarry intrinsic
83+
// fallback for environments where we don't have an addcarry intrinsic
84+
#[cfg(not(use_addcarry))]
7185
#[inline]
7286
fn sbb(a: BigDigit, b: BigDigit, acc: &mut SignedDoubleBigDigit) -> BigDigit {
7387
*acc += SignedDoubleBigDigit::from(a);

0 commit comments

Comments
 (0)