Skip to content

Commit d9bfeca

Browse files
authored
Merge pull request rust-lang#316 from tgross35/arch-module
Move arch-specific behavior and intrinsics to a separate module
2 parents e299027 + 586962f commit d9bfeca

File tree

13 files changed

+376
-257
lines changed

13 files changed

+376
-257
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ exclude = ["/ci/", "/.github/workflows/"]
1414
rust-version = "1.63"
1515

1616
[features]
17-
default = []
17+
default = ["arch"]
18+
19+
# Enable architecture-specific features such as SIMD or assembly routines.
20+
arch = []
1821

1922
# This tells the compiler to assume that a Nightly toolchain is being used and
2023
# that it should activate any useful Nightly things accordingly.

build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ fn main() {
1515
}
1616

1717
configure_intrinsics();
18+
configure_arch();
1819
}
1920

2021
/// Simplify the feature logic for enabling intrinsics so code only needs to use
@@ -28,3 +29,14 @@ fn configure_intrinsics() {
2829
println!("cargo:rustc-cfg=intrinsics_enabled");
2930
}
3031
}
32+
33+
/// Simplify the feature logic for enabling arch-specific features so code only needs to use
34+
/// `cfg(arch_enabled)`.
35+
fn configure_arch() {
36+
println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
37+
38+
// Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
39+
if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
40+
println!("cargo:rustc-cfg=arch_enabled");
41+
}
42+
}

ci/run.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ fi
6464

6565
# Make sure we can build with overriding features. We test the indibidual
6666
# features it controls separately.
67+
cargo check --no-default-features
6768
cargo check --features "force-soft-floats"
6869

6970
if [ "${BUILD_ONLY:-}" = "1" ]; then

crates/compiler-builtins-smoke-test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ force-soft-floats = []
1818

1919
[lints.rust]
2020
unexpected_cfgs = { level = "warn", check-cfg = [
21+
"cfg(arch_enabled)",
2122
"cfg(assert_no_panic)",
2223
"cfg(intrinsics_enabled)",
2324
] }

crates/libm-test/build.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ mod musl_serialized_tests {
156156
return;
157157
}
158158

159-
let files = fs::read_dir(math_src).unwrap().map(|f| f.unwrap().path()).collect::<Vec<_>>();
159+
let files = fs::read_dir(math_src)
160+
.unwrap()
161+
.map(|f| f.unwrap().path())
162+
.filter(file_needs_test)
163+
.collect::<Vec<_>>();
160164

161165
let mut math = Vec::new();
162166
for file in files {
@@ -187,6 +191,19 @@ mod musl_serialized_tests {
187191
generate_unit_tests(&math);
188192
}
189193

194+
/// Check whether a path within `src/math` should get tests generated.
195+
fn file_needs_test(path: &PathBuf) -> bool {
196+
// Skip directories
197+
if path.is_dir() {
198+
return false;
199+
}
200+
201+
let fname = path.file_name().unwrap().to_str().unwrap();
202+
203+
// Musl doesn't support `f16` or `f128`
204+
!(fname.contains("f16") || fname.contains("f128"))
205+
}
206+
190207
/// A "poor man's" parser for the signature of a function
191208
fn parse(s: &str) -> Function {
192209
let s = eat(s, "pub fn ");

src/math/arch/i586.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! Architecture-specific support for x86-32 without SSE2
2+
3+
use super::super::fabs;
4+
5+
/// Use an alternative implementation on x86, because the
6+
/// main implementation fails with the x87 FPU used by
7+
/// debian i386, probably due to excess precision issues.
8+
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
9+
pub fn ceil(x: f64) -> f64 {
10+
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
11+
let truncated = x as i64 as f64;
12+
if truncated < x {
13+
return truncated + 1.0;
14+
} else {
15+
return truncated;
16+
}
17+
} else {
18+
return x;
19+
}
20+
}
21+
22+
/// Use an alternative implementation on x86, because the
23+
/// main implementation fails with the x87 FPU used by
24+
/// debian i386, probably due to excess precision issues.
25+
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
26+
pub fn floor(x: f64) -> f64 {
27+
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
28+
let truncated = x as i64 as f64;
29+
if truncated > x {
30+
return truncated - 1.0;
31+
} else {
32+
return truncated;
33+
}
34+
} else {
35+
return x;
36+
}
37+
}

src/math/arch/i686.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! Architecture-specific support for x86-32 and x86-64 with SSE2
2+
3+
#![cfg(not(feature = "force-soft-floats"))]
4+
5+
#[cfg(target_arch = "x86")]
6+
use core::arch::x86::*;
7+
#[cfg(target_arch = "x86_64")]
8+
use core::arch::x86_64::*;
9+
10+
pub fn sqrtf(x: f32) -> f32 {
11+
unsafe {
12+
let m = _mm_set_ss(x);
13+
let m_sqrt = _mm_sqrt_ss(m);
14+
_mm_cvtss_f32(m_sqrt)
15+
}
16+
}
17+
18+
pub fn sqrt(x: f64) -> f64 {
19+
unsafe {
20+
let m = _mm_set_sd(x);
21+
let m_sqrt = _mm_sqrt_pd(m);
22+
_mm_cvtsd_f64(m_sqrt)
23+
}
24+
}

src/math/arch/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,22 @@
77
88
#[cfg(intrinsics_enabled)]
99
pub mod intrinsics;
10+
11+
// Most implementations should be defined here, to ensure they are not made available when
12+
// soft floats are required.
13+
#[cfg(arch_enabled)]
14+
cfg_if! {
15+
if #[cfg(target_feature = "sse2")] {
16+
mod i686;
17+
pub use i686::{sqrt, sqrtf};
18+
}
19+
}
20+
21+
// There are certain architecture-specific implementations that are needed for correctness
22+
// even with `force-soft-float`. These are configured here.
23+
cfg_if! {
24+
if #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] {
25+
mod i586;
26+
pub use i586::{ceil, floor};
27+
}
28+
}

src/math/ceil.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
1010
pub fn ceil(x: f64) -> f64 {
1111
select_implementation! {
1212
name: ceil,
13+
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
1314
use_intrinsic: target_arch = "wasm32",
1415
args: x,
1516
}
1617

17-
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
18-
{
19-
//use an alternative implementation on x86, because the
20-
//main implementation fails with the x87 FPU used by
21-
//debian i386, probably due to excess precision issues.
22-
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
23-
use super::fabs;
24-
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
25-
let truncated = x as i64 as f64;
26-
if truncated < x {
27-
return truncated + 1.0;
28-
} else {
29-
return truncated;
30-
}
31-
} else {
32-
return x;
33-
}
34-
}
3518
let u: u64 = x.to_bits();
3619
let e: i64 = (u >> 52 & 0x7ff) as i64;
3720
let y: f64;

src/math/floor.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
1010
pub fn floor(x: f64) -> f64 {
1111
select_implementation! {
1212
name: floor,
13+
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
1314
use_intrinsic: target_arch = "wasm32",
1415
args: x,
1516
}
1617

17-
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
18-
{
19-
//use an alternative implementation on x86, because the
20-
//main implementation fails with the x87 FPU used by
21-
//debian i386, probably due to excess precision issues.
22-
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
23-
use super::fabs;
24-
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
25-
let truncated = x as i64 as f64;
26-
if truncated > x {
27-
return truncated - 1.0;
28-
} else {
29-
return truncated;
30-
}
31-
} else {
32-
return x;
33-
}
34-
}
3518
let ui = x.to_bits();
3619
let e = ((ui >> 52) & 0x7ff) as i32;
3720

0 commit comments

Comments
 (0)