Skip to content

Commit

Permalink
Rollup merge of rust-lang#124294 - tspiteri:ilog-first-iter, r=the8472
Browse files Browse the repository at this point in the history
Unroll first iteration of checked_ilog loop

This follows the optimization of rust-lang#115913. As shown in rust-lang#115913 (comment), the performance was improved in all important cases, but some regressions were introduced for the benchmarks `u32_log_random_small`, `u8_log_random` and `u8_log_random_small`.

Basically, rust-lang#115913 changed the implementation from one division per iteration to one multiplication per iteration plus one division. When there are zero iterations, this is a regression from zero divisions to one division.

This PR avoids this by avoiding the division if we need zero iterations by returning `Some(0)` early. It also reduces the number of multiplications by one in all other cases.
  • Loading branch information
fmease committed Jun 1, 2024
2 parents 0038c02 + 245cc23 commit 007ba0b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
7 changes: 5 additions & 2 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,9 +1148,12 @@ macro_rules! uint_impl {
pub const fn checked_ilog(self, base: Self) -> Option<u32> {
if self <= 0 || base <= 1 {
None
} else if self < base {
Some(0)
} else {
let mut n = 0;
let mut r = 1;
// Since base >= self, n >= 1
let mut n = 1;
let mut r = base;

// Optimization for 128 bit wide integers.
if Self::BITS == 128 {
Expand Down
20 changes: 20 additions & 0 deletions tests/codegen/checked_ilog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ compile-flags: -O

#![crate_type = "lib"]

// Ensure that when val < base, we do not divide or multiply.

// CHECK-LABEL: @checked_ilog
// CHECK-SAME: (i16 noundef %val, i16 noundef %base)
#[no_mangle]
pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
// CHECK-NOT: udiv
// CHECK-NOT: mul
// CHECK: %[[IS_LESS:.+]] = icmp ult i16 %val, %base
// CHECK-NEXT: br i1 %[[IS_LESS]], label %[[TRUE:.+]], label %[[FALSE:.+]]
// CHECK: [[TRUE]]:
// CHECK-NOT: udiv
// CHECK-NOT: mul
// CHECK: ret { i32, i32 }
val.checked_ilog(base)
}

0 comments on commit 007ba0b

Please sign in to comment.