Skip to content

Commit

Permalink
Auto merge of rust-lang#3055 - eduardosm:x86-sse2-intrinsics, r=RalfJung
Browse files Browse the repository at this point in the history
Implement some `llvm.x86.sse2.*` intrinsics and add tests

Continuation of rust-lang/miri#2989 with SSE2 intrinsics.

Thankfully, a significant amount of SSE2 functions use `simd_*` intrinsics, which are already implemented in Miri.
  • Loading branch information
bors committed Sep 12, 2023
2 parents 259b4f0 + ab927c8 commit 8cd31ea
Show file tree
Hide file tree
Showing 6 changed files with 1,894 additions and 57 deletions.
5 changes: 5 additions & 0 deletions src/tools/miri/src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this, link_name, abi, args, dest,
);
}
name if name.starts_with("llvm.x86.sse2.") => {
return shims::x86::sse2::EvalContextExt::emulate_x86_sse2_intrinsic(
this, link_name, abi, args, dest,
);
}

// Platform-specific shims
_ =>
Expand Down
44 changes: 44 additions & 0 deletions src/tools/miri/src/shims/x86/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,45 @@
use crate::InterpResult;

pub(super) mod sse;
pub(super) mod sse2;

/// Floating point comparison operation
///
/// <https://www.felixcloutier.com/x86/cmpss>
/// <https://www.felixcloutier.com/x86/cmpps>
/// <https://www.felixcloutier.com/x86/cmpsd>
/// <https://www.felixcloutier.com/x86/cmppd>
#[derive(Copy, Clone)]
enum FloatCmpOp {
Eq,
Lt,
Le,
Unord,
Neq,
/// Not less-than
Nlt,
/// Not less-or-equal
Nle,
/// Ordered, i.e. neither of them is NaN
Ord,
}

impl FloatCmpOp {
/// Convert from the `imm` argument used to specify the comparison
/// operation in intrinsics such as `llvm.x86.sse.cmp.ss`.
fn from_intrinsic_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> {
match imm {
0 => Ok(Self::Eq),
1 => Ok(Self::Lt),
2 => Ok(Self::Le),
3 => Ok(Self::Unord),
4 => Ok(Self::Neq),
5 => Ok(Self::Nlt),
6 => Ok(Self::Nle),
7 => Ok(Self::Ord),
imm => {
throw_unsup_format!("invalid `imm` parameter of {intrinsic}: {imm}");
}
}
}
}
69 changes: 14 additions & 55 deletions src/tools/miri/src/shims/x86/sse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_target::spec::abi::Abi;

use rand::Rng as _;

use super::FloatCmpOp;
use crate::*;
use shims::foreign_items::EmulateByNameResult;

Expand Down Expand Up @@ -78,7 +79,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

unary_op_ss(this, which, op, dest)?;
}
// Used to implement _mm_{sqrt,rcp,rsqrt}_ss functions.
// Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions.
// Performs the operations on all components of `op`.
"sqrt.ps" | "rcp.ps" | "rsqrt.ps" => {
let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
Expand All @@ -100,22 +101,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [left, right, imm] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;

let which = match this.read_scalar(imm)?.to_i8()? {
0 => FloatBinOp::Cmp(FloatCmpOp::Eq),
1 => FloatBinOp::Cmp(FloatCmpOp::Lt),
2 => FloatBinOp::Cmp(FloatCmpOp::Le),
3 => FloatBinOp::Cmp(FloatCmpOp::Unord),
4 => FloatBinOp::Cmp(FloatCmpOp::Neq),
5 => FloatBinOp::Cmp(FloatCmpOp::Nlt),
6 => FloatBinOp::Cmp(FloatCmpOp::Nle),
7 => FloatBinOp::Cmp(FloatCmpOp::Ord),
imm => {
throw_unsup_format!(
"invalid 3rd parameter of llvm.x86.sse.cmp.ps: {}",
imm
);
}
};
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
this.read_scalar(imm)?.to_i8()?,
"llvm.x86.sse.cmp.ss",
)?);

bin_op_ss(this, which, left, right, dest)?;
}
Expand All @@ -127,26 +116,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [left, right, imm] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;

let which = match this.read_scalar(imm)?.to_i8()? {
0 => FloatBinOp::Cmp(FloatCmpOp::Eq),
1 => FloatBinOp::Cmp(FloatCmpOp::Lt),
2 => FloatBinOp::Cmp(FloatCmpOp::Le),
3 => FloatBinOp::Cmp(FloatCmpOp::Unord),
4 => FloatBinOp::Cmp(FloatCmpOp::Neq),
5 => FloatBinOp::Cmp(FloatCmpOp::Nlt),
6 => FloatBinOp::Cmp(FloatCmpOp::Nle),
7 => FloatBinOp::Cmp(FloatCmpOp::Ord),
imm => {
throw_unsup_format!(
"invalid 3rd parameter of llvm.x86.sse.cmp.ps: {}",
imm
);
}
};
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
this.read_scalar(imm)?.to_i8()?,
"llvm.x86.sse.cmp.ps",
)?);

bin_op_ps(this, which, left, right, dest)?;
}
// Used to implement _mm_{,u}comi{eq,lt,le,gt,ge,neq}_ps functions.
// Used to implement _mm_{,u}comi{eq,lt,le,gt,ge,neq}_ss functions.
// Compares the first component of `left` and `right` and returns
// a scalar value (0 or 1).
"comieq.ss" | "comilt.ss" | "comile.ss" | "comigt.ss" | "comige.ss" | "comineq.ss"
Expand Down Expand Up @@ -292,6 +269,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let op = this.read_scalar(&this.project_index(&op, i)?)?;
let op = op.to_u32()?;

// Extract the highest bit of `op` and place it in the `i`-th bit of `res`
res |= (op >> 31) << i;
}

Expand All @@ -303,25 +281,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
}

/// Floating point comparison operation
///
/// <https://www.felixcloutier.com/x86/cmpss>
/// <https://www.felixcloutier.com/x86/cmpps>
#[derive(Copy, Clone)]
enum FloatCmpOp {
Eq,
Lt,
Le,
Unord,
Neq,
/// Not less-than
Nlt,
/// Not less-or-equal
Nle,
/// Ordered, i.e. neither of them is NaN
Ord,
}

#[derive(Copy, Clone)]
enum FloatBinOp {
/// Arithmetic operation
Expand Down Expand Up @@ -436,8 +395,8 @@ fn bin_op_ss<'tcx>(
Ok(())
}

/// Performs `which` operation on each component of `left`, and
/// `right` storing the result is stored in `dest`.
/// Performs `which` operation on each component of `left` and
/// `right`, storing the result is stored in `dest`.
fn bin_op_ps<'tcx>(
this: &mut crate::MiriInterpCx<'_, 'tcx>,
which: FloatBinOp,
Expand Down
Loading

0 comments on commit 8cd31ea

Please sign in to comment.