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

From: David Desobry

Date: Tue Jan 20 2026 - 18:50:30 EST


On 1/20/26 22:46, David Laight wrote:


Maybe better to write as:
if (val < 0) {
d = 1;
v = -val;
} else {
d = 0;
v = val;
}
The compiler will only generate one jump.

Agreed, I've adopted this in v3.


- while (val >= m) {
- m *= 10;
- d++;
+ switch (v) {
+ case 0 ... 9:
+ return d + 1;
+ case 10 ... 99:
+ return d + 2;
+ case 100 ... 999:
+ return d + 3;
+ case 1000 ... 9999:
+ return d + 4;
+ case 10000 ... 99999:
+ return d + 5;
+ case 100000 ... 999999:
+ return d + 6;
+ case 1000000 ... 9999999:
+ return d + 7;
+ case 10000000 ... 99999999:
+ return d + 8;
+ case 100000000 ... 999999999:
+ return d + 9;
+ default:
+ return d + 10;

clang generates something really horrid for that.

Either:
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;
or:
if ((++d && v > 9) &&
(++d && v > 99) &&
(++d && v > 999) &&
(++d && v > 9999) &&
(++d && v > 99999) &&
(++d && v > 999999) &&
(++d && v > 9999999) &&
(++d && v > 99999999) &&
(++d && v > 999999999))
d++;
return d;
generate better code.
In particular it is almost certainly best to only have one taken branch.
Dumping in a load of unlikely() might help that as well.
(Neither compiler does the ++d inline, the add is done before the return.)

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.

David