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:
@@ -679,10 +679,10 @@ where
|
||||
Opcode::Fmul => binary(Value::mul, arg(0)?, arg(1)?)?,
|
||||
Opcode::Fdiv => binary(Value::div, arg(0)?, arg(1)?)?,
|
||||
Opcode::Sqrt => assign(Value::sqrt(arg(0)?)?),
|
||||
Opcode::Fma => unimplemented!("Fma"),
|
||||
Opcode::Fneg => binary(Value::sub, Value::float(0, ctrl_ty)?, arg(0)?)?,
|
||||
Opcode::Fabs => unimplemented!("Fabs"),
|
||||
Opcode::Fcopysign => unimplemented!("Fcopysign"),
|
||||
Opcode::Fma => assign(Value::fma(arg(0)?, arg(1)?, arg(2)?)?),
|
||||
Opcode::Fneg => assign(Value::neg(arg(0)?)?),
|
||||
Opcode::Fabs => assign(Value::abs(arg(0)?)?),
|
||||
Opcode::Fcopysign => binary(Value::copysign, arg(0)?, arg(1)?)?,
|
||||
Opcode::Fmin => choose(
|
||||
Value::is_nan(&arg(0)?)? || Value::lt(&arg(0)?, &arg(1)?)?,
|
||||
arg(0)?,
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user