Skip to content

Commit

Permalink
Implement copysign for libcalls
Browse files Browse the repository at this point in the history
  • Loading branch information
workingjubilee committed Oct 5, 2024
1 parent 96851fd commit 854585f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/float/bitops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// FIXME: This module existing reflects a failure of the codegen backend to always legalize bitops.
// LLVM should be taught how to always emit llvm.fcopysign for f{16,32,64,128} without needing this!

// FIXME: delete when we move fabs to core and it reaches stable
fn fabs_f32(f: f32) -> f32 {
f32::from_bits(f.to_bits() & const { !(i32::MIN as u32) })
}

// FIXME: delete when we move fabs to core and it reaches stable
fn fabs_f64(f: f64) -> f64 {
f64::from_bits(f.to_bits() & const { !(i64::MIN as u64) })
}

// FIXME: delete when we move fabs to core and it reaches stable
fn fabs_128(f: f128) -> f128 {
f128::from_bits(f.to_bits() & const { !(i128::MIN as u128) })
}

fn copysign_f32(magnitude: f32, sign: f32) -> f32 {
let sign = fabs_f32(sign).to_bits() ^ sign.to_bits();
f32::from_bits(fabs_f32(magnitude).to_bits() | sign)
}

fn copysign_f64(magnitude: f64, sign: f64) -> f64 {
let sign = fabs_f64(sign).to_bits() ^ sign.to_bits();
f64::from_bits(fabs_f64(magnitude).to_bits() | sign)
}

fn copysign_f128(magnitude: f128, sign: f128) -> f128 {
let sign = fabs_128(sign).to_bits() ^ sign.to_bits();
f128::from_bits(fabs_128(magnitude).to_bits() | sign)
}

intrinsics! {
#[cfg_attr(target_env = "msvc", link_name = "_fcopysign")]
pub extern "C" fn fcopysign(magnitude: f32, sign: f32) -> f32 {
copysign_f32(magnitude, sign)
}

#[cfg_attr(target_env = "msvc", link_name = "_copysign")]
pub extern "C" fn copysign(magnitude: f64, sign: f64) -> f64 {
copysign_f64(magnitude, sign)
}

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "powerpc", target_arch = "powerpc64")))]
pub extern "C" fn copysignl(magnitude: f128, sign: f128) -> f128 {
copysign_f128(magnitude, sign)
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86_64", target_arch = "powerpc", target_arch = "powerpc64"))]
pub extern "C" fn copysignf128(magnitude: f128, sign: f128) -> f128 {
copysign_f128(magnitude, sign)
}
}
1 change: 1 addition & 0 deletions src/float/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::ops;
use crate::int::{DInt, Int, MinInt};

pub mod add;
pub mod bitops;
pub mod cmp;
pub mod conv;
pub mod div;
Expand Down

0 comments on commit 854585f

Please sign in to comment.