about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/num/uint_macros.rs7
-rw-r--r--tests/codegen/checked_ilog.rs20
2 files changed, 25 insertions, 2 deletions
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index f70c34199ac..50a8f411119 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -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 {
diff --git a/tests/codegen/checked_ilog.rs b/tests/codegen/checked_ilog.rs
new file mode 100644
index 00000000000..8f3c07119fe
--- /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<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)
+}