From bc809befe2bdb10ed174e888185baa525fed4b7c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Nov 2025 15:22:50 +0100 Subject: [PATCH] use funnel shift as fallback impl for rotating shifts --- .../src/interpret/intrinsics.rs | 23 ------------------- library/core/src/intrinsics/mod.rs | 20 +++++++++++++--- library/core/src/num/uint_macros.rs | 2 ++ 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 58d7f8ef8c63..ffd7833dba1e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -333,29 +333,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let r = self.read_immediate(&args[1])?; self.exact_div(&l, &r, dest)?; } - sym::rotate_left | sym::rotate_right => { - // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) - // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) - let layout_val = self.layout_of(instance_args.type_at(0))?; - let val = self.read_scalar(&args[0])?; - let val_bits = val.to_bits(layout_val.size)?; // sign is ignored here - - let layout_raw_shift = self.layout_of(self.tcx.types.u32)?; - let raw_shift = self.read_scalar(&args[1])?; - let raw_shift_bits = raw_shift.to_bits(layout_raw_shift.size)?; - - let width_bits = u128::from(layout_val.size.bits()); - let shift_bits = raw_shift_bits % width_bits; - let inv_shift_bits = (width_bits - shift_bits) % width_bits; - let result_bits = if intrinsic_name == sym::rotate_left { - (val_bits << shift_bits) | (val_bits >> inv_shift_bits) - } else { - (val_bits >> shift_bits) | (val_bits << inv_shift_bits) - }; - let truncated_bits = layout_val.size.truncate(result_bits); - let result = Scalar::from_uint(truncated_bits, layout_val.size); - self.write_scalar(result, dest)?; - } sym::copy => { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 5ba2d92a4596..d9467b8a43ac 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -56,7 +56,7 @@ use crate::ffi::va_list::{VaArgSafe, VaListImpl}; use crate::marker::{ConstParamTy, Destruct, DiscriminantKind, PointeeSized, Tuple}; -use crate::ptr; +use crate::{mem, ptr}; mod bounds; pub mod fallback; @@ -2017,7 +2017,14 @@ pub const unsafe fn unchecked_mul(x: T, y: T) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const fn rotate_left(x: T, shift: u32) -> T; +#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[miri::intrinsic_fallback_is_spec] +pub const fn rotate_left(x: T, shift: u32) -> T { + // Make sure to call the intrinsic for `funnel_shl`, not the fallback impl. + // SAFETY: we modulo `shift` so that the result is definitely less than the size of + // `T` in bits. + unsafe { unchecked_funnel_shl(x, x, shift % (mem::size_of::() as u32 * 8)) } +} /// Performs rotate right. /// @@ -2032,7 +2039,14 @@ pub const fn rotate_left(x: T, shift: u32) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const fn rotate_right(x: T, shift: u32) -> T; +#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[miri::intrinsic_fallback_is_spec] +pub const fn rotate_right(x: T, shift: u32) -> T { + // Make sure to call the intrinsic for `funnel_shr`, not the fallback impl. + // SAFETY: we modulo `shift` so that the result is definitely less than the size of + // `T` in bits. + unsafe { unchecked_funnel_shr(x, x, shift % (mem::size_of::() as u32 * 8)) } +} /// Returns (a + b) mod 2N, where N is the width of T in bits. /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1efc551d670a..8cdc7e925b68 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -351,6 +351,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[rustc_allow_const_fn_unstable(const_trait_impl)] // for the intrinsic fallback pub const fn rotate_left(self, n: u32) -> Self { return intrinsics::rotate_left(self, n); } @@ -374,6 +375,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[rustc_allow_const_fn_unstable(const_trait_impl)] // for the intrinsic fallback pub const fn rotate_right(self, n: u32) -> Self { return intrinsics::rotate_right(self, n); }