Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move arch-specific behavior and intrinsics to a separate module #316

Merged
merged 5 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ exclude = ["/ci/", "/.github/workflows/"]
rust-version = "1.63"

[features]
default = []
default = ["arch"]

# Enable architecture-specific features such as SIMD or assembly routines.
arch = []

# This tells the compiler to assume that a Nightly toolchain is being used and
# that it should activate any useful Nightly things accordingly.
Expand Down
12 changes: 12 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ fn main() {
}

configure_intrinsics();
configure_arch();
}

/// Simplify the feature logic for enabling intrinsics so code only needs to use
Expand All @@ -28,3 +29,14 @@ fn configure_intrinsics() {
println!("cargo:rustc-cfg=intrinsics_enabled");
}
}

/// Simplify the feature logic for enabling arch-specific features so code only needs to use
/// `cfg(arch_enabled)`.
fn configure_arch() {
println!("cargo:rustc-check-cfg=cfg(arch_enabled)");

// Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
println!("cargo:rustc-cfg=arch_enabled");
}
}
1 change: 1 addition & 0 deletions ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ fi

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

if [ "${BUILD_ONLY:-}" = "1" ]; then
Expand Down
1 change: 1 addition & 0 deletions crates/compiler-builtins-smoke-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ force-soft-floats = []

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
"cfg(arch_enabled)",
"cfg(assert_no_panic)",
"cfg(intrinsics_enabled)",
] }
19 changes: 18 additions & 1 deletion crates/libm-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ mod musl_serialized_tests {
return;
}

let files = fs::read_dir(math_src).unwrap().map(|f| f.unwrap().path()).collect::<Vec<_>>();
let files = fs::read_dir(math_src)
.unwrap()
.map(|f| f.unwrap().path())
.filter(file_needs_test)
.collect::<Vec<_>>();

let mut math = Vec::new();
for file in files {
Expand Down Expand Up @@ -187,6 +191,19 @@ mod musl_serialized_tests {
generate_unit_tests(&math);
}

/// Check whether a path within `src/math` should get tests generated.
fn file_needs_test(path: &PathBuf) -> bool {
// Skip directories
if path.is_dir() {
return false;
}

let fname = path.file_name().unwrap().to_str().unwrap();

// Musl doesn't support `f16` or `f128`
!(fname.contains("f16") || fname.contains("f128"))
}

/// A "poor man's" parser for the signature of a function
fn parse(s: &str) -> Function {
let s = eat(s, "pub fn ");
Expand Down
37 changes: 37 additions & 0 deletions src/math/arch/i586.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Architecture-specific support for x86-32 without SSE2

use super::super::fabs;

/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn ceil(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
}
}

/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn floor(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
24 changes: 24 additions & 0 deletions src/math/arch/i686.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Architecture-specific support for x86-32 and x86-64 with SSE2

#![cfg(not(feature = "force-soft-floats"))]

#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;

pub fn sqrtf(x: f32) -> f32 {
unsafe {
let m = _mm_set_ss(x);
let m_sqrt = _mm_sqrt_ss(m);
_mm_cvtss_f32(m_sqrt)
}
}

pub fn sqrt(x: f64) -> f64 {
unsafe {
let m = _mm_set_sd(x);
let m_sqrt = _mm_sqrt_pd(m);
_mm_cvtsd_f64(m_sqrt)
}
}
19 changes: 19 additions & 0 deletions src/math/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,22 @@

#[cfg(intrinsics_enabled)]
pub mod intrinsics;

// Most implementations should be defined here, to ensure they are not made available when
// soft floats are required.
#[cfg(arch_enabled)]
cfg_if! {
if #[cfg(target_feature = "sse2")] {
mod i686;
pub use i686::{sqrt, sqrtf};
}
}

// There are certain architecture-specific implementations that are needed for correctness
// even with `force-soft-float`. These are configured here.
cfg_if! {
if #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] {
mod i586;
pub use i586::{ceil, floor};
}
}
19 changes: 1 addition & 18 deletions src/math/ceil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
pub fn ceil(x: f64) -> f64 {
select_implementation! {
name: ceil,
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
use_intrinsic: target_arch = "wasm32",
args: x,
}

#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probably due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let u: u64 = x.to_bits();
let e: i64 = (u >> 52 & 0x7ff) as i64;
let y: f64;
Expand Down
19 changes: 1 addition & 18 deletions src/math/floor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
pub fn floor(x: f64) -> f64 {
select_implementation! {
name: floor,
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
use_intrinsic: target_arch = "wasm32",
args: x,
}

#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probably due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let ui = x.to_bits();
let e = ((ui >> 52) & 0x7ff) as i32;

Expand Down
Loading