about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/intrinsics/simd.rs4
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs13
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs15
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr15
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs13
5 files changed, 15 insertions, 45 deletions
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index 6afe924f99d..86e3f8509ee 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -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;
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index de5da6ec898..c9250ba1b81 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -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" => {
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs
deleted file mode 100644
index 409098ac3b5..00000000000
--- a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs
+++ /dev/null
@@ -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
-    }
-}
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr
deleted file mode 100644
index 9acb51d8c5f..00000000000
--- a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr
+++ /dev/null
@@ -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
-
diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
index cc753dac215..e14ce51f35a 100644
--- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
@@ -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.