Skip to content

Commit 2a57557

Browse files
committed
Auto merge of #131581 - tgross35:rollup-vul4kol, r=tgross35
Rollup of 7 pull requests Successful merges: - #124874 (intrinsics fmuladdf{32,64}: expose llvm.fmuladd.* semantics) - #130962 (Migrate lib's `&Option<T>` into `Option<&T>`) - #131289 (stabilize duration_consts_float) - #131310 (Support clobber_abi in MSP430 inline assembly) - #131546 (Make unused_parens's suggestion considering expr's attributes.) - #131565 (Remove deprecation note in the `non_local_definitions` lint) - #131576 (Flatten redundant test module `run_make_support::diff::tests::tests`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents ec6a41b + eb7f900 commit 2a57557

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

src/intrinsics/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
295295
this.write_scalar(res, dest)?;
296296
}
297297

298+
"fmuladdf32" => {
299+
let [a, b, c] = check_arg_count(args)?;
300+
let a = this.read_scalar(a)?.to_f32()?;
301+
let b = this.read_scalar(b)?.to_f32()?;
302+
let c = this.read_scalar(c)?.to_f32()?;
303+
let fuse: bool = this.machine.rng.get_mut().gen();
304+
let res = if fuse {
305+
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
306+
a.to_host().mul_add(b.to_host(), c.to_host()).to_soft()
307+
} else {
308+
((a * b).value + c).value
309+
};
310+
let res = this.adjust_nan(res, &[a, b, c]);
311+
this.write_scalar(res, dest)?;
312+
}
313+
"fmuladdf64" => {
314+
let [a, b, c] = check_arg_count(args)?;
315+
let a = this.read_scalar(a)?.to_f64()?;
316+
let b = this.read_scalar(b)?.to_f64()?;
317+
let c = this.read_scalar(c)?.to_f64()?;
318+
let fuse: bool = this.machine.rng.get_mut().gen();
319+
let res = if fuse {
320+
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
321+
a.to_host().mul_add(b.to_host(), c.to_host()).to_soft()
322+
} else {
323+
((a * b).value + c).value
324+
};
325+
let res = this.adjust_nan(res, &[a, b, c]);
326+
this.write_scalar(res, dest)?;
327+
}
328+
298329
"powf32" => {
299330
let [f1, f2] = check_arg_count(args)?;
300331
let f1 = this.read_scalar(f1)?.to_f32()?;

tests/pass/float.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn main() {
3030
libm();
3131
test_fast();
3232
test_algebraic();
33+
test_fmuladd();
3334
}
3435

3536
trait Float: Copy + PartialEq + Debug {
@@ -1041,3 +1042,20 @@ fn test_algebraic() {
10411042
test_operations_f32(11., 2.);
10421043
test_operations_f32(10., 15.);
10431044
}
1045+
1046+
fn test_fmuladd() {
1047+
use std::intrinsics::{fmuladdf32, fmuladdf64};
1048+
1049+
#[inline(never)]
1050+
pub fn test_operations_f32(a: f32, b: f32, c: f32) {
1051+
assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c);
1052+
}
1053+
1054+
#[inline(never)]
1055+
pub fn test_operations_f64(a: f64, b: f64, c: f64) {
1056+
assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c);
1057+
}
1058+
1059+
test_operations_f32(0.1, 0.2, 0.3);
1060+
test_operations_f64(1.1, 1.2, 1.3);
1061+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![feature(core_intrinsics)]
2+
use std::intrinsics::{fmuladdf32, fmuladdf64};
3+
4+
fn main() {
5+
let mut saw_zero = false;
6+
let mut saw_nonzero = false;
7+
for _ in 0..50 {
8+
let a = std::hint::black_box(0.1_f64);
9+
let b = std::hint::black_box(0.2);
10+
let c = std::hint::black_box(-a * b);
11+
// It is unspecified whether the following operation is fused or not. The
12+
// following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused.
13+
let x = unsafe { fmuladdf64(a, b, c) };
14+
if x == 0.0 {
15+
saw_zero = true;
16+
} else {
17+
saw_nonzero = true;
18+
}
19+
}
20+
assert!(
21+
saw_zero && saw_nonzero,
22+
"`fmuladdf64` failed to be evaluated as both fused and unfused"
23+
);
24+
25+
let mut saw_zero = false;
26+
let mut saw_nonzero = false;
27+
for _ in 0..50 {
28+
let a = std::hint::black_box(0.1_f32);
29+
let b = std::hint::black_box(0.2);
30+
let c = std::hint::black_box(-a * b);
31+
// It is unspecified whether the following operation is fused or not. The
32+
// following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused.
33+
let x = unsafe { fmuladdf32(a, b, c) };
34+
if x == 0.0 {
35+
saw_zero = true;
36+
} else {
37+
saw_nonzero = true;
38+
}
39+
}
40+
assert!(
41+
saw_zero && saw_nonzero,
42+
"`fmuladdf32` failed to be evaluated as both fused and unfused"
43+
);
44+
}

0 commit comments

Comments
 (0)