diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-04-02 21:22:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-02 21:22:01 +0200 |
| commit | 1b0e46f8a05de7497ea17c8ad0a1c525c1b123f6 (patch) | |
| tree | 085f3ddab6d607e9e10802abf40dfe77497c6448 /library/core | |
| parent | d63ddef8033b056b73efc4531769dca07e3a2f66 (diff) | |
| parent | 46265218319573cb9afcce0c2e8dc7411ab28768 (diff) | |
| download | rust-1b0e46f8a05de7497ea17c8ad0a1c525c1b123f6.tar.gz rust-1b0e46f8a05de7497ea17c8ad0a1c525c1b123f6.zip | |
Rollup merge of #123226 - scottmcm:u32-shifts, r=WaffleLapkin
De-LLVM the unchecked shifts [MCP#693] This is just one part of the MCP (https://github.com/rust-lang/compiler-team/issues/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
Diffstat (limited to 'library/core')
| -rw-r--r-- | library/core/src/intrinsics.rs | 6 | ||||
| -rw-r--r-- | library/core/src/num/int_macros.rs | 32 | ||||
| -rw-r--r-- | library/core/src/num/mod.rs | 11 | ||||
| -rw-r--r-- | library/core/src/num/uint_macros.rs | 32 | ||||
| -rw-r--r-- | library/core/src/ptr/mod.rs | 14 |
5 files changed, 64 insertions, 31 deletions
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 26e813346be..e08828f0005 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2224,18 +2224,20 @@ extern "rust-intrinsic" { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] + #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_nounwind] - pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T; + pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// `y < 0` or `y >= N`, where N is the width of T in bits. /// /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] + #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_nounwind] - pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T; + pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T; /// Returns the result of an unchecked addition, resulting in /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 2f5184da885..e34e9b7fff6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1227,10 +1227,18 @@ macro_rules! int_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shl`. - // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } + #[cfg(bootstrap)] + { + // For bootstrapping, just use built-in primitive shift. + // panicking is a legal manifestation of UB + self << rhs + } + #[cfg(not(bootstrap))] + { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shl`. + unsafe { intrinsics::unchecked_shl(self, rhs) } + } } /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is @@ -1310,10 +1318,18 @@ macro_rules! int_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shr`. - // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } + #[cfg(bootstrap)] + { + // For bootstrapping, just use built-in primitive shift. + // panicking is a legal manifestation of UB + self >> rhs + } + #[cfg(not(bootstrap))] + { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shr`. + unsafe { intrinsics::unchecked_shr(self, rhs) } + } } /// Checked absolute value. Computes `self.abs()`, returning `None` if diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9e519dad432..9ebbb4ffe80 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -285,17 +285,6 @@ macro_rules! widening_impl { }; } -macro_rules! conv_rhs_for_unchecked_shift { - ($SelfT:ty, $x:expr) => {{ - // If the `as` cast will truncate, ensure we still tell the backend - // that the pre-truncation value was also small. - if <$SelfT>::BITS < 32 { - intrinsics::assume($x <= (<$SelfT>::MAX as u32)); - } - $x as $SelfT - }}; -} - impl i8 { int_impl! { Self = i8, diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 3f4b5955d62..ba6a243041c 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1286,10 +1286,18 @@ macro_rules! uint_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shl`. - // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } + #[cfg(bootstrap)] + { + // For bootstrapping, just use built-in primitive shift. + // panicking is a legal manifestation of UB + self << rhs + } + #[cfg(not(bootstrap))] + { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shl`. + unsafe { intrinsics::unchecked_shl(self, rhs) } + } } /// Checked shift right. Computes `self >> rhs`, returning `None` @@ -1369,10 +1377,18 @@ macro_rules! uint_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shr`. - // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } + #[cfg(bootstrap)] + { + // For bootstrapping, just use built-in primitive shift. + // panicking is a legal manifestation of UB + self >> rhs + } + #[cfg(not(bootstrap))] + { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shr`. + unsafe { intrinsics::unchecked_shr(self, rhs) } + } } /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 56378b437e7..9514f431769 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1781,9 +1781,19 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= // 1, where the method versions of these operations are not inlined. use intrinsics::{ - assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, - unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, + assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_sub, + wrapping_add, wrapping_mul, wrapping_sub, }; + #[cfg(bootstrap)] + const unsafe fn unchecked_shl(value: usize, shift: usize) -> usize { + value << shift + } + #[cfg(bootstrap)] + const unsafe fn unchecked_shr(value: usize, shift: usize) -> usize { + value >> shift + } + #[cfg(not(bootstrap))] + use intrinsics::{unchecked_shl, unchecked_shr}; /// Calculate multiplicative modular inverse of `x` modulo `m`. /// |
