mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
add support for missing SIMD float intrinsics
This commit is contained in:
parent
f0d864fe04
commit
c87ec61a42
@ -33,6 +33,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
| "round"
|
| "round"
|
||||||
| "trunc"
|
| "trunc"
|
||||||
| "fsqrt"
|
| "fsqrt"
|
||||||
|
| "fsin"
|
||||||
|
| "fcos"
|
||||||
|
| "fexp"
|
||||||
|
| "fexp2"
|
||||||
|
| "flog"
|
||||||
|
| "flog2"
|
||||||
|
| "flog10"
|
||||||
| "ctlz"
|
| "ctlz"
|
||||||
| "cttz"
|
| "cttz"
|
||||||
| "bswap"
|
| "bswap"
|
||||||
@ -45,17 +52,16 @@ 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)]
|
#[derive(Copy, Clone)]
|
||||||
enum Op {
|
enum Op<'a> {
|
||||||
MirOp(mir::UnOp),
|
MirOp(mir::UnOp),
|
||||||
Abs,
|
Abs,
|
||||||
Sqrt,
|
|
||||||
Round(rustc_apfloat::Round),
|
Round(rustc_apfloat::Round),
|
||||||
Numeric(Symbol),
|
Numeric(Symbol),
|
||||||
|
HostOp(&'a str),
|
||||||
}
|
}
|
||||||
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,
|
||||||
"fsqrt" => Op::Sqrt,
|
|
||||||
"ceil" => Op::Round(rustc_apfloat::Round::TowardPositive),
|
"ceil" => Op::Round(rustc_apfloat::Round::TowardPositive),
|
||||||
"floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
|
"floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
|
||||||
"round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
|
"round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
|
||||||
@ -64,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
"cttz" => Op::Numeric(sym::cttz),
|
"cttz" => Op::Numeric(sym::cttz),
|
||||||
"bswap" => Op::Numeric(sym::bswap),
|
"bswap" => Op::Numeric(sym::bswap),
|
||||||
"bitreverse" => Op::Numeric(sym::bitreverse),
|
"bitreverse" => Op::Numeric(sym::bitreverse),
|
||||||
_ => unreachable!(),
|
_ => Op::HostOp(intrinsic_name),
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in 0..dest_len {
|
for i in 0..dest_len {
|
||||||
@ -89,7 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Op::Sqrt => {
|
Op::HostOp(host_op) => {
|
||||||
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)
|
||||||
};
|
};
|
||||||
@ -98,13 +104,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||||
FloatTy::F32 => {
|
FloatTy::F32 => {
|
||||||
let f = op.to_scalar().to_f32()?;
|
let f = op.to_scalar().to_f32()?;
|
||||||
let res = f.to_host().sqrt().to_soft();
|
let f_host = f.to_host();
|
||||||
|
let res = match host_op {
|
||||||
|
"fsqrt" => f_host.sqrt(),
|
||||||
|
"fsin" => f_host.sin(),
|
||||||
|
"fcos" => f_host.cos(),
|
||||||
|
"fexp" => f_host.exp(),
|
||||||
|
"fexp2" => f_host.exp2(),
|
||||||
|
"flog" => f_host.ln(),
|
||||||
|
"flog2" => f_host.log2(),
|
||||||
|
"flog10" => f_host.log10(),
|
||||||
|
_ => bug!(),
|
||||||
|
};
|
||||||
|
let res = res.to_soft();
|
||||||
let res = this.adjust_nan(res, &[f]);
|
let res = this.adjust_nan(res, &[f]);
|
||||||
Scalar::from(res)
|
Scalar::from(res)
|
||||||
}
|
}
|
||||||
FloatTy::F64 => {
|
FloatTy::F64 => {
|
||||||
let f = op.to_scalar().to_f64()?;
|
let f = op.to_scalar().to_f64()?;
|
||||||
let res = f.to_host().sqrt().to_soft();
|
let f_host = f.to_host();
|
||||||
|
let res = match host_op {
|
||||||
|
"fsqrt" => f_host.sqrt(),
|
||||||
|
"fsin" => f_host.sin(),
|
||||||
|
"fcos" => f_host.cos(),
|
||||||
|
"fexp" => f_host.exp(),
|
||||||
|
"fexp2" => f_host.exp2(),
|
||||||
|
"flog" => f_host.ln(),
|
||||||
|
"flog2" => f_host.log2(),
|
||||||
|
"flog10" => f_host.log10(),
|
||||||
|
_ => bug!(),
|
||||||
|
};
|
||||||
|
let res = res.to_soft();
|
||||||
let res = this.adjust_nan(res, &[f]);
|
let res = this.adjust_nan(res, &[f]);
|
||||||
Scalar::from(res)
|
Scalar::from(res)
|
||||||
}
|
}
|
||||||
|
@ -526,6 +526,23 @@ fn simd_intrinsics() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simd_float_intrinsics() {
|
||||||
|
use intrinsics::*;
|
||||||
|
|
||||||
|
// These are just smoke tests to ensure the intrinsics can be called.
|
||||||
|
unsafe {
|
||||||
|
let a = f32x4::splat(10.0);
|
||||||
|
simd_fsqrt(a);
|
||||||
|
simd_fsin(a);
|
||||||
|
simd_fcos(a);
|
||||||
|
simd_fexp(a);
|
||||||
|
simd_fexp2(a);
|
||||||
|
simd_flog(a);
|
||||||
|
simd_flog2(a);
|
||||||
|
simd_flog10(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn simd_masked_loadstore() {
|
fn simd_masked_loadstore() {
|
||||||
// The buffer is deliberarely too short, so reading the last element would be UB.
|
// The buffer is deliberarely too short, so reading the last element would be UB.
|
||||||
let buf = [3i32; 3];
|
let buf = [3i32; 3];
|
||||||
@ -559,5 +576,6 @@ fn main() {
|
|||||||
simd_gather_scatter();
|
simd_gather_scatter();
|
||||||
simd_round();
|
simd_round();
|
||||||
simd_intrinsics();
|
simd_intrinsics();
|
||||||
|
simd_float_intrinsics();
|
||||||
simd_masked_loadstore();
|
simd_masked_loadstore();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user