From 91b8469092a34fd100e9a1f27b0ec75d3c625b05 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 2 Aug 2024 21:45:59 -0400 Subject: [PATCH] Update float conversion tests 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]: https://github.com/rust-lang/compiler-builtins/issues/655 --- testcrate/benches/float_extend.rs | 10 ++ testcrate/benches/float_trunc.rs | 6 + testcrate/build.rs | 1 + testcrate/src/lib.rs | 6 +- testcrate/tests/conv.rs | 268 +++++++++++------------------- 5 files changed, 116 insertions(+), 175 deletions(-) diff --git a/testcrate/benches/float_extend.rs b/testcrate/benches/float_extend.rs index 9bd8009e9..0169a99c4 100644 --- a/testcrate/benches/float_extend.rs +++ b/testcrate/benches/float_extend.rs @@ -82,6 +82,7 @@ float_bench! { asm: [], } +#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] criterion_group!( float_extend, extend_f16_f32, @@ -90,4 +91,13 @@ criterion_group!( extend_f32_f128, extend_f64_f128, ); + +#[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); diff --git a/testcrate/benches/float_trunc.rs b/testcrate/benches/float_trunc.rs index 70869bcaf..74b43dfc8 100644 --- a/testcrate/benches/float_trunc.rs +++ b/testcrate/benches/float_trunc.rs @@ -115,6 +115,7 @@ float_bench! { asm: [], } +#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] criterion_group!( float_trunc, trunc_f32_f16, @@ -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); diff --git a/testcrate/build.rs b/testcrate/build.rs index fc01f3f8d..8c441de8a 100644 --- a/testcrate/build.rs +++ b/testcrate/build.rs @@ -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` diff --git a/testcrate/src/lib.rs b/testcrate/src/lib.rs index f9b052528..5458c9ab6 100644 --- a/testcrate/src/lib.rs +++ b/testcrate/src/lib.rs @@ -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),+ @@ -318,7 +320,7 @@ 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; @@ -326,7 +328,7 @@ macro_rules! apfloat_fallback { }}; // 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, diff --git a/testcrate/tests/conv.rs b/testcrate/tests/conv.rs index 1425b49ce..c2bee0acd 100644 --- a/testcrate/tests/conv.rs +++ b/testcrate/tests/conv.rs @@ -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) + ); + } + }) + }; }