Implement fma/fabs/fneg/fcopysign on the interpreter (#4367)

* cranelift: Implement `fma` on interpreter

* cranelift: Implement `fabs` on interpreter

* cranelift: Fix `fneg` implementation on interpreter

`fneg` was implemented as `0 - x` which is not correct according to the
standard since that operation makes no guarantees on what the output
is when the input is `NaN`. However for `fneg` the output for `NaN`
inputs is fully defined.

* cranelift: Implement `fcopysign` on interpreter
This commit is contained in:
Afonso Bordado
2022-07-05 17:03:04 +01:00
committed by GitHub
parent 5542c4ef26
commit 2003ae99a0
7 changed files with 511 additions and 10 deletions

View File

@@ -51,6 +51,12 @@ pub trait Value: Clone + From<DataValue> {
fn div(self, other: Self) -> ValueResult<Self>;
fn rem(self, other: Self) -> ValueResult<Self>;
fn sqrt(self) -> ValueResult<Self>;
fn fma(self, a: Self, b: Self) -> ValueResult<Self>;
fn abs(self) -> ValueResult<Self>;
// Float operations
fn neg(self) -> ValueResult<Self>;
fn copysign(self, sign: Self) -> ValueResult<Self>;
// Saturating arithmetic.
fn add_sat(self, other: Self) -> ValueResult<Self>;
@@ -468,6 +474,30 @@ impl Value for DataValue {
unary_match!(sqrt(&self); [F32, F64]; [Ieee32, Ieee64])
}
fn fma(self, b: Self, c: Self) -> ValueResult<Self> {
match (self, b, c) {
(DataValue::F32(a), DataValue::F32(b), DataValue::F32(c)) => {
Ok(DataValue::F32(a.mul_add(b, c)))
}
(DataValue::F64(a), DataValue::F64(b), DataValue::F64(c)) => {
Ok(DataValue::F64(a.mul_add(b, c)))
}
(a, _b, _c) => Err(ValueError::InvalidType(ValueTypeClass::Float, a.ty())),
}
}
fn abs(self) -> ValueResult<Self> {
unary_match!(abs(&self); [F32, F64])
}
fn neg(self) -> ValueResult<Self> {
unary_match!(neg(&self); [F32, F64])
}
fn copysign(self, sign: Self) -> ValueResult<Self> {
binary_match!(copysign(&self, &sign); [F32, F64])
}
fn add_sat(self, other: Self) -> ValueResult<Self> {
binary_match!(saturating_add(self, &other); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128])
}