[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260120231940.17557-1-david.desobry@formalgen.com>
Date: Wed, 21 Jan 2026 00:19:40 +0100
From: David Desobry <david.desobry@...malgen.com>
To: tglx@...nel.org,
mingo@...hat.com,
bp@...en8.de,
dave.hansen@...ux.intel.com
Cc: x86@...nel.org,
hpa@...or.com,
linux-kernel@...r.kernel.org,
David Desobry <david.desobry@...malgen.com>
Subject: [PATCH v3] x86/lib: Optimize num_digits() and fix INT_MIN overflow
The current implementation of num_digits() uses a loop with repeated
multiplication, which is inefficient. Furthermore, the negation of
the input value "val = -val" causes undefined behavior when val is
INT_MIN, as its absolute value cannot be represented as a 32-bit integer.
Replace the loop with a linear chain of comparisons. This allows the
compiler to generate optimized branch sequences, providing better
performance than the original loop and more efficient assembly than a
switch statement on compilers like Clang. By using an internal unsigned
int to handle the magnitude, we safely handle the INT_MIN case without
relying on 64-bit types or triggering undefined signed overflow.
Removed the outdated comment.
Signed-off-by: David Desobry <david.desobry@...malgen.com>
---
v3:
- Replaced switch statement with a linear if-chain for better compiler
optimization.
- Simplified sign handling logic to a single if/else block.
- (v2) Fixed INT_MIN overflow using unsigned magnitude and removed
outdated comment.
arch/x86/lib/misc.c | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/arch/x86/lib/misc.c b/arch/x86/lib/misc.c
index 40b81c338ae5..3d56583411cf 100644
--- a/arch/x86/lib/misc.c
+++ b/arch/x86/lib/misc.c
@@ -3,22 +3,38 @@
/*
* Count the digits of @val including a possible sign.
- *
- * (Typed on and submitted from hpa's mobile phone.)
*/
int num_digits(int val)
{
- long long m = 10;
- int d = 1;
+ unsigned int v;
+ int d;
if (val < 0) {
- d++;
- val = -val;
+ d = 1;
+ v = -val;
+ } else {
+ d = 0;
+ v = val;
}
- while (val >= m) {
- m *= 10;
- d++;
- }
- return d;
+ if (v <= 9)
+ return d + 1;
+ if (v <= 99)
+ return d + 2;
+ if (v <= 999)
+ return d + 3;
+ if (v <= 9999)
+ return d + 4;
+ if (v <= 99999)
+ return d + 5;
+ if (v <= 999999)
+ return d + 6;
+ if (v <= 9999999)
+ return d + 7;
+ if (v <= 99999999)
+ return d + 8;
+ if (v <= 999999999)
+ return d + 9;
+
+ return d + 10;
}
--
2.43.0
Powered by blists - more mailing lists