From 3b2436c1361e03d52b4d5d9a188ea94909bd245a Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 23 Apr 2024 15:49:00 +0200 Subject: [PATCH 1/2] unroll first iter of checked_ilog loop to save one multiplication --- library/core/src/num/uint_macros.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c13763243f031..a76b84e7e5412 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1093,9 +1093,12 @@ macro_rules! uint_impl { pub const fn checked_ilog(self, base: Self) -> Option { 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 { From 245cc23a2f7d55c22437b2482f057fa44cce0624 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 23 Apr 2024 18:31:57 +0200 Subject: [PATCH 2/2] add codegen test The test confirms that when val < base, we do not divide or multiply. --- tests/codegen/checked_ilog.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/codegen/checked_ilog.rs diff --git a/tests/codegen/checked_ilog.rs b/tests/codegen/checked_ilog.rs new file mode 100644 index 0000000000000..8f3c07119feeb --- /dev/null +++ b/tests/codegen/checked_ilog.rs @@ -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 { + // 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) +}