Skip to content

Commit 131704c

Browse files
Rollup merge of rust-lang#161522 - folkertdev:gcc-fma16-correctly-rounded, r=tgross35
test `f16::mul_add` not double-rounding the result test the precision of `f16::mul_add`. The semantics of `mul_add` are that there should only be one rounding of the final result back into the storage type, i.e. the intermediate result of the multiplication should not be rounded. A naive implementation of `f16::mul_add` as `f32::mul_add(a as f32, b as f32, c as f32) as f16` has insufficient precision, see llvm/llvm-project#98389. Our `rustc_codegen_gcc` backend still used the `f32` approach, this PR changes it to instead (implicitly) use the fallback body from `core`, which uses `f64::mul_add` so that the result is correctly rounded.
2 parents 9f7ebfa + a5f0125 commit 131704c

2 files changed

Lines changed: 8 additions & 2 deletions

File tree

  • compiler/rustc_codegen_gcc/src/intrinsic
  • library/coretests/tests/num

โ€Žcompiler/rustc_codegen_gcc/src/intrinsic/mod.rsโ€Ž

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ fn f16_builtin<'gcc, 'tcx>(
171171
sym::exp2f16 => "exp2f",
172172
sym::fabs => "fabsf",
173173
sym::floorf16 => "__builtin_floorf",
174-
sym::fmaf16 => "fmaf",
175174
sym::logf16 => "logf",
176175
sym::log2f16 => "log2f",
177176
sym::log10f16 => "log10f",
@@ -249,7 +248,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
249248
| sym::expf16
250249
| sym::exp2f16
251250
| sym::floorf16
252-
| sym::fmaf16
253251
| sym::logf16
254252
| sym::log2f16
255253
| sym::log10f16

โ€Žlibrary/coretests/tests/num/floats.rsโ€Ž

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ pub(crate) trait TestableFloat: Sized {
5858
const RAW_MINUS_14_DOT_25: Self;
5959
/// The result of 12.3.mul_add(4.5, 6.7)
6060
const MUL_ADD_RESULT: Self;
61+
/// The result of 48.34375.mul_add(0.000013887882, 0.12438965), which checks that f16::mul_add
62+
/// is correctly rounded. A naive implementation via f32::mul_add has insufficient precision.
63+
const F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT: Self;
6164
/// The result of (-12.3).mul_add(-4.5, -6.7)
6265
const NEG_MUL_ADD_RESULT: Self;
6366
/// Reciprocal of the maximum val
@@ -109,6 +112,7 @@ impl TestableFloat for f16 {
109112
const RAW_1337: Self = Self::from_bits(0x6539);
110113
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xcb20);
111114
const MUL_ADD_RESULT: Self = 62.031;
115+
const F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT: Self = 0.1251;
112116
const NEG_MUL_ADD_RESULT: Self = 48.625;
113117
const MAX_RECIP: Self = 1.526624e-5;
114118
const ASINH_ACOSH_MAX: Self = 11.781;
@@ -168,6 +172,7 @@ impl TestableFloat for f32 {
168172
const RAW_1337: Self = Self::from_bits(0x44a72000);
169173
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc1640000);
170174
const MUL_ADD_RESULT: Self = 62.05;
175+
const F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT: Self = 0.12506104;
171176
const NEG_MUL_ADD_RESULT: Self = 48.65;
172177
const MAX_RECIP: Self = 2.938736e-39;
173178
const ASINH_ACOSH_MAX: Self = 89.4159851;
@@ -200,6 +205,7 @@ impl TestableFloat for f64 {
200205
const RAW_1337: Self = Self::from_bits(0x4094e40000000000);
201206
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc02c800000000000);
202207
const MUL_ADD_RESULT: Self = 62.050000000000004;
208+
const F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT: Self = 0.1250610422954375;
203209
const NEG_MUL_ADD_RESULT: Self = 48.650000000000006;
204210
const MAX_RECIP: Self = 5.562684646268003e-309;
205211
const ASINH_ACOSH_MAX: Self = 710.47586007394398;
@@ -242,6 +248,7 @@ impl TestableFloat for f128 {
242248
const RAW_1337: Self = Self::from_bits(0x40094e40000000000000000000000000);
243249
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc002c800000000000000000000000000);
244250
const MUL_ADD_RESULT: Self = 62.0500000000000000000000000000000037;
251+
const F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT: Self = 0.1250610422954375;
245252
const NEG_MUL_ADD_RESULT: Self = 48.6500000000000000000000000000000049;
246253
const MAX_RECIP: Self = 8.40525785778023376565669454330438228902076605e-4933;
247254
const ASINH_ACOSH_MAX: Self = 11357.216553474703894801348310092223;
@@ -1978,6 +1985,7 @@ float_test! {
19781985
let inf: Float = Float::INFINITY;
19791986
let neg_inf: Float = Float::NEG_INFINITY;
19801987
assert_biteq!(flt(12.3).mul_add(flt(4.5), flt(6.7)), Float::MUL_ADD_RESULT);
1988+
assert_biteq!(flt( 48.34375).mul_add(flt(0.000013887882), flt(0.12438965)), Float::F16_NO_DOUBLE_ROUNDING_MUL_ADD_RESULT);
19811989
assert_biteq!((flt(-12.3)).mul_add(flt(-4.5), flt(-6.7)), Float::NEG_MUL_ADD_RESULT);
19821990
assert_biteq!(flt(0.0).mul_add(8.9, 1.2), 1.2);
19831991
assert_biteq!(flt(3.4).mul_add(-0.0, 5.6), 5.6);

0 commit comments

Comments
ย (0)