diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-06-15 10:56:41 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-15 10:56:41 +0200 |
| commit | f24509aa232f927332219cb56fd1b13ba680e1dd (patch) | |
| tree | d838d1f6b47fb8470dfcb08e2ff7b29aed4950e0 /compiler/rustc_const_eval/src/interpret | |
| parent | b473ec2744e89b66f2b09205b19fe015dff9e3a5 (diff) | |
| parent | 669a40006bf3494b0d320fb77bf39cc19a6c5bc4 (diff) | |
Rollup merge of #126469 - RalfJung:mir-shifts, r=scottmcm
MIR Shl/Shr: the offset can be computed with rem_euclid r? ````@scottmcm````
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/operator.rs | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index a6eef9f5662..4d0f35618ef 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Shift ops can have an RHS with a different numeric type. if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) { - let size = left.layout.size.bits(); + let l_bits = left.layout.size.bits(); // Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is // the one MIR operator that does *not* directly map to a single LLVM operation.) let (shift_amount, overflow) = if right.layout.abi.is_signed() { let shift_amount = r_signed(); - let overflow = shift_amount < 0 || shift_amount >= i128::from(size); - // Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result - // of the `as` will be equal modulo `size` (since it is a power of two). - let masked_amount = (shift_amount as u128) % u128::from(size); - assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap()); - (masked_amount, overflow) + let rem = shift_amount.rem_euclid(l_bits.into()); + // `rem` is guaranteed positive, so the `unwrap` cannot fail + (u128::try_from(rem).unwrap(), rem != shift_amount) } else { let shift_amount = r_unsigned(); - let overflow = shift_amount >= u128::from(size); - let masked_amount = shift_amount % u128::from(size); - assert_eq!(overflow, shift_amount != masked_amount); - (masked_amount, overflow) + let rem = shift_amount.rem_euclid(l_bits.into()); + (rem, rem != shift_amount) }; - let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit + let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit // Compute the shifted result. let result = if left.layout.abi.is_signed() { let l = l_signed(); |
