Do not use host floats in simd_{ceil,floor,round,trunc}

This commit is contained in:
Eduardo Sánchez Muñoz 2023-10-06 15:12:36 +02:00
parent 4587c7c1c0
commit e1e880e9c6

View File

@ -32,28 +32,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
assert_eq!(dest_len, op_len); assert_eq!(dest_len, op_len);
#[derive(Copy, Clone)]
enum HostFloatOp {
Ceil,
Floor,
Round,
Trunc,
Sqrt,
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum Op { enum Op {
MirOp(mir::UnOp), MirOp(mir::UnOp),
Abs, Abs,
HostOp(HostFloatOp), Sqrt,
Round(rustc_apfloat::Round),
} }
let which = match intrinsic_name { let which = match intrinsic_name {
"neg" => Op::MirOp(mir::UnOp::Neg), "neg" => Op::MirOp(mir::UnOp::Neg),
"fabs" => Op::Abs, "fabs" => Op::Abs,
"ceil" => Op::HostOp(HostFloatOp::Ceil), "fsqrt" => Op::Sqrt,
"floor" => Op::HostOp(HostFloatOp::Floor), "ceil" => Op::Round(rustc_apfloat::Round::TowardPositive),
"round" => Op::HostOp(HostFloatOp::Round), "floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
"trunc" => Op::HostOp(HostFloatOp::Trunc), "round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
"fsqrt" => Op::HostOp(HostFloatOp::Sqrt), "trunc" => Op::Round(rustc_apfloat::Round::TowardZero),
_ => unreachable!(), _ => unreachable!(),
}; };
@ -73,7 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()), FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
} }
} }
Op::HostOp(host_op) => { Op::Sqrt => {
let ty::Float(float_ty) = op.layout.ty.kind() else { let ty::Float(float_ty) = op.layout.ty.kind() else {
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
}; };
@ -81,28 +74,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
match float_ty { match float_ty {
FloatTy::F32 => { FloatTy::F32 => {
let f = f32::from_bits(op.to_scalar().to_u32()?); let f = f32::from_bits(op.to_scalar().to_u32()?);
let res = match host_op { let res = f.sqrt();
HostFloatOp::Ceil => f.ceil(),
HostFloatOp::Floor => f.floor(),
HostFloatOp::Round => f.round(),
HostFloatOp::Trunc => f.trunc(),
HostFloatOp::Sqrt => f.sqrt(),
};
Scalar::from_u32(res.to_bits()) Scalar::from_u32(res.to_bits())
} }
FloatTy::F64 => { FloatTy::F64 => {
let f = f64::from_bits(op.to_scalar().to_u64()?); let f = f64::from_bits(op.to_scalar().to_u64()?);
let res = match host_op { let res = f.sqrt();
HostFloatOp::Ceil => f.ceil(),
HostFloatOp::Floor => f.floor(),
HostFloatOp::Round => f.round(),
HostFloatOp::Trunc => f.trunc(),
HostFloatOp::Sqrt => f.sqrt(),
};
Scalar::from_u64(res.to_bits()) Scalar::from_u64(res.to_bits())
} }
} }
}
Op::Round(rounding) => {
let ty::Float(float_ty) = op.layout.ty.kind() else {
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
};
match float_ty {
FloatTy::F32 => {
let f = op.to_scalar().to_f32()?;
let res = f.round_to_integral(rounding).value;
Scalar::from_f32(res)
}
FloatTy::F64 => {
let f = op.to_scalar().to_f64()?;
let res = f.round_to_integral(rounding).value;
Scalar::from_f64(res)
}
}
} }
}; };
this.write_scalar(val, &dest)?; this.write_scalar(val, &dest)?;