Skip to content

Commit

Permalink
Update float conversion tests
Browse files Browse the repository at this point in the history
Since there are more platforms that do not have symbols present, we need
to use `rustc_apfloat` for more conversion tests. Make use of the
fallback like other tests, and refactor so each test gets its own
function.

Previously we were testing both apfloat and system conversion methods
when possible. This changes to only test one or the other, depending on
whether or not the system version is available. This seems reasonable
because it is consistent with all other tests, but we should consider
updating all tests to check both at some point.

This also includes an adjustment of PowerPC configuration to account for
the linking errors at [1].

[1]: #655
  • Loading branch information
tgross35 committed Aug 3, 2024
1 parent 614f96b commit 4872d5e
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 175 deletions.
11 changes: 11 additions & 0 deletions testcrate/benches/float_extend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ float_bench! {
asm: [],
}

#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
criterion_group!(
float_extend,
extend_f16_f32,
Expand All @@ -90,4 +91,14 @@ criterion_group!(
extend_f32_f128,
extend_f64_f128,
);

// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
criterion_group!(
float_extend,
extend_f32_f64,
extend_f32_f128,
extend_f64_f128,
);

criterion_main!(float_extend);
6 changes: 6 additions & 0 deletions testcrate/benches/float_trunc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ float_bench! {
asm: [],
}

#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
criterion_group!(
float_trunc,
trunc_f32_f16,
Expand All @@ -124,4 +125,9 @@ criterion_group!(
trunc_f128_f32,
trunc_f128_f64,
);

// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
criterion_group!(float_trunc, trunc_f64_f32, trunc_f128_f32, trunc_f128_f64,);

criterion_main!(float_trunc);
1 change: 1 addition & 0 deletions testcrate/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ fn main() {
|| target.starts_with("powerpc-")
|| target.starts_with("powerpc64-")
|| target.starts_with("powerpc64le-")
|| target.starts_with("i586-")
|| target.contains("windows-")
// Linking says "error: function signature mismatch: __extendhfsf2" and seems to
// think the signature is either `(i32) -> f32` or `(f32) -> f32`
Expand Down
6 changes: 4 additions & 2 deletions testcrate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ macro_rules! apfloat_fallback {
// The expression to run. This expression may use `FloatTy` for its signature.
// Optionally, the final conversion back to a float can be suppressed using
// `=> no_convert` (for e.g. operations that return a bool).
//
// If the apfloat needs a different operation, it can be provided here.
$op:expr $(=> $convert:ident)? $(; $apfloat_op:expr)?,
// Arguments that get passed to `$op` after converting to a float
$($arg:expr),+
Expand Down Expand Up @@ -318,15 +320,15 @@ macro_rules! apfloat_fallback {

// Some apfloat operations return a `StatusAnd` that we need to extract the value from. This
// is the default.
(@inner fty: $float_ty:ty, op_res: $val:expr, args: $($_arg:expr),+) => {{
(@inner fty: $float_ty:ty, op_res: $val:expr, args: $($_arg:expr),+) => {{
// ignore the status, just get the value
let unwrapped = $val.value;

<$float_ty>::from_bits(FloatTy::to_bits(unwrapped).try_into().unwrap())
}};

// This is the case where we can't use the same expression for the default builtin and
// nonstandard apfloat fallbac (e.g. `as` casts in std are normal functions in apfloat, so
// nonstandard apfloat fallback (e.g. `as` casts in std are normal functions in apfloat, so
// two separate expressions must be specified.
(@inner
fty: $float_ty:ty, op_res: $_val:expr,
Expand Down
268 changes: 95 additions & 173 deletions testcrate/tests/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,212 +206,134 @@ mod f_to_i {
}
}

macro_rules! conv {
($fX:ident, $fD:ident, $fn:ident, $apfloatX:ident, $apfloatD:ident) => {
fuzz_float(N, |x: $fX| {
let tmp0: $apfloatD = $apfloatX::from_bits(x.to_bits().into())
.convert(&mut false)
.value;
let tmp0 = $fD::from_bits(tmp0.to_bits().try_into().unwrap());
let tmp1: $fD = $fn(x);
if !Float::eq_repr(tmp0, tmp1) {
panic!(
"{}({x:?}): apfloat: {tmp0:?}, builtins: {tmp1:?}",
stringify!($fn)
);
}
})
};
}

macro_rules! extend {
($fX:ident, $fD:ident, $fn:ident) => {
macro_rules! f_to_f {
(
$mod:ident,
$(
$from_ty:ty => $to_ty:ty,
$from_ap_ty:ident => $to_ap_ty:ident,
$fn:ident, $sys_available:meta
);+;
) => {$(
#[test]
fn $fn() {
use compiler_builtins::float::extend::$fn;
use compiler_builtins::float::{$mod::$fn, Float};
use rustc_apfloat::ieee::{$from_ap_ty, $to_ap_ty};

fuzz_float(N, |x: $from_ty| {
let tmp0: $to_ty = apfloat_fallback!(
$from_ty,
$from_ap_ty,
$sys_available,
|x: $from_ty| x as $to_ty;
|x: $from_ty| {
let from_apf = FloatTy::from_bits(x.to_bits().into());
// Get `value` directly to ignore INVALID_OP
let to_apf: $to_ap_ty = from_apf.convert(&mut false).value;
<$to_ty>::from_bits(to_apf.to_bits().try_into().unwrap())
},
x
);
let tmp1: $to_ty = $fn(x);

fuzz_float(N, |x: $fX| {
let tmp0 = x as $fD;
let tmp1: $fD = $fn(x);
if !Float::eq_repr(tmp0, tmp1) {
panic!(
"{}({}): std: {}, builtins: {}",
"{}({:?}): std: {:?}, builtins: {:?}",
stringify!($fn),
x,
tmp0,
tmp1
);
}
});
})
}
};
)+};
}

// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
#[cfg(not(target_arch = "powerpc64"))]
mod float_extend {
mod extend {
use super::*;

extend!(f32, f64, __extendsfdf2);

#[test]
fn conv() {
use compiler_builtins::float::extend::__extendsfdf2;
use rustc_apfloat::ieee::{Double, Single};

conv!(f32, f64, __extendsfdf2, Single, Double);
f_to_f! {
extend,
f32 => f64, Single => Double, __extendsfdf2, all();
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_extend_f128 {
use super::*;

#[test]
fn conv() {
use compiler_builtins::float::extend::{
__extenddftf2, __extendhfsf2, __extendhftf2, __extendsftf2, __gnu_h2f_ieee,
};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};

// FIXME(f16_f128): Also do extend!() for `f16` and `f128` when builtins are in nightly
conv!(f16, f32, __extendhfsf2, Half, Single);
conv!(f16, f32, __gnu_h2f_ieee, Half, Single);
conv!(f16, f128, __extendhftf2, Half, Quad);
conv!(f32, f128, __extendsftf2, Single, Quad);
conv!(f64, f128, __extenddftf2, Double, Quad);
#[cfg(target_arch = "arm")]
f_to_f! {
extend,
f32 => f64, Single => Double, __extendsfdf2vfp, all();
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_extend_f128_ppc {
use super::*;

#[test]
fn conv() {
use compiler_builtins::float::extend::{
__extenddfkf2, __extendhfkf2, __extendhfsf2, __extendsfkf2, __gnu_h2f_ieee,
};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};

// FIXME(f16_f128): Also do extend!() for `f16` and `f128` when builtins are in nightly
conv!(f16, f32, __extendhfsf2, Half, Single);
conv!(f16, f32, __gnu_h2f_ieee, Half, Single);
conv!(f16, f128, __extendhfkf2, Half, Quad);
conv!(f32, f128, __extendsfkf2, Single, Quad);
conv!(f64, f128, __extenddfkf2, Double, Quad);
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
extend,
f16 => f32, Half => Single, __extendhfsf2, not(feature = "no-sys-f16");
f16 => f32, Half => Single, __gnu_h2f_ieee, not(feature = "no-sys-f16");
f16 => f128, Half => Quad, __extendhftf2, not(feature = "no-sys-f16-f128-convert");
f32 => f128, Single => Quad, __extendsftf2, not(feature = "no-sys-f128");
f64 => f128, Double => Quad, __extenddftf2, not(feature = "no-sys-f128");
}
}

#[cfg(target_arch = "arm")]
mod float_extend_arm {
use super::*;

extend!(f32, f64, __extendsfdf2vfp);

#[test]
fn conv() {
use compiler_builtins::float::extend::__extendsfdf2vfp;
use rustc_apfloat::ieee::{Double, Single};

conv!(f32, f64, __extendsfdf2vfp, Single, Double);
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
extend,
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
f32 => f128, Single => Quad, __extendsfkf2, not(feature = "no-sys-f128");
f64 => f128, Double => Quad, __extenddfkf2, not(feature = "no-sys-f128");
}
}

macro_rules! trunc {
($fX:ident, $fD:ident, $fn:ident) => {
#[test]
fn $fn() {
use compiler_builtins::float::trunc::$fn;

fuzz_float(N, |x: $fX| {
let tmp0 = x as $fD;
let tmp1: $fD = $fn(x);
if !Float::eq_repr(tmp0, tmp1) {
panic!(
"{}({}): std: {}, builtins: {}",
stringify!($fn),
x,
tmp0,
tmp1
);
}
});
}
};
}

// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
#[cfg(not(target_arch = "powerpc64"))]
mod float_trunc {
mod trunc {
use super::*;

trunc!(f64, f32, __truncdfsf2);

#[test]
fn conv() {
use compiler_builtins::float::trunc::__truncdfsf2;
use rustc_apfloat::ieee::{Double, Single};

conv!(f64, f32, __truncdfsf2, Double, Single);
f_to_f! {
trunc,
f64 => f32, Double => Single, __truncdfsf2, all();
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_trunc_f128 {
use super::*;

#[test]
fn conv() {
use compiler_builtins::float::trunc::{__gnu_f2h_ieee, __truncdfhf2, __truncsfhf2};
use compiler_builtins::float::trunc::{__trunctfdf2, __trunctfhf2, __trunctfsf2};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};

// FIXME(f16_f128): Also do trunc!() for `f16` and `f128` when builtins are in nightly
conv!(f32, f16, __truncsfhf2, Single, Half);
conv!(f32, f16, __gnu_f2h_ieee, Single, Half);
conv!(f64, f16, __truncdfhf2, Double, Half);
conv!(f128, f16, __trunctfhf2, Quad, Half);
conv!(f128, f32, __trunctfsf2, Quad, Single);
conv!(f128, f64, __trunctfdf2, Quad, Double);
#[cfg(target_arch = "arm")]
f_to_f! {
trunc,
f64 => f32, Double => Single, __truncdfsf2vfp, all();
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_trunc_f128_ppc {
use super::*;

#[test]
fn conv() {
use compiler_builtins::float::trunc::{__gnu_f2h_ieee, __truncdfhf2, __truncsfhf2};
use compiler_builtins::float::trunc::{__trunckfdf2, __trunckfhf2, __trunckfsf2};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
trunc,
f32 => f16, Single => Half, __truncsfhf2, not(feature = "no-sys-f16");
f32 => f16, Single => Half, __gnu_f2h_ieee, not(feature = "no-sys-f16");
f128 => f16, Quad => Half, __trunctfhf2, not(feature = "no-sys-f16-f128-convert");
f128 => f32, Quad => Single, __trunctfsf2, not(feature = "no-sys-f128");
f128 => f64, Quad => Double, __trunctfdf2, not(feature = "no-sys-f128");
}

// FIXME(f16_f128): Also do trunc!() for `f16` and `f128` when builtins are in nightly
conv!(f32, f16, __truncsfhf2, Single, Half);
conv!(f32, f16, __gnu_f2h_ieee, Single, Half);
conv!(f64, f16, __truncdfhf2, Double, Half);
conv!(f128, f16, __trunckfhf2, Quad, Half);
conv!(f128, f32, __trunckfsf2, Quad, Single);
conv!(f128, f64, __trunckfdf2, Quad, Double);
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
trunc,
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
f128 => f32, Quad => Single, __trunckfsf2, not(feature = "no-sys-f128");
f128 => f64, Quad => Double, __trunckfdf2, not(feature = "no-sys-f128");
}
}

#[cfg(target_arch = "arm")]
mod float_trunc_arm {
use super::*;

trunc!(f64, f32, __truncdfsf2vfp);

#[test]
fn conv() {
use compiler_builtins::float::trunc::__truncdfsf2vfp;
use rustc_apfloat::ieee::{Double, Single};

conv!(f64, f32, __truncdfsf2vfp, Double, Single)
}
macro_rules! conv {
($fX:ident, $fD:ident, $fn:ident, $apfloatX:ident, $apfloatD:ident) => {
fuzz_float(N, |x: $fX| {
let tmp0: $apfloatD = $apfloatX::from_bits(x.to_bits().into())
.convert(&mut false)
.value;
let tmp0 = $fD::from_bits(tmp0.to_bits().try_into().unwrap());
let tmp1: $fD = $fn(x);
if !Float::eq_repr(tmp0, tmp1) {
panic!(
"{}({x:?}): apfloat: {tmp0:?}, builtins: {tmp1:?}",
stringify!($fn)
);
}
})
};
}

0 comments on commit 4872d5e

Please sign in to comment.