Re: [PATCH v2] x86/lib: Optimize num_digits() and fix INT_MIN overflow

From: David Desobry

Date: Tue Jan 20 2026 - 20:22:16 EST


On 1/21/26 00:49, H. Peter Anvin wrote:
On 2026-01-20 15:32, David Desobry wrote:

Good catch. I have replaced the switch statement with a linear if-chain in v3
to ensure better code generation for both GCC and Clang.


I think a bigger deal is just to change it to unsigned.

Now, for really silly optimization:

int num_digits(unsigned int x)
{
int n = 0;
asm("cmp %2,%1; sbb $-2,%0" : "+r" (n) : "r" (x), "g" (10));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (100));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (1000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (10000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (100000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (1000000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (10000000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (100000000));
asm("cmp %2,%1; sbb $-1,%0" : "+r" (n) : "r" (x), "g" (1000000000));

return n;
}

No branches at all!

-hpa


Actually, the V3 change:
if (val < 0) {
- d++;
- val = -val;
+ d = 1;
+ v = -val;
+ } else {
+ d = 0;
+ v = val;
}
reintroduced the undefined behavior for val == INT_MIN.
So this V3 version is incorrect.
I'm not familiar enough with the rest of the codebase to know if changing the function signature to unsigned int is correct here.