Skip to content

Commit

Permalink
Implement some llvm.x86.sse2.* intrinsics and add tests
Browse files Browse the repository at this point in the history
Implements LLVM intrisics needed to run most SSE2 functions from `core::arch::x86{,_64}`.

Also adds miri tests for those functions (mostly copied from core_arch tests).
  • Loading branch information
eduardosm committed Sep 12, 2023
1 parent 9df62ad commit ab927c8
Show file tree
Hide file tree
Showing 5 changed files with 1,869 additions and 51 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}");
}
}
}
}
61 changes: 10 additions & 51 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 @@ -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,22 +116,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.ps",
)?);

bin_op_ps(this, which, left, right, dest)?;
}
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
Loading

0 comments on commit ab927c8

Please sign in to comment.