Skip to content

Commit c1c8fcc

Browse files
authored
Merge pull request #637 from beetrees/fix-float-mul
Fix incorrect rounding with subnormal/zero results of float multiplication
2 parents 7a84ce4 + 254edbc commit c1c8fcc

File tree

4 files changed

+34
-25
lines changed

4 files changed

+34
-25
lines changed

src/float/mul.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,13 @@ where
149149
}
150150

151151
// Otherwise, shift the significand of the result so that the round
152-
// bit is the high bit of productLo.
153-
if shift < bits {
154-
let sticky = product_low << (bits - shift);
155-
product_low = product_high << (bits - shift) | product_low >> shift | sticky;
156-
product_high >>= shift;
157-
} else if shift < (2 * bits) {
158-
let sticky = product_high << (2 * bits - shift) | product_low;
159-
product_low = product_high >> (shift - bits) | sticky;
160-
product_high = zero;
161-
} else {
162-
product_high = zero;
163-
}
152+
// bit is the high bit of `product_low`.
153+
// Ensure one of the non-highest bits in `product_low` is set if the shifted out bit are
154+
// not all zero so that the result is correctly rounded below.
155+
let sticky = product_low << (bits - shift) != zero;
156+
product_low =
157+
product_high << (bits - shift) | product_low >> shift | (sticky as u32).cast();
158+
product_high >>= shift;
164159
} else {
165160
// Result is normal before rounding; insert the exponent.
166161
product_high &= significand_mask;

src/probestack.rs

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ macro_rules! define_rust_probestack {
120120
};
121121
}
122122

123+
// FIXME(rust-lang/rust#126984): Remove allow once lint is fixed
124+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
125+
use define_rust_probestack;
126+
123127
// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
124128
// ensuring that if any pages are unmapped we'll make a page fault.
125129
//

testcrate/src/bench.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
1717
"extend_f16_f32",
1818
"trunc_f32_f16",
1919
"trunc_f64_f16",
20-
// FIXME(f16_f128): rounding error
20+
// FIXME(#616): re-enable once fix is in nightly
2121
// <https://github.com/rust-lang/compiler-builtins/issues/616>
22-
"mul_f128",
22+
"mul_f32",
23+
"mul_f64",
2324
];
2425

2526
// FIXME(f16_f128): error on LE ppc64. There are more tests that are cfg-ed out completely
@@ -29,7 +30,13 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
2930

3031
// FIXME(f16_f128): system symbols have incorrect results
3132
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2125914639>
32-
const X86_NO_SSE_SKIPPED: &[&str] = &["add_f128", "sub_f128", "powi_f32", "powi_f64"];
33+
const X86_NO_SSE_SKIPPED: &[&str] =
34+
&["add_f128", "sub_f128", "mul_f128", "powi_f32", "powi_f64"];
35+
36+
// FIXME(f16_f128): Wide multiply carry bug in `compiler-rt`, re-enable when nightly no longer
37+
// uses `compiler-rt` version.
38+
// <https://github.com/llvm/llvm-project/issues/91840>
39+
const AARCH64_SKIPPED: &[&str] = &["mul_f128"];
3340

3441
// FIXME(llvm): system symbols have incorrect results on Windows
3542
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2121359807>
@@ -61,6 +68,10 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
6168
return true;
6269
}
6370

71+
if cfg!(target_arch = "aarch64") && AARCH64_SKIPPED.contains(&test_name) {
72+
return true;
73+
}
74+
6475
if cfg!(target_family = "windows") && WINDOWS_SKIPPED.contains(&test_name) {
6576
return true;
6677
}

testcrate/tests/mul.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,11 @@ macro_rules! float_mul {
107107
fuzz_float_2(N, |x: $f, y: $f| {
108108
let mul0 = apfloat_fallback!($f, $apfloat_ty, $sys_available, Mul::mul, x, y);
109109
let mul1: $f = $fn(x, y);
110-
// multiplication of subnormals is not currently handled
111-
if !(Float::is_subnormal(mul0) || Float::is_subnormal(mul1)) {
112-
if !Float::eq_repr(mul0, mul1) {
113-
panic!(
114-
"{}({:?}, {:?}): std: {:?}, builtins: {:?}",
115-
stringify!($fn), x, y, mul0, mul1
116-
);
117-
}
110+
if !Float::eq_repr(mul0, mul1) {
111+
panic!(
112+
"{}({:?}, {:?}): std: {:?}, builtins: {:?}",
113+
stringify!($fn), x, y, mul0, mul1
114+
);
118115
}
119116
});
120117
}
@@ -126,9 +123,11 @@ macro_rules! float_mul {
126123
mod float_mul {
127124
use super::*;
128125

126+
// FIXME(#616): Stop ignoring arches that don't have native support once fix for builtins is in
127+
// nightly.
129128
float_mul! {
130-
f32, __mulsf3, Single, all();
131-
f64, __muldf3, Double, all();
129+
f32, __mulsf3, Single, not(target_arch = "arm");
130+
f64, __muldf3, Double, not(target_arch = "arm");
132131
}
133132
}
134133

0 commit comments

Comments
 (0)