Merge pull request #764 from RalfJung/minmax
implement min and max floating point intrinsics
This commit is contained in:
commit
deb0ff46eb
@ -1 +1 @@
|
|||||||
1cbd8a4d686d1411105f26cddf876c5994e69593
|
8e948df707ea8a3c88c65bf2ffdcb2f1cf5491be
|
||||||
|
@ -758,7 +758,7 @@ fn emulate_foreign_item(
|
|||||||
this.machine.last_error = err;
|
this.machine.last_error = err;
|
||||||
}
|
}
|
||||||
"GetLastError" => {
|
"GetLastError" => {
|
||||||
this.write_scalar(Scalar::from_uint(this.machine.last_error, Size::from_bits(32)), dest)?;
|
this.write_scalar(Scalar::from_u32(this.machine.last_error), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"AddVectoredExceptionHandler" => {
|
"AddVectoredExceptionHandler" => {
|
||||||
@ -854,7 +854,7 @@ fn emulate_foreign_item(
|
|||||||
};
|
};
|
||||||
// If there was no error, write back how much was written.
|
// If there was no error, write back how much was written.
|
||||||
if let Some(n) = written {
|
if let Some(n) = written {
|
||||||
this.write_scalar(Scalar::from_uint(n, Size::from_bits(32)), written_place.into())?;
|
this.write_scalar(Scalar::from_u32(n), written_place.into())?;
|
||||||
}
|
}
|
||||||
// Return whether this was a success.
|
// Return whether this was a success.
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use rustc_apfloat::Float;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::interpret::{InterpResult, PointerArithmetic};
|
use rustc::mir::interpret::{InterpResult, PointerArithmetic};
|
||||||
use rustc::ty::layout::{self, LayoutOf, Size};
|
use rustc::ty::layout::{self, LayoutOf, Size};
|
||||||
@ -186,7 +187,8 @@ fn call_intrinsic(
|
|||||||
|
|
||||||
"sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" |
|
"sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" |
|
||||||
"log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" => {
|
"log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f32()?;
|
// FIXME: Using host floats.
|
||||||
|
let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?);
|
||||||
let f = match intrinsic_name.get() {
|
let f = match intrinsic_name.get() {
|
||||||
"sinf32" => f.sin(),
|
"sinf32" => f.sin(),
|
||||||
"fabsf32" => f.abs(),
|
"fabsf32" => f.abs(),
|
||||||
@ -202,12 +204,13 @@ fn call_intrinsic(
|
|||||||
"truncf32" => f.trunc(),
|
"truncf32" => f.trunc(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
this.write_scalar(Scalar::from_f32(f), dest)?;
|
this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" |
|
"sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" |
|
||||||
"log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" => {
|
"log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f64()?;
|
// FIXME: Using host floats.
|
||||||
|
let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?);
|
||||||
let f = match intrinsic_name.get() {
|
let f = match intrinsic_name.get() {
|
||||||
"sinf64" => f.sin(),
|
"sinf64" => f.sin(),
|
||||||
"fabsf64" => f.abs(),
|
"fabsf64" => f.abs(),
|
||||||
@ -223,7 +226,7 @@ fn call_intrinsic(
|
|||||||
"truncf64" => f.trunc(),
|
"truncf64" => f.trunc(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
this.write_scalar(Scalar::from_f64(f), dest)?;
|
this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
||||||
@ -240,6 +243,28 @@ fn call_intrinsic(
|
|||||||
this.binop_ignore_overflow(op, a, b, dest)?;
|
this.binop_ignore_overflow(op, a, b, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"minnumf32" | "maxnumf32" => {
|
||||||
|
let a = this.read_scalar(args[0])?.to_f32()?;
|
||||||
|
let b = this.read_scalar(args[1])?.to_f32()?;
|
||||||
|
let res = if intrinsic_name.get().starts_with("min") {
|
||||||
|
a.min(b)
|
||||||
|
} else {
|
||||||
|
a.max(b)
|
||||||
|
};
|
||||||
|
this.write_scalar(Scalar::from_f32(res), dest)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
"minnumf64" | "maxnumf64" => {
|
||||||
|
let a = this.read_scalar(args[0])?.to_f64()?;
|
||||||
|
let b = this.read_scalar(args[1])?.to_f64()?;
|
||||||
|
let res = if intrinsic_name.get().starts_with("min") {
|
||||||
|
a.min(b)
|
||||||
|
} else {
|
||||||
|
a.max(b)
|
||||||
|
};
|
||||||
|
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||||
|
}
|
||||||
|
|
||||||
"exact_div" => {
|
"exact_div" => {
|
||||||
// Performs an exact division, resulting in undefined behavior where
|
// Performs an exact division, resulting in undefined behavior where
|
||||||
// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
|
// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
|
||||||
@ -320,19 +345,21 @@ fn call_intrinsic(
|
|||||||
}
|
}
|
||||||
|
|
||||||
"powf32" => {
|
"powf32" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f32()?;
|
// FIXME: Using host floats.
|
||||||
let f2 = this.read_scalar(args[1])?.to_f32()?;
|
let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?);
|
||||||
|
let f2 = f32::from_bits(this.read_scalar(args[1])?.to_u32()?);
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f32(f.powf(f2)),
|
Scalar::from_u32(f.powf(f2).to_bits()),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"powf64" => {
|
"powf64" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f64()?;
|
// FIXME: Using host floats.
|
||||||
let f2 = this.read_scalar(args[1])?.to_f64()?;
|
let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?);
|
||||||
|
let f2 = f64::from_bits(this.read_scalar(args[1])?.to_u64()?);
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f64(f.powf(f2)),
|
Scalar::from_u64(f.powf(f2).to_bits()),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -341,8 +368,9 @@ fn call_intrinsic(
|
|||||||
let a = this.read_scalar(args[0])?.to_f32()?;
|
let a = this.read_scalar(args[0])?.to_f32()?;
|
||||||
let b = this.read_scalar(args[1])?.to_f32()?;
|
let b = this.read_scalar(args[1])?.to_f32()?;
|
||||||
let c = this.read_scalar(args[2])?.to_f32()?;
|
let c = this.read_scalar(args[2])?.to_f32()?;
|
||||||
|
let res = a.mul_add(b, c).value;
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f32(a * b + c),
|
Scalar::from_f32(res),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -351,26 +379,29 @@ fn call_intrinsic(
|
|||||||
let a = this.read_scalar(args[0])?.to_f64()?;
|
let a = this.read_scalar(args[0])?.to_f64()?;
|
||||||
let b = this.read_scalar(args[1])?.to_f64()?;
|
let b = this.read_scalar(args[1])?.to_f64()?;
|
||||||
let c = this.read_scalar(args[2])?.to_f64()?;
|
let c = this.read_scalar(args[2])?.to_f64()?;
|
||||||
|
let res = a.mul_add(b, c).value;
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f64(a * b + c),
|
Scalar::from_f64(res),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"powif32" => {
|
"powif32" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f32()?;
|
// FIXME: Using host floats.
|
||||||
|
let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?);
|
||||||
let i = this.read_scalar(args[1])?.to_i32()?;
|
let i = this.read_scalar(args[1])?.to_i32()?;
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f32(f.powi(i)),
|
Scalar::from_u32(f.powi(i).to_bits()),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"powif64" => {
|
"powif64" => {
|
||||||
let f = this.read_scalar(args[0])?.to_f64()?;
|
// FIXME: Using host floats.
|
||||||
|
let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?);
|
||||||
let i = this.read_scalar(args[1])?.to_i32()?;
|
let i = this.read_scalar(args[1])?.to_i32()?;
|
||||||
this.write_scalar(
|
this.write_scalar(
|
||||||
Scalar::from_f64(f.powi(i)),
|
Scalar::from_u64(f.powi(i).to_bits()),
|
||||||
dest,
|
dest,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
// From rustc.
|
// From rustc.
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
#[macro_use]
|
extern crate rustc_apfloat;
|
||||||
extern crate rustc;
|
#[macro_use] extern crate rustc;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_mir;
|
extern crate rustc_mir;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
|
@ -11,11 +11,13 @@ enum Signed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn foo() -> [u8; 3] {
|
fn foo() -> [u8; 3] {
|
||||||
[Foo::Bar as u8, Foo::Baz as u8, Foo::Quux as u8]
|
let baz = Foo::Baz; // let-expansion changes the MIR significantly
|
||||||
|
[Foo::Bar as u8, baz as u8, Foo::Quux as u8]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signed() -> [i8; 3] {
|
fn signed() -> [i8; 3] {
|
||||||
[Signed::Bar as i8, Signed::Baz as i8, Signed::Quux as i8]
|
let baz = Signed::Baz; // let-expansion changes the MIR significantly
|
||||||
|
[Signed::Bar as i8, baz as i8, Signed::Quux as i8]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsafe_match() -> bool {
|
fn unsafe_match() -> bool {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(6.0_f32*6.0_f32, 36.0_f32);
|
assert_eq!(6.0_f32*6.0_f32, 36.0_f32);
|
||||||
assert_eq!(6.0_f64*6.0_f64, 36.0_f64);
|
assert_eq!(6.0_f64*6.0_f64, 36.0_f64);
|
||||||
@ -12,4 +11,18 @@ fn main() {
|
|||||||
assert_eq!(5.0f32 as u32, 5);
|
assert_eq!(5.0f32 as u32, 5);
|
||||||
assert_eq!(5.0f32 as i32, 5);
|
assert_eq!(5.0f32 as i32, 5);
|
||||||
assert_eq!(-5.0f32 as i32, -5);
|
assert_eq!(-5.0f32 as i32, -5);
|
||||||
|
|
||||||
|
assert_eq!((1.0 as f32).max(-1.0), 1.0);
|
||||||
|
assert_eq!((1.0 as f32).min(-1.0), -1.0);
|
||||||
|
assert_eq!(std::f32::NAN.min(9.0), 9.0);
|
||||||
|
assert_eq!(std::f32::NAN.max(-9.0), -9.0);
|
||||||
|
assert_eq!((9.0 as f32).min(std::f32::NAN), 9.0);
|
||||||
|
assert_eq!((-9.0 as f32).max(std::f32::NAN), -9.0);
|
||||||
|
|
||||||
|
assert_eq!((1.0 as f64).max(-1.0), 1.0);
|
||||||
|
assert_eq!((1.0 as f64).min(-1.0), -1.0);
|
||||||
|
assert_eq!(std::f64::NAN.min(9.0), 9.0);
|
||||||
|
assert_eq!(std::f64::NAN.max(-9.0), -9.0);
|
||||||
|
assert_eq!((9.0 as f64).min(std::f64::NAN), 9.0);
|
||||||
|
assert_eq!((-9.0 as f64).max(std::f64::NAN), -9.0);
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,10 @@ pub fn main() {
|
|||||||
assert_approx_eq!(8f32.log2(), 3f32);
|
assert_approx_eq!(8f32.log2(), 3f32);
|
||||||
assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E);
|
assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E);
|
||||||
|
|
||||||
assert_approx_eq!(1.0f32.mul_add(2.0f32, 5.0f32), 7.0f32);
|
assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0);
|
||||||
assert_approx_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E);
|
assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E);
|
||||||
|
assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0);
|
||||||
|
assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E);
|
||||||
|
|
||||||
assert_approx_eq!((-1.0f32).abs(), 1.0f32);
|
assert_approx_eq!((-1.0f32).abs(), 1.0f32);
|
||||||
assert_approx_eq!(34.2f64.abs(), 34.2f64);
|
assert_approx_eq!(34.2f64.abs(), 34.2f64);
|
||||||
|
Loading…
Reference in New Issue
Block a user