Skip to content

Commit 0118850

Browse files
authored
Unrolled build for rust-lang#126469
Rollup merge of rust-lang#126469 - RalfJung:mir-shifts, r=scottmcm MIR Shl/Shr: the offset can be computed with rem_euclid r? ````@scottmcm````
2 parents 1d1356d + 669a400 commit 0118850

File tree

2 files changed

+11
-14
lines changed

2 files changed

+11
-14
lines changed

compiler/rustc_const_eval/src/interpret/operator.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
112112

113113
// Shift ops can have an RHS with a different numeric type.
114114
if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
115-
let size = left.layout.size.bits();
115+
let l_bits = left.layout.size.bits();
116116
// Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
117117
// the one MIR operator that does *not* directly map to a single LLVM operation.)
118118
let (shift_amount, overflow) = if right.layout.abi.is_signed() {
119119
let shift_amount = r_signed();
120-
let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
121-
// Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result
122-
// of the `as` will be equal modulo `size` (since it is a power of two).
123-
let masked_amount = (shift_amount as u128) % u128::from(size);
124-
assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap());
125-
(masked_amount, overflow)
120+
let rem = shift_amount.rem_euclid(l_bits.into());
121+
// `rem` is guaranteed positive, so the `unwrap` cannot fail
122+
(u128::try_from(rem).unwrap(), rem != shift_amount)
126123
} else {
127124
let shift_amount = r_unsigned();
128-
let overflow = shift_amount >= u128::from(size);
129-
let masked_amount = shift_amount % u128::from(size);
130-
assert_eq!(overflow, shift_amount != masked_amount);
131-
(masked_amount, overflow)
125+
let rem = shift_amount.rem_euclid(l_bits.into());
126+
(rem, rem != shift_amount)
132127
};
133-
let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
128+
let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit
134129
// Compute the shifted result.
135130
let result = if left.layout.abi.is_signed() {
136131
let l = l_signed();

compiler/rustc_middle/src/mir/syntax.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1490,15 +1490,17 @@ pub enum BinOp {
14901490
BitOr,
14911491
/// The `<<` operator (shift left)
14921492
///
1493-
/// The offset is (uniquely) determined as follows:
1493+
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
1494+
/// In other words, it is (uniquely) determined as follows:
14941495
/// - it is "equal modulo LHS::BITS" to the RHS
14951496
/// - it is in the range `0..LHS::BITS`
14961497
Shl,
14971498
/// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
14981499
ShlUnchecked,
14991500
/// The `>>` operator (shift right)
15001501
///
1501-
/// The offset is (uniquely) determined as follows:
1502+
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
1503+
/// In other words, it is (uniquely) determined as follows:
15021504
/// - it is "equal modulo LHS::BITS" to the RHS
15031505
/// - it is in the range `0..LHS::BITS`
15041506
///

0 commit comments

Comments
 (0)