Auto merge of #2894 - RalfJung:simd-ptr, r=RalfJung

implement SIMD ptr casts
This commit is contained in:
bors 2023-05-13 11:52:57 +00:00
commit 7750cd93eb
2 changed files with 33 additions and 5 deletions

View File

@ -421,14 +421,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
} }
#[rustfmt::skip] #[rustfmt::skip]
"cast" | "as" => { "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
let [op] = check_arg_count(args)?; let [op] = check_arg_count(args)?;
let (op, op_len) = this.operand_to_simd(op)?; let (op, op_len) = this.operand_to_simd(op)?;
let (dest, dest_len) = this.place_to_simd(dest)?; let (dest, dest_len) = this.place_to_simd(dest)?;
assert_eq!(dest_len, op_len); assert_eq!(dest_len, op_len);
let unsafe_cast = intrinsic_name == "cast";
let safe_cast = intrinsic_name == "as"; let safe_cast = intrinsic_name == "as";
let ptr_cast = intrinsic_name == "cast_ptr";
let expose_cast = intrinsic_name == "expose_addr";
let from_exposed_cast = intrinsic_name == "from_exposed_addr";
for i in 0..dest_len { for i in 0..dest_len {
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?; let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
@ -436,19 +440,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) { let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
// Int-to-(int|float): always safe // Int-to-(int|float): always safe
(ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) => (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
this.int_to_int_or_float(&op, dest.layout.ty)?, this.int_to_int_or_float(&op, dest.layout.ty)?,
// Float-to-float: always safe // Float-to-float: always safe
(ty::Float(_), ty::Float(_)) => (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
this.float_to_float_or_int(&op, dest.layout.ty)?, this.float_to_float_or_int(&op, dest.layout.ty)?,
// Float-to-int in safe mode // Float-to-int in safe mode
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
this.float_to_float_or_int(&op, dest.layout.ty)?, this.float_to_float_or_int(&op, dest.layout.ty)?,
// Float-to-int in unchecked mode // Float-to-int in unchecked mode
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast => (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(), this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if !safe_cast => (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(), this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
// Ptr-to-ptr cast
(ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
this.ptr_to_ptr(&op, dest.layout.ty)?
}
// Ptr/Int casts
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
this.pointer_expose_address_cast(&op, dest.layout.ty)?
}
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
}
// Error otherwise
_ => _ =>
throw_unsup_format!( throw_unsup_format!(
"Unsupported SIMD cast from element type {from_ty} to {to_ty}", "Unsupported SIMD cast from element type {from_ty} to {to_ty}",

View File

@ -0,0 +1,12 @@
// Separate test without strict provenance
//@compile-flags: -Zmiri-permissive-provenance
#![feature(portable_simd, platform_intrinsics)]
use std::ptr;
use std::simd::*;
fn main() {
// Pointer casts
let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
}