Browse Source

cranelift: Use `round_ties_even` for `nearest` in interpreter (#4413)

As @MaxGraey pointed out (thanks!) in #4397, `round` has different
 behavior from `nearest`. And it looks like the native rust
 implementation is still pending stabilization.

 Right now we duplicate the wasmtime implementation, merged in #2171.

 However, we definitely should switch to the rust native version
 when it is available.
pull/4402/head
Afonso Bordado 2 years ago
committed by GitHub
parent
commit
16cb287c53
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      cranelift/codegen/src/ir/immediates.rs
  2. 28
      cranelift/filetests/filetests/runtests/ceil.clif
  3. 28
      cranelift/filetests/filetests/runtests/floor.clif
  4. 28
      cranelift/filetests/filetests/runtests/nearest.clif
  5. 28
      cranelift/filetests/filetests/runtests/trunc.clif
  6. 2
      cranelift/interpreter/src/value.rs

34
cranelift/codegen/src/ir/immediates.rs

@ -816,9 +816,20 @@ impl Ieee32 {
Self::with_float(self.as_f32().trunc())
}
/// Returns the nearest integer to `self`. Round half-way cases away from `0.0`.
pub fn nearest(self) -> Self {
Self::with_float(self.as_f32().round())
/// Returns the nearest integer to `self`. Rounds half-way cases to the number
/// with an even least significant digit.
pub fn round_ties_even(self) -> Self {
// TODO: Replace with the native implementation once
// https://github.com/rust-lang/rust/issues/96710 is stabilized
let toint_32: f32 = 1.0 / f32::EPSILON;
let f = self.as_f32();
let e = self.0 >> 23 & 0xff;
if e >= 0x7f_u32 + 23 {
self
} else {
Self::with_float((f.abs() + toint_32 - toint_32).copysign(f))
}
}
}
@ -965,9 +976,20 @@ impl Ieee64 {
Self::with_float(self.as_f64().trunc())
}
/// Returns the nearest integer to `self`. Round half-way cases away from `0.0`.
pub fn nearest(self) -> Self {
Self::with_float(self.as_f64().round())
/// Returns the nearest integer to `self`. Rounds half-way cases to the number
/// with an even least significant digit.
pub fn round_ties_even(self) -> Self {
// TODO: Replace with the native implementation once
// https://github.com/rust-lang/rust/issues/96710 is stabilized
let toint_64: f64 = 1.0 / f64::EPSILON;
let f = self.as_f64();
let e = self.0 >> 52 & 0x7ff_u64;
if e >= 0x3ff_u64 + 52 {
self
} else {
Self::with_float((f.abs() + toint_64 - toint_64).copysign(f))
}
}
}

28
cranelift/filetests/filetests/runtests/ceil.clif

@ -14,6 +14,13 @@ block0(v0: f32):
; run: %ceil_f32(0x1.5) == 0x1.0p1
; run: %ceil_f32(0x2.9) == 0x1.8p1
; run: %ceil_f32(0x1.1p10) == 0x1.1p10
; run: %ceil_f32(0x1.400000p1) == 0x1.8p1
; run: %ceil_f32(0x1.4cccccp0) == 0x1.0p1
; run: %ceil_f32(0x1.800000p0) == 0x1.0p1
; run: %ceil_f32(0x1.b33334p0) == 0x1.0p1
; run: %ceil_f32(0x1.99999ap-2) == 0x1.0
; run: %ceil_f32(0x1.333334p-1) == 0x1.0
; run: %ceil_f32(0x1.666666p1) == 0x1.8p1
; Negatives
; run: %ceil_f32(-0x0.5) == -0x0.0
@ -21,6 +28,13 @@ block0(v0: f32):
; run: %ceil_f32(-0x1.5) == -0x1.0
; run: %ceil_f32(-0x2.9) == -0x1.0p1
; run: %ceil_f32(-0x1.1p10) == -0x1.1p10
; run: %ceil_f32(-0x1.333334p-1) == -0x0.0
; run: %ceil_f32(-0x1.99999ap-2) == -0x0.0
; run: %ceil_f32(-0x1.4cccccp0) == -0x1.0
; run: %ceil_f32(-0x1.800000p0) == -0x1.0
; run: %ceil_f32(-0x1.b33334p0) == -0x1.0
; run: %ceil_f32(-0x1.400000p1) == -0x1.0p1
; run: %ceil_f32(-0x1.666666p1) == -0x1.0p1
; Specials
; run: %ceil_f32(0x0.0) == 0x0.0
@ -71,6 +85,13 @@ block0(v0: f64):
; run: %ceil_f64(0x1.5) == 0x1.0p1
; run: %ceil_f64(0x2.9) == 0x1.8p1
; run: %ceil_f64(0x1.1p10) == 0x1.1p10
; run: %ceil_f64(0x1.4000000000000p1) == 0x1.8p1
; run: %ceil_f64(0x1.4cccccccccccdp0) == 0x1.0p1
; run: %ceil_f64(0x1.8000000000000p0) == 0x1.0p1
; run: %ceil_f64(0x1.b333333333333p0) == 0x1.0p1
; run: %ceil_f64(0x1.999999999999ap-2) == 0x1.0
; run: %ceil_f64(0x1.3333333333333p-1) == 0x1.0
; run: %ceil_f64(0x1.6666666666666p1) == 0x1.8p1
; Negatives
; run: %ceil_f64(-0x0.5) == -0x0.0
@ -78,6 +99,13 @@ block0(v0: f64):
; run: %ceil_f64(-0x1.5) == -0x1.0
; run: %ceil_f64(-0x2.9) == -0x1.0p1
; run: %ceil_f64(-0x1.1p10) == -0x1.1p10
; run: %ceil_f64(-0x1.3333333333333p-1) == -0x0.0
; run: %ceil_f64(-0x1.999999999999ap-2) == -0x0.0
; run: %ceil_f64(-0x1.4cccccccccccdp0) == -0x1.0
; run: %ceil_f64(-0x1.8000000000000p0) == -0x1.0
; run: %ceil_f64(-0x1.b333333333333p0) == -0x1.0
; run: %ceil_f64(-0x1.4000000000000p1) == -0x1.0p1
; run: %ceil_f64(-0x1.6666666666666p1) == -0x1.0p1
; Specials
; run: %ceil_f64(0x0.0) == 0x0.0

28
cranelift/filetests/filetests/runtests/floor.clif

@ -14,6 +14,13 @@ block0(v0: f32):
; run: %floor_f32(0x1.5) == 0x1.0
; run: %floor_f32(0x2.9) == 0x1.0p1
; run: %floor_f32(0x1.1p10) == 0x1.1p10
; run: %floor_f32(0x1.400000p1) == 0x1.0p1
; run: %floor_f32(0x1.4cccccp0) == 0x1.0
; run: %floor_f32(0x1.800000p0) == 0x1.0
; run: %floor_f32(0x1.b33334p0) == 0x1.0
; run: %floor_f32(0x1.99999ap-2) == 0x0.0
; run: %floor_f32(0x1.333334p-1) == 0x0.0
; run: %floor_f32(0x1.666666p1) == 0x1.0p1
; Negatives
; run: %floor_f32(-0x0.5) == -0x1.0
@ -21,6 +28,13 @@ block0(v0: f32):
; run: %floor_f32(-0x1.5) == -0x1.0p1
; run: %floor_f32(-0x2.9) == -0x1.8p1
; run: %floor_f32(-0x1.1p10) == -0x1.1p10
; run: %floor_f32(-0x1.333334p-1) == -0x1.0
; run: %floor_f32(-0x1.99999ap-2) == -0x1.0
; run: %floor_f32(-0x1.4cccccp0) == -0x1.0p1
; run: %floor_f32(-0x1.800000p0) == -0x1.0p1
; run: %floor_f32(-0x1.b33334p0) == -0x1.0p1
; run: %floor_f32(-0x1.400000p1) == -0x1.8p1
; run: %floor_f32(-0x1.666666p1) == -0x1.8p1
; Specials
; run: %floor_f32(0x0.0) == 0x0.0
@ -71,6 +85,13 @@ block0(v0: f64):
; run: %floor_f64(0x1.5) == 0x1.0
; run: %floor_f64(0x2.9) == 0x1.0p1
; run: %floor_f64(0x1.1p10) == 0x1.1p10
; run: %floor_f64(0x1.4000000000000p1) == 0x1.0p1
; run: %floor_f64(0x1.4cccccccccccdp0) == 0x1.0
; run: %floor_f64(0x1.8000000000000p0) == 0x1.0
; run: %floor_f64(0x1.b333333333333p0) == 0x1.0
; run: %floor_f64(0x1.999999999999ap-2) == 0x0.0
; run: %floor_f64(0x1.3333333333333p-1) == 0x0.0
; run: %floor_f64(0x1.6666666666666p1) == 0x1.0p1
; Negatives
; run: %floor_f64(-0x0.5) == -0x1.0
@ -78,6 +99,13 @@ block0(v0: f64):
; run: %floor_f64(-0x1.5) == -0x1.0p1
; run: %floor_f64(-0x2.9) == -0x1.8p1
; run: %floor_f64(-0x1.1p10) == -0x1.1p10
; run: %floor_f64(-0x1.3333333333333p-1) == -0x1.0
; run: %floor_f64(-0x1.999999999999ap-2) == -0x1.0
; run: %floor_f64(-0x1.4cccccccccccdp0) == -0x1.0p1
; run: %floor_f64(-0x1.8000000000000p0) == -0x1.0p1
; run: %floor_f64(-0x1.b333333333333p0) == -0x1.0p1
; run: %floor_f64(-0x1.4000000000000p1) == -0x1.8p1
; run: %floor_f64(-0x1.6666666666666p1) == -0x1.8p1
; Specials
; run: %floor_f64(0x0.0) == 0x0.0

28
cranelift/filetests/filetests/runtests/nearest.clif

@ -14,6 +14,13 @@ block0(v0: f32):
; run: %nearest_f32(0x1.5) == 0x1.0
; run: %nearest_f32(0x2.9) == 0x1.8p1
; run: %nearest_f32(0x1.1p10) == 0x1.1p10
; run: %nearest_f32(0x1.400000p1) == 0x1.0p1
; run: %nearest_f32(0x1.4cccccp0) == 0x1.0
; run: %nearest_f32(0x1.800000p0) == 0x1.0p1
; run: %nearest_f32(0x1.b33334p0) == 0x1.0p1
; run: %nearest_f32(0x1.99999ap-2) == 0x0.0
; run: %nearest_f32(0x1.333334p-1) == 0x1.0
; run: %nearest_f32(0x1.666666p1) == 0x1.8p1
; Negatives
; run: %nearest_f32(-0x0.5) == -0x0.0
@ -21,6 +28,13 @@ block0(v0: f32):
; run: %nearest_f32(-0x1.5) == -0x1.0
; run: %nearest_f32(-0x2.9) == -0x1.8p1
; run: %nearest_f32(-0x1.1p10) == -0x1.1p10
; run: %nearest_f32(-0x1.333334p-1) == -0x1.0
; run: %nearest_f32(-0x1.99999ap-2) == -0x0.0
; run: %nearest_f32(-0x1.4cccccp0) == -0x1.0
; run: %nearest_f32(-0x1.800000p0) == -0x1.0p1
; run: %nearest_f32(-0x1.b33334p0) == -0x1.0p1
; run: %nearest_f32(-0x1.400000p1) == -0x1.0p1
; run: %nearest_f32(-0x1.666666p1) == -0x1.8p1
; Specials
; run: %nearest_f32(0x0.0) == 0x0.0
@ -71,6 +85,13 @@ block0(v0: f64):
; run: %nearest_f64(0x1.5) == 0x1.0
; run: %nearest_f64(0x2.9) == 0x1.8p1
; run: %nearest_f64(0x1.1p10) == 0x1.1p10
; run: %nearest_f64(0x1.4000000000000p1) == 0x1.0p1
; run: %nearest_f64(0x1.4cccccccccccdp0) == 0x1.0
; run: %nearest_f64(0x1.8000000000000p0) == 0x1.0p1
; run: %nearest_f64(0x1.b333333333333p0) == 0x1.0p1
; run: %nearest_f64(0x1.999999999999ap-2) == 0x0.0
; run: %nearest_f64(0x1.3333333333333p-1) == 0x1.0
; run: %nearest_f64(0x1.6666666666666p1) == 0x1.8p1
; Negatives
; run: %nearest_f64(-0x0.5) == -0x0.0
@ -78,6 +99,13 @@ block0(v0: f64):
; run: %nearest_f64(-0x1.5) == -0x1.0
; run: %nearest_f64(-0x2.9) == -0x1.8p1
; run: %nearest_f64(-0x1.1p10) == -0x1.1p10
; run: %nearest_f64(-0x1.3333333333333p-1) == -0x1.0
; run: %nearest_f64(-0x1.999999999999ap-2) == -0x0.0
; run: %nearest_f64(-0x1.4cccccccccccdp0) == -0x1.0
; run: %nearest_f64(-0x1.8000000000000p0) == -0x1.0p1
; run: %nearest_f64(-0x1.b333333333333p0) == -0x1.0p1
; run: %nearest_f64(-0x1.4000000000000p1) == -0x1.0p1
; run: %nearest_f64(-0x1.6666666666666p1) == -0x1.8p1
; Specials
; run: %nearest_f64(0x0.0) == 0x0.0

28
cranelift/filetests/filetests/runtests/trunc.clif

@ -14,6 +14,13 @@ block0(v0: f32):
; run: %trunc_f32(0x1.5) == 0x1.0
; run: %trunc_f32(0x2.9) == 0x1.0p1
; run: %trunc_f32(0x1.1p10) == 0x1.1p10
; run: %trunc_f32(0x1.400000p1) == 0x1.0p1
; run: %trunc_f32(0x1.4cccccp0) == 0x1.0
; run: %trunc_f32(0x1.800000p0) == 0x1.0
; run: %trunc_f32(0x1.b33334p0) == 0x1.0
; run: %trunc_f32(0x1.99999ap-2) == 0x0.0
; run: %trunc_f32(0x1.333334p-1) == 0x0.0
; run: %trunc_f32(0x1.666666p1) == 0x1.0p1
; Negatives
; run: %trunc_f32(-0x0.5) == -0x0.0
@ -21,6 +28,13 @@ block0(v0: f32):
; run: %trunc_f32(-0x1.5) == -0x1.0
; run: %trunc_f32(-0x2.9) == -0x1.0p1
; run: %trunc_f32(-0x1.1p10) == -0x1.1p10
; run: %trunc_f32(-0x1.333334p-1) == -0x0.0
; run: %trunc_f32(-0x1.99999ap-2) == -0x0.0
; run: %trunc_f32(-0x1.4cccccp0) == -0x1.0
; run: %trunc_f32(-0x1.800000p0) == -0x1.0
; run: %trunc_f32(-0x1.b33334p0) == -0x1.0
; run: %trunc_f32(-0x1.400000p1) == -0x1.0p1
; run: %trunc_f32(-0x1.666666p1) == -0x1.0p1
; Specials
; run: %trunc_f32(0x0.0) == 0x0.0
@ -71,6 +85,13 @@ block0(v0: f64):
; run: %trunc_f64(0x1.5) == 0x1.0
; run: %trunc_f64(0x2.9) == 0x1.0p1
; run: %trunc_f64(0x1.1p10) == 0x1.1p10
; run: %trunc_f64(0x1.4000000000000p1) == 0x1.0p1
; run: %trunc_f64(0x1.4cccccccccccdp0) == 0x1.0
; run: %trunc_f64(0x1.8000000000000p0) == 0x1.0
; run: %trunc_f64(0x1.b333333333333p0) == 0x1.0
; run: %trunc_f64(0x1.999999999999ap-2) == 0x0.0
; run: %trunc_f64(0x1.3333333333333p-1) == 0x0.0
; run: %trunc_f64(0x1.6666666666666p1) == 0x1.0p1
; Negatives
; run: %trunc_f64(-0x0.5) == -0x0.0
@ -78,6 +99,13 @@ block0(v0: f64):
; run: %trunc_f64(-0x1.5) == -0x1.0
; run: %trunc_f64(-0x2.9) == -0x1.0p1
; run: %trunc_f64(-0x1.1p10) == -0x1.1p10
; run: %trunc_f64(-0x1.3333333333333p-1) == -0x0.0
; run: %trunc_f64(-0x1.999999999999ap-2) == -0x0.0
; run: %trunc_f64(-0x1.4cccccccccccdp0) == -0x1.0
; run: %trunc_f64(-0x1.8000000000000p0) == -0x1.0
; run: %trunc_f64(-0x1.b333333333333p0) == -0x1.0
; run: %trunc_f64(-0x1.4000000000000p1) == -0x1.0p1
; run: %trunc_f64(-0x1.6666666666666p1) == -0x1.0p1
; Specials
; run: %trunc_f64(0x0.0) == 0x0.0

2
cranelift/interpreter/src/value.rs

@ -534,7 +534,7 @@ impl Value for DataValue {
}
fn nearest(self) -> ValueResult<Self> {
unary_match!(nearest(&self); [F32, F64])
unary_match!(round_ties_even(&self); [F32, F64])
}
fn add_sat(self, other: Self) -> ValueResult<Self> {

Loading…
Cancel
Save