Account for possible qemu bug

This commit is contained in:
Caleb Zulawski 2023-07-22 17:56:21 -04:00
parent e73d02929a
commit d07ce3cef9
2 changed files with 39 additions and 2 deletions

View File

@ -1,3 +1,5 @@
#![feature(stdsimd, powerpc_target_feature)]
pub mod array;
#[cfg(target_arch = "wasm32")]
@ -198,7 +200,7 @@ pub fn test_unary_elementwise_flush_subnormals<
Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
{
let flush = |x: Scalar| FlushSubnormals::flush(fs(FlushSubnormals::flush(x)));
let flush = |x: Scalar| subnormals::flush(fs(subnormals::flush_in(x)));
test_1(&|x: [Scalar; LANES]| {
proptest::prop_assume!(check(x));
let result_v: [ScalarResult; LANES] = fv(x.into()).into();
@ -308,7 +310,7 @@ pub fn test_binary_elementwise_flush_subnormals<
VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
{
let flush = |x: Scalar1, y: Scalar2| {
FlushSubnormals::flush(fs(FlushSubnormals::flush(x), FlushSubnormals::flush(y)))
subnormals::flush(fs(subnormals::flush_in(x), subnormals::flush_in(y)))
};
test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| {
proptest::prop_assume!(check(x, y));

View File

@ -41,3 +41,38 @@ macro_rules! impl_else {
impl_float! { f32, f64 }
impl_else! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize }
/// AltiVec should flush subnormal inputs to zero, but QEMU seems to only flush outputs.
/// https://gitlab.com/qemu-project/qemu/-/issues/1779
#[cfg(all(target_arch = "powerpc", target_feature = "altivec"))]
fn in_buggy_qemu() -> bool {
use std::sync::OnceLock;
static BUGGY: OnceLock<bool> = OnceLock::new();
fn add(x: f32, y: f32) -> f32 {
use core::arch::powerpc::*;
let array: [f32; 4] =
unsafe { core::mem::transmute(vec_add(vec_splats(x), vec_splats(y))) };
array[0]
}
*BUGGY.get_or_init(|| add(-1.0857398e-38, 0.).is_sign_negative())
}
#[cfg(all(target_arch = "powerpc", target_feature = "altivec"))]
pub fn flush_in<T: FlushSubnormals>(x: T) -> T {
if in_buggy_qemu() {
x
} else {
x.flush()
}
}
#[cfg(not(all(target_arch = "powerpc", target_feature = "altivec")))]
pub fn flush_in<T: FlushSubnormals>(x: T) -> T {
x.flush()
}
pub fn flush<T: FlushSubnormals>(x: T) -> T {
x.flush()
}