From 24124f6577f597deaf169c40acd30271b3938e1f Mon Sep 17 00:00:00 2001 From: SomeFlyingThing <306498559+SomeFlyingThing@users.noreply.github.com> Date: Fri, 14 Aug 2026 07:26:56 +1200 Subject: [PATCH] Optimize checked_next_power_of_two consumers --- library/core/src/num/uint_macros.rs | 15 ++++++++++- .../codegen-llvm/checked-next-power-of-two.rs | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/codegen-llvm/checked-next-power-of-two.rs diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5d5df10694197..06eed58ed0f87 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3954,7 +3954,20 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn checked_next_power_of_two(self) -> Option { - self.one_less_than_next_power_of_two().checked_add(1) + let result = self.one_less_than_next_power_of_two().checked_add(1); + + if let Some(result) = result { + // SAFETY: `one_less_than_next_power_of_two` returns one less than the + // smallest power of two greater than or equal to `self`. Therefore, if + // adding one succeeds, the result is a power of two at least as large as + // `self`. + unsafe { + crate::hint::assert_unchecked(result.is_power_of_two()); + crate::hint::assert_unchecked(result >= self); + } + } + + result } /// Returns the smallest power of two greater than or equal to `n`. If diff --git a/tests/codegen-llvm/checked-next-power-of-two.rs b/tests/codegen-llvm/checked-next-power-of-two.rs new file mode 100644 index 0000000000000..324bee69c0962 --- /dev/null +++ b/tests/codegen-llvm/checked-next-power-of-two.rs @@ -0,0 +1,25 @@ +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] +#![no_std] + +// CHECK-LABEL: @checked_next_power_of_two_properties +// CHECK: ret i1 true +#[no_mangle] +pub fn checked_next_power_of_two_properties(value: u64) -> bool { + value + .checked_next_power_of_two() + .is_none_or(|result| result.is_power_of_two() && result >= value) +} + +// CHECK-LABEL: @modulo_checked_next_power_of_two +// CHECK-NOT: udiv +// CHECK-NOT: urem +// CHECK: and i64 +// CHECK-NOT: udiv +// CHECK-NOT: urem +// CHECK: ret +#[no_mangle] +pub fn modulo_checked_next_power_of_two(value: u64, dividend: u64) -> Option { + value.checked_next_power_of_two().map(|divisor| dividend % divisor) +}