Skip to content

Commit 4dd5c26

Browse files
authored
Rollup merge of rust-lang#123226 - scottmcm:u32-shifts, r=WaffleLapkin
De-LLVM the unchecked shifts [MCP#693] This is just one part of the MCP (rust-lang/compiler-team#693), but it's the one that IMHO removes the most noise from the standard library code. Seems net simpler this way, since MIR already supported heterogeneous shifts anyway, and thus it's not more work for backends than before. r? WaffleLapkin
2 parents 49e00d7 + 0485d6a commit 4dd5c26

File tree

5 files changed

+64
-31
lines changed

5 files changed

+64
-31
lines changed

core/src/intrinsics.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,18 +2224,20 @@ extern "rust-intrinsic" {
22242224
/// Safe wrappers for this intrinsic are available on the integer
22252225
/// primitives via the `checked_shl` method. For example,
22262226
/// [`u32::checked_shl`]
2227+
#[cfg(not(bootstrap))]
22272228
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
22282229
#[rustc_nounwind]
2229-
pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T;
2230+
pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
22302231
/// Performs an unchecked right shift, resulting in undefined behavior when
22312232
/// `y < 0` or `y >= N`, where N is the width of T in bits.
22322233
///
22332234
/// Safe wrappers for this intrinsic are available on the integer
22342235
/// primitives via the `checked_shr` method. For example,
22352236
/// [`u32::checked_shr`]
2237+
#[cfg(not(bootstrap))]
22362238
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
22372239
#[rustc_nounwind]
2238-
pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
2240+
pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
22392241

22402242
/// Returns the result of an unchecked addition, resulting in
22412243
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.

core/src/num/int_macros.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,10 +1227,18 @@ macro_rules! int_impl {
12271227
#[inline(always)]
12281228
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
12291229
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
1230-
// SAFETY: the caller must uphold the safety contract for
1231-
// `unchecked_shl`.
1232-
// Any legal shift amount is losslessly representable in the self type.
1233-
unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) }
1230+
#[cfg(bootstrap)]
1231+
{
1232+
// For bootstrapping, just use built-in primitive shift.
1233+
// panicking is a legal manifestation of UB
1234+
self << rhs
1235+
}
1236+
#[cfg(not(bootstrap))]
1237+
{
1238+
// SAFETY: the caller must uphold the safety contract for
1239+
// `unchecked_shl`.
1240+
unsafe { intrinsics::unchecked_shl(self, rhs) }
1241+
}
12341242
}
12351243

12361244
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1310,10 +1318,18 @@ macro_rules! int_impl {
13101318
#[inline(always)]
13111319
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
13121320
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
1313-
// SAFETY: the caller must uphold the safety contract for
1314-
// `unchecked_shr`.
1315-
// Any legal shift amount is losslessly representable in the self type.
1316-
unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) }
1321+
#[cfg(bootstrap)]
1322+
{
1323+
// For bootstrapping, just use built-in primitive shift.
1324+
// panicking is a legal manifestation of UB
1325+
self >> rhs
1326+
}
1327+
#[cfg(not(bootstrap))]
1328+
{
1329+
// SAFETY: the caller must uphold the safety contract for
1330+
// `unchecked_shr`.
1331+
unsafe { intrinsics::unchecked_shr(self, rhs) }
1332+
}
13171333
}
13181334

13191335
/// Checked absolute value. Computes `self.abs()`, returning `None` if

core/src/num/mod.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -285,17 +285,6 @@ macro_rules! widening_impl {
285285
};
286286
}
287287

288-
macro_rules! conv_rhs_for_unchecked_shift {
289-
($SelfT:ty, $x:expr) => {{
290-
// If the `as` cast will truncate, ensure we still tell the backend
291-
// that the pre-truncation value was also small.
292-
if <$SelfT>::BITS < 32 {
293-
intrinsics::assume($x <= (<$SelfT>::MAX as u32));
294-
}
295-
$x as $SelfT
296-
}};
297-
}
298-
299288
impl i8 {
300289
int_impl! {
301290
Self = i8,

core/src/num/uint_macros.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,10 +1286,18 @@ macro_rules! uint_impl {
12861286
#[inline(always)]
12871287
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
12881288
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
1289-
// SAFETY: the caller must uphold the safety contract for
1290-
// `unchecked_shl`.
1291-
// Any legal shift amount is losslessly representable in the self type.
1292-
unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) }
1289+
#[cfg(bootstrap)]
1290+
{
1291+
// For bootstrapping, just use built-in primitive shift.
1292+
// panicking is a legal manifestation of UB
1293+
self << rhs
1294+
}
1295+
#[cfg(not(bootstrap))]
1296+
{
1297+
// SAFETY: the caller must uphold the safety contract for
1298+
// `unchecked_shl`.
1299+
unsafe { intrinsics::unchecked_shl(self, rhs) }
1300+
}
12931301
}
12941302

12951303
/// Checked shift right. Computes `self >> rhs`, returning `None`
@@ -1369,10 +1377,18 @@ macro_rules! uint_impl {
13691377
#[inline(always)]
13701378
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
13711379
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
1372-
// SAFETY: the caller must uphold the safety contract for
1373-
// `unchecked_shr`.
1374-
// Any legal shift amount is losslessly representable in the self type.
1375-
unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) }
1380+
#[cfg(bootstrap)]
1381+
{
1382+
// For bootstrapping, just use built-in primitive shift.
1383+
// panicking is a legal manifestation of UB
1384+
self >> rhs
1385+
}
1386+
#[cfg(not(bootstrap))]
1387+
{
1388+
// SAFETY: the caller must uphold the safety contract for
1389+
// `unchecked_shr`.
1390+
unsafe { intrinsics::unchecked_shr(self, rhs) }
1391+
}
13761392
}
13771393

13781394
/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if

core/src/ptr/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,9 +1781,19 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
17811781
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
17821782
// 1, where the method versions of these operations are not inlined.
17831783
use intrinsics::{
1784-
assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl,
1785-
unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub,
1784+
assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_sub,
1785+
wrapping_add, wrapping_mul, wrapping_sub,
17861786
};
1787+
#[cfg(bootstrap)]
1788+
const unsafe fn unchecked_shl(value: usize, shift: usize) -> usize {
1789+
value << shift
1790+
}
1791+
#[cfg(bootstrap)]
1792+
const unsafe fn unchecked_shr(value: usize, shift: usize) -> usize {
1793+
value >> shift
1794+
}
1795+
#[cfg(not(bootstrap))]
1796+
use intrinsics::{unchecked_shl, unchecked_shr};
17871797

17881798
/// Calculate multiplicative modular inverse of `x` modulo `m`.
17891799
///

0 commit comments

Comments
 (0)