implement simd_shuffle
This commit is contained in:
parent
5aeff5d9ef
commit
3eba7fcf73
@ -3,7 +3,7 @@ use std::iter;
|
||||
use log::trace;
|
||||
|
||||
use rustc_apfloat::{Float, Round};
|
||||
use rustc_middle::ty::layout::{IntegerExt, LayoutOf};
|
||||
use rustc_middle::ty::layout::{HasParamEnv, IntegerExt, LayoutOf};
|
||||
use rustc_middle::{mir, mir::BinOp, ty, ty::FloatTy};
|
||||
use rustc_target::abi::{Align, Integer};
|
||||
|
||||
@ -614,6 +614,45 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
this.write_immediate(val, &dest.into())?;
|
||||
}
|
||||
}
|
||||
"simd_shuffle" => {
|
||||
let &[ref left, ref right, ref index] = check_arg_count(args)?;
|
||||
let (left, left_len) = this.operand_to_simd(left)?;
|
||||
let (right, right_len) = this.operand_to_simd(right)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
|
||||
// `index` is an array, not a SIMD type
|
||||
let ty::Array(_, index_len) = index.layout.ty.kind() else {
|
||||
bug!("simd_shuffle index argument has non-array type {}", index.layout.ty)
|
||||
};
|
||||
let index_len = index_len.eval_usize(*this.tcx, this.param_env());
|
||||
|
||||
assert_eq!(left_len, right_len);
|
||||
assert_eq!(index_len, dest_len);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let src_index: u64 = this
|
||||
.read_immediate(&this.operand_index(&index, i)?.into())?
|
||||
.to_scalar()?
|
||||
.to_u32()?
|
||||
.into();
|
||||
let dest = this.mplace_index(&dest, i)?;
|
||||
|
||||
let val = if src_index < left_len {
|
||||
this.read_immediate(&this.mplace_index(&left, src_index)?.into())?
|
||||
} else if src_index < left_len.checked_add(right_len).unwrap() {
|
||||
this.read_immediate(
|
||||
&this.mplace_index(&right, src_index - left_len)?.into(),
|
||||
)?
|
||||
} else {
|
||||
bug!(
|
||||
"simd_shuffle index {} is out of bounds for 2 vectors of size {}",
|
||||
src_index,
|
||||
left_len
|
||||
);
|
||||
};
|
||||
this.write_immediate(*val, &dest.into())?;
|
||||
}
|
||||
}
|
||||
|
||||
// Atomic operations
|
||||
"atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?,
|
||||
|
@ -238,6 +238,17 @@ fn simd_cast() {
|
||||
}
|
||||
}
|
||||
|
||||
fn simd_swizzle() {
|
||||
use Which::*;
|
||||
|
||||
let a = f32x4::splat(10.0);
|
||||
let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
|
||||
|
||||
assert_eq!(simd_swizzle!(b, [3, 0, 0, 2]), f32x4::from_array([-4.0, 1.0, 1.0, 3.0]));
|
||||
assert_eq!(simd_swizzle!(b, [1, 2]), f32x2::from_array([2.0, 3.0]));
|
||||
assert_eq!(simd_swizzle!(b, a, [First(3), Second(0)]), f32x2::from_array([-4.0, 10.0]));
|
||||
}
|
||||
|
||||
fn simd_intrinsics() {
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_eq<T, U>(x: T, y: T) -> U;
|
||||
@ -276,5 +287,6 @@ fn main() {
|
||||
simd_ops_f64();
|
||||
simd_ops_i32();
|
||||
simd_cast();
|
||||
simd_swizzle();
|
||||
simd_intrinsics();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user