Skip to content

Commit d07ce3c

Browse files
committed
Account for possible qemu bug
1 parent e73d029 commit d07ce3c

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

crates/test_helpers/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(stdsimd, powerpc_target_feature)]
2+
13
pub mod array;
24

35
#[cfg(target_arch = "wasm32")]
@@ -198,7 +200,7 @@ pub fn test_unary_elementwise_flush_subnormals<
198200
Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
199201
VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
200202
{
201-
let flush = |x: Scalar| FlushSubnormals::flush(fs(FlushSubnormals::flush(x)));
203+
let flush = |x: Scalar| subnormals::flush(fs(subnormals::flush_in(x)));
202204
test_1(&|x: [Scalar; LANES]| {
203205
proptest::prop_assume!(check(x));
204206
let result_v: [ScalarResult; LANES] = fv(x.into()).into();
@@ -308,7 +310,7 @@ pub fn test_binary_elementwise_flush_subnormals<
308310
VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
309311
{
310312
let flush = |x: Scalar1, y: Scalar2| {
311-
FlushSubnormals::flush(fs(FlushSubnormals::flush(x), FlushSubnormals::flush(y)))
313+
subnormals::flush(fs(subnormals::flush_in(x), subnormals::flush_in(y)))
312314
};
313315
test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| {
314316
proptest::prop_assume!(check(x, y));

crates/test_helpers/src/subnormals.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,38 @@ macro_rules! impl_else {
4141

4242
impl_float! { f32, f64 }
4343
impl_else! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize }
44+
45+
/// AltiVec should flush subnormal inputs to zero, but QEMU seems to only flush outputs.
46+
/// https://gitlab.com/qemu-project/qemu/-/issues/1779
47+
#[cfg(all(target_arch = "powerpc", target_feature = "altivec"))]
48+
fn in_buggy_qemu() -> bool {
49+
use std::sync::OnceLock;
50+
static BUGGY: OnceLock<bool> = OnceLock::new();
51+
52+
fn add(x: f32, y: f32) -> f32 {
53+
use core::arch::powerpc::*;
54+
let array: [f32; 4] =
55+
unsafe { core::mem::transmute(vec_add(vec_splats(x), vec_splats(y))) };
56+
array[0]
57+
}
58+
59+
*BUGGY.get_or_init(|| add(-1.0857398e-38, 0.).is_sign_negative())
60+
}
61+
62+
#[cfg(all(target_arch = "powerpc", target_feature = "altivec"))]
63+
pub fn flush_in<T: FlushSubnormals>(x: T) -> T {
64+
if in_buggy_qemu() {
65+
x
66+
} else {
67+
x.flush()
68+
}
69+
}
70+
71+
#[cfg(not(all(target_arch = "powerpc", target_feature = "altivec")))]
72+
pub fn flush_in<T: FlushSubnormals>(x: T) -> T {
73+
x.flush()
74+
}
75+
76+
pub fn flush<T: FlushSubnormals>(x: T) -> T {
77+
x.flush()
78+
}

0 commit comments

Comments
 (0)