Skip to content

Commit 487d999

Browse files
committed
Auto merge of rust-lang#3206 - RalfJung:simd-bitmask, r=RalfJung
SIMD bitmasks: use 'round up to multiple of 8' rather than 'clamp to at least 8' This should prepare us better for a future with non-power-of-2 vectors, if they ever happen.
2 parents 6da0959 + 7c6ed0c commit 487d999

File tree

5 files changed

+16
-13
lines changed

5 files changed

+16
-13
lines changed

Diff for: src/tools/miri/src/helpers.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1188,3 +1188,11 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
11881188
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
11891189
})
11901190
}
1191+
1192+
// This looks like something that would be nice to have in the standard library...
1193+
pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 {
1194+
assert_ne!(divisor, 0);
1195+
// divisor is nonzero; multiplication cannot overflow since we just divided
1196+
#[allow(clippy::arithmetic_side_effects)]
1197+
return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor;
1198+
}

Diff for: src/tools/miri/src/machine.rs

-5
Original file line numberDiff line numberDiff line change
@@ -768,11 +768,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
768768
drop(self.profiler.take());
769769
}
770770

771-
pub(crate) fn round_up_to_multiple_of_page_size(&self, length: u64) -> Option<u64> {
772-
#[allow(clippy::arithmetic_side_effects)] // page size is nonzero
773-
(length.checked_add(self.page_size - 1)? / self.page_size).checked_mul(self.page_size)
774-
}
775-
776771
pub(crate) fn page_align(&self) -> Align {
777772
Align::from_bytes(self.page_size).unwrap()
778773
}

Diff for: src/tools/miri/src/shims/intrinsics/simd.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ use rustc_middle::{mir, ty, ty::FloatTy};
44
use rustc_span::{sym, Symbol};
55
use rustc_target::abi::{Endian, HasDataLayout};
66

7+
use crate::helpers::{
8+
bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool,
9+
};
710
use crate::*;
8-
use helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool};
911

1012
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
1113
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
@@ -411,7 +413,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
411413
let (yes, yes_len) = this.operand_to_simd(yes)?;
412414
let (no, no_len) = this.operand_to_simd(no)?;
413415
let (dest, dest_len) = this.place_to_simd(dest)?;
414-
let bitmask_len = dest_len.max(8);
416+
let bitmask_len = round_to_next_multiple_of(dest_len, 8);
415417

416418
// The mask must be an integer or an array.
417419
assert!(
@@ -457,7 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
457459
"bitmask" => {
458460
let [op] = check_arg_count(args)?;
459461
let (op, op_len) = this.operand_to_simd(op)?;
460-
let bitmask_len = op_len.max(8);
462+
let bitmask_len = round_to_next_multiple_of(op_len, 8);
461463

462464
// Returns either an unsigned integer or array of `u8`.
463465
assert!(

Diff for: src/tools/miri/src/shims/unix/mem.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! equivalent. That is the only part we support: no MAP_FIXED or MAP_SHARED or anything
88
//! else that goes beyond a basic allocation API.
99
10-
use crate::*;
10+
use crate::{helpers::round_to_next_multiple_of, *};
1111
use rustc_target::abi::Size;
1212

1313
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -89,7 +89,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
8989
}
9090

9191
let align = this.machine.page_align();
92-
let map_length = this.machine.round_up_to_multiple_of_page_size(length).unwrap_or(u64::MAX);
92+
let map_length = round_to_next_multiple_of(length, this.machine.page_size);
9393

9494
let ptr =
9595
this.allocate_ptr(Size::from_bytes(map_length), align, MiriMemoryKind::Mmap.into())?;
@@ -123,7 +123,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
123123
return Ok(Scalar::from_i32(-1));
124124
}
125125

126-
let length = this.machine.round_up_to_multiple_of_page_size(length).unwrap_or(u64::MAX);
126+
let length = round_to_next_multiple_of(length, this.machine.page_size);
127127

128128
let ptr = Machine::ptr_from_addr_cast(this, addr)?;
129129

Diff for: src/tools/miri/tests/pass/portable-simd.rs

-2
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,6 @@ fn simd_mask() {
253253
let bitmask = mask.to_bitmask();
254254
assert_eq!(bitmask, 0b1000);
255255
assert_eq!(Mask::<i64, 4>::from_bitmask(bitmask), mask);
256-
257-
// Also directly call intrinsic, to test both kinds of return types.
258256
unsafe {
259257
let bitmask1: u8 = simd_bitmask(mask.to_int());
260258
let bitmask2: [u8; 1] = simd_bitmask(mask.to_int());

0 commit comments

Comments
 (0)