simd_select_bitmask: the 'padding' bits in the mask are just ignored
This commit is contained in:
parent
883f9f72e8
commit
31cb737dee
5 changed files with 15 additions and 45 deletions
|
|
@ -577,11 +577,9 @@ pub unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
|
|||
/// For each element, if the bit in `mask` is `1`, select the element from
|
||||
/// `if_true`. If the corresponding bit in `mask` is `0`, select the element from
|
||||
/// `if_false`.
|
||||
/// The remaining bits of the mask are ignored.
|
||||
///
|
||||
/// The bitmask bit order matches `simd_bitmask`.
|
||||
///
|
||||
/// # Safety
|
||||
/// Padding bits must be all zero.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
|
||||
|
|
|
|||
|
|
@ -506,7 +506,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
};
|
||||
|
||||
let dest_len = u32::try_from(dest_len).unwrap();
|
||||
let bitmask_len = u32::try_from(bitmask_len).unwrap();
|
||||
for i in 0..dest_len {
|
||||
let bit_i = simd_bitmask_index(i, dest_len, this.data_layout().endian);
|
||||
let mask = mask & 1u64.strict_shl(bit_i);
|
||||
|
|
@ -517,17 +516,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let val = if mask != 0 { yes } else { no };
|
||||
this.write_immediate(*val, &dest)?;
|
||||
}
|
||||
for i in dest_len..bitmask_len {
|
||||
// If the mask is "padded", ensure that padding is all-zero.
|
||||
// This deliberately does not use `simd_bitmask_index`; these bits are outside
|
||||
// the bitmask. It does not matter in which order we check them.
|
||||
let mask = mask & 1u64.strict_shl(i);
|
||||
if mask != 0 {
|
||||
throw_ub_format!(
|
||||
"a SIMD bitmask less than 8 bits long must be filled with 0s for the remaining bits"
|
||||
);
|
||||
}
|
||||
}
|
||||
// The remaining bits of the mask are ignored.
|
||||
}
|
||||
// Converts a "vector of bool" into a bitmask.
|
||||
"bitmask" => {
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
#![feature(core_intrinsics, repr_simd)]
|
||||
|
||||
use std::intrinsics::simd::simd_select_bitmask;
|
||||
|
||||
#[repr(simd)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct i32x2([i32; 2]);
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let x = i32x2([0, 1]);
|
||||
simd_select_bitmask(0b11111111u8, x, x); //~ERROR: bitmask less than 8 bits long must be filled with 0s for the remaining bits
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
error: Undefined Behavior: a SIMD bitmask less than 8 bits long must be filled with 0s for the remaining bits
|
||||
--> tests/fail/intrinsics/simd-select-bitmask-invalid.rs:LL:CC
|
||||
|
|
||||
LL | simd_select_bitmask(0b11111111u8, x, x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a SIMD bitmask less than 8 bits long must be filled with 0s for the remaining bits
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at tests/fail/intrinsics/simd-select-bitmask-invalid.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -331,6 +331,19 @@ fn simd_mask() {
|
|||
);
|
||||
assert_eq!(selected1, i32x4::from_array([0, 0, 0, 1]));
|
||||
assert_eq!(selected2, selected1);
|
||||
// Non-zero "padding" (the extra bits) is also allowed.
|
||||
let selected1 = simd_select_bitmask::<u8, _>(
|
||||
if cfg!(target_endian = "little") { 0b11111000 } else { 0b11110001 },
|
||||
i32x4::splat(1), // yes
|
||||
i32x4::splat(0), // no
|
||||
);
|
||||
let selected2 = simd_select_bitmask::<[u8; 1], _>(
|
||||
if cfg!(target_endian = "little") { [0b11111000] } else { [0b11110001] },
|
||||
i32x4::splat(1), // yes
|
||||
i32x4::splat(0), // no
|
||||
);
|
||||
assert_eq!(selected1, i32x4::from_array([0, 0, 0, 1]));
|
||||
assert_eq!(selected2, selected1);
|
||||
}
|
||||
|
||||
// Non-power-of-2 multi-byte mask.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue