about summary refs log tree commit diff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2024-03-20 01:27:33 -0700
committeriximeow <me@iximeow.net>2024-03-20 03:33:07 -0700
commite7fbf7223f640c5121b21183cd26ecd3ccb6a820 (patch)
tree38f9f6c5f5f44553ad41618048043623aa7cd3cb
parentb7dcabe55e3b915ba9488dc374f752404c2c8945 (diff)
downloadrust-e7fbf7223f640c5121b21183cd26ecd3ccb6a820.tar.gz
rust-e7fbf7223f640c5121b21183cd26ecd3ccb6a820.zip
improve codegen of fmt_num to delete unreachable panic
it seems LLVM doesn't realize that `curr` is always decremented at least
once in either loop formatting characters of the input string by their
appropriate radix, and so the later `&buf[curr..]` generates a check for
out-of-bounds access and panic. this is unreachable in reality as even
for `x == T::zero()` we'll produce at least the character
`Self::digit(T::zero())` for at least one character output, and `curr`
will always be at least one below `buf.len()`.

adjust `fmt_int` to make this fact more obvious to the compiler, which
fortunately (or unfortunately) results in a measurable performance
improvement for workloads heavy on formatting integers.
-rw-r--r--library/core/src/fmt/num.rs8
1 files changed, 4 insertions, 4 deletions
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index ab2158394bf..abe833a4bf2 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -79,11 +79,11 @@ unsafe trait GenericRadix: Sized {
         if is_nonnegative {
             // Accumulate each digit of the number from the least significant
             // to the most significant figure.
-            for byte in buf.iter_mut().rev() {
+            loop {
                 let n = x % base; // Get the current place value.
                 x = x / base; // Deaccumulate the number.
-                byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
                 curr -= 1;
+                buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
                 if x == zero {
                     // No more digits left to accumulate.
                     break;
@@ -91,11 +91,11 @@ unsafe trait GenericRadix: Sized {
             }
         } else {
             // Do the same as above, but accounting for two's complement.
-            for byte in buf.iter_mut().rev() {
+            loop {
                 let n = zero - (x % base); // Get the current place value.
                 x = x / base; // Deaccumulate the number.
-                byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
                 curr -= 1;
+                buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
                 if x == zero {
                     // No more digits left to accumulate.
                     break;