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
This commit is contained in:
parent
b6c2b6ebf7
commit
e0e6243b21
5 changed files with 110 additions and 186 deletions
|
|
@ -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,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -206,212 +206,116 @@ 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! 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::{$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);
|
||||
|
||||
macro_rules! extend {
|
||||
($fX:ident, $fD:ident, $fn:ident) => {
|
||||
#[test]
|
||||
fn $fn() {
|
||||
use compiler_builtins::float::extend::$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: {}",
|
||||
"{}({:?}): 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);
|
||||
f_to_f! {
|
||||
extend,
|
||||
f32 => f64, Single => Double, __extendsfdf2, all();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conv() {
|
||||
use compiler_builtins::float::extend::__extendsfdf2;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
#[cfg(target_arch = "arm")]
|
||||
f_to_f! {
|
||||
extend,
|
||||
f32 => f64, Single => Double, __extendsfdf2vfp, all();
|
||||
}
|
||||
|
||||
conv!(f32, f64, __extendsfdf2, Single, Double);
|
||||
#[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(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");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-f16-f128"))]
|
||||
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
|
||||
mod float_extend_f128 {
|
||||
mod trunc {
|
||||
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};
|
||||
f_to_f! {
|
||||
trunc,
|
||||
f64 => f32, Double => Single, __truncdfsf2, all();
|
||||
}
|
||||
|
||||
// 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(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(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);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#[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(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};
|
||||
|
||||
// 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(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)
|
||||
#[cfg(target_arch = "arm")]
|
||||
f_to_f! {
|
||||
trunc,
|
||||
f64 => f32, Double => Single, __truncdfsf2vfp, all();
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue