factor SIMD bool handling into helper functions

This commit is contained in:
Ralf Jung 2022-03-01 18:15:39 -05:00
parent e05a543f74
commit f672282bf2
2 changed files with 18 additions and 13 deletions

View file

@ -758,3 +758,18 @@ pub fn immty_from_uint_checked<'tcx>(
err_unsup_format!("unsigned value {:#x} does not fit in {} bits", int, layout.size.bits())
})?)
}
pub fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Tag> {
// SIMD uses all-1 as pattern for "true"
let val = if b { -1 } else { 0 };
Scalar::from_int(val, size)
}
pub fn simd_element_to_bool<'tcx>(elem: ImmTy<'tcx, Tag>) -> InterpResult<'tcx, bool> {
let val = elem.to_scalar()?.to_int(elem.layout.size)?;
Ok(match val {
0 => false,
-1 => true,
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
})
}

View file

@ -8,7 +8,7 @@ use rustc_middle::{mir, mir::BinOp, ty, ty::FloatTy};
use rustc_target::abi::{Align, Integer};
use crate::*;
use helpers::check_arg_count;
use helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool};
pub enum AtomicOp {
MirOp(mir::BinOp, bool),
@ -365,8 +365,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Special handling for boolean-returning operations
assert_eq!(ty, this.tcx.types.bool);
let val = val.to_bool().unwrap();
let val = if val { -1 } else { 0 }; // SIMD uses all-1 as pattern for "true"
let val = Scalar::from_int(val, dest.layout.size);
let val = bool_to_simd_element(val, dest.layout.size);
this.write_scalar(val, &dest.into())?;
} else {
assert_eq!(ty, dest.layout.ty);
@ -381,16 +380,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let mut res = false; // the neutral element
for i in 0..arg_len {
let op = this.read_immediate(&this.mplace_index(&arg, i)?.into())?;
// We convert it to a *signed* integer and expect either 0 or -1 (the latter means all bits were set).
let val = op.to_scalar()?.to_int(op.layout.size)?;
let val = match val {
0 => false,
-1 => true,
_ =>
throw_ub_format!(
"each element of a simd_reduce_any operand must be all-0-bits or all-1-bits"
),
};
let val = simd_element_to_bool(op)?;
res = res | val;
}