rust/library/compiler-builtins/builtins-test/tests/div_rem.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

165 lines
5.7 KiB
Rust
Raw Normal View History

#![feature(f128)]
2020-12-11 01:56:36 +00:00
#![allow(unused_macros)]
use builtins_test::*;
2020-08-29 23:02:57 +00:00
use compiler_builtins::int::sdiv::{__divmoddi4, __divmodsi4, __divmodti4};
use compiler_builtins::int::udiv::{__udivmoddi4, __udivmodsi4, __udivmodti4, u128_divide_sparc};
// Division algorithms have by far the nastiest and largest number of edge cases, and experience shows
// that sometimes 100_000 iterations of the random fuzzer is needed.
/// Creates intensive test functions for division functions of a certain size
macro_rules! test {
(
$n:expr, // the number of bits in a $iX or $uX
$uX:ident, // unsigned integer that will be shifted
$iX:ident, // signed version of $uX
$test_name:ident, // name of the test function
$unsigned_name:ident, // unsigned division function
$signed_name:ident // signed division function
) => {
#[test]
fn $test_name() {
fuzz_2(N, |lhs, rhs| {
if rhs == 0 {
return;
}
let mut rem: $uX = 0;
let quo: $uX = $unsigned_name(lhs, rhs, Some(&mut rem));
if rhs <= rem || (lhs != rhs.wrapping_mul(quo).wrapping_add(rem)) {
panic!(
"unsigned division function failed with lhs:{} rhs:{} \
std:({}, {}) builtins:({}, {})",
lhs,
rhs,
lhs.wrapping_div(rhs),
lhs.wrapping_rem(rhs),
quo,
rem
);
}
// test the signed division function also
let lhs = lhs as $iX;
let rhs = rhs as $iX;
let mut rem: $iX = 0;
let quo: $iX = $signed_name(lhs, rhs, &mut rem);
// We cannot just test that
// `lhs == rhs.wrapping_mul(quo).wrapping_add(rem)`, but also
// need to make sure the remainder isn't larger than the divisor
// and has the correct sign.
let incorrect_rem = if rem == 0 {
false
} else if rhs == $iX::MIN {
// `rhs.wrapping_abs()` would overflow, so handle this case
// separately.
(lhs.is_negative() != rem.is_negative()) || (rem == $iX::MIN)
} else {
(lhs.is_negative() != rem.is_negative())
|| (rhs.wrapping_abs() <= rem.wrapping_abs())
};
if incorrect_rem || lhs != rhs.wrapping_mul(quo).wrapping_add(rem) {
panic!(
"signed division function failed with lhs:{} rhs:{} \
std:({}, {}) builtins:({}, {})",
lhs,
rhs,
lhs.wrapping_div(rhs),
lhs.wrapping_rem(rhs),
quo,
rem
);
}
});
}
};
}
test!(32, u32, i32, div_rem_si4, __udivmodsi4, __divmodsi4);
test!(64, u64, i64, div_rem_di4, __udivmoddi4, __divmoddi4);
test!(128, u128, i128, div_rem_ti4, __udivmodti4, __divmodti4);
#[test]
fn divide_sparc() {
fuzz_2(N, |lhs, rhs| {
if rhs == 0 {
return;
}
let mut rem: u128 = 0;
let quo: u128 = u128_divide_sparc(lhs, rhs, &mut rem);
if rhs <= rem || (lhs != rhs.wrapping_mul(quo).wrapping_add(rem)) {
panic!(
"u128_divide_sparc({}, {}): \
std:({}, {}), builtins:({}, {})",
lhs,
rhs,
lhs.wrapping_div(rhs),
lhs.wrapping_rem(rhs),
quo,
rem
);
}
});
}
macro_rules! float {
($($f:ty, $fn:ident, $apfloat_ty:ident, $sys_available:meta);*;) => {
$(
#[test]
fn $fn() {
use compiler_builtins::float::{div::$fn, Float};
use core::ops::Div;
2023-06-25 13:06:18 +00:00
fuzz_float_2(N, |x: $f, y: $f| {
let quo0: $f = apfloat_fallback!($f, $apfloat_ty, $sys_available, Div::div, x, y);
let quo1: $f = $fn(x, y);
// ARM SIMD instructions always flush subnormals to zero
if cfg!(target_arch = "arm") &&
((Float::is_subnormal(quo0)) || Float::is_subnormal(quo1)) {
return;
}
if !Float::eq_repr(quo0, quo1) {
panic!(
"{}({:?}, {:?}): std: {:?}, builtins: {:?}",
stringify!($fn),
x,
y,
quo0,
quo1
);
}
});
}
)*
};
}
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
mod float_div {
use super::*;
float! {
f32, __divsf3, Single, all();
f64, __divdf3, Double, all();
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
float! {
f128, __divtf3, Quad,
// FIXME(llvm): there is a bug in LLVM rt.
// See <https://github.com/llvm/llvm-project/issues/91840>.
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
float! {
f128, __divkf3, Quad, not(feature = "no-sys-f128");
}
}