@@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
112
112
113
113
// Shift ops can have an RHS with a different numeric type.
114
114
if matches ! ( bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked ) {
115
- let size = left. layout . size . bits ( ) ;
115
+ let l_bits = left. layout . size . bits ( ) ;
116
116
// Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
117
117
// the one MIR operator that does *not* directly map to a single LLVM operation.)
118
118
let ( shift_amount, overflow) = if right. layout . abi . is_signed ( ) {
119
119
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)
126
123
} else {
127
124
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)
132
127
} ;
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
134
129
// Compute the shifted result.
135
130
let result = if left. layout . abi . is_signed ( ) {
136
131
let l = l_signed ( ) ;
0 commit comments