Re: [PATCH] Reduce the number of expensive division instructions doneby _parse_integer()

From: Linus Torvalds
Date: Thu Feb 09 2012 - 12:08:30 EST


On Thu, Feb 9, 2012 at 8:58 AM, Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
>
> So David's patch looks ok, although if this really is
> performance-critical (and I could imagine some crazy /proc or /sys
> access loads where the divide really does show up very clearly) I do
> think it could be even done more efficiently. But probably only if we
> start doing some arch-specific stuff.

Looking at the code generated, the "val >> 60" thing actually does
generate a shift, and at least on x86-64, the attached patch generates
better code.

David, does this work for you? I also removed the nasty pointer
indirection crap.

Linus
lib/kstrtox.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index 7a94c8f14e29..b1dd3e7d88cb 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -44,12 +44,13 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
*
* Don't you dare use this function.
*/
-unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res)
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
{
+ unsigned long long res;
unsigned int rv;
int overflow;

- *res = 0;
+ res = 0;
rv = 0;
overflow = 0;
while (*s) {
@@ -64,12 +65,19 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long

if (val >= base)
break;
- if (*res > div_u64(ULLONG_MAX - val, base))
- overflow = 1;
- *res = *res * base + val;
+ /*
+ * Check for overflow only if we are within range of
+ * it in the max base we support (16)
+ */
+ if (unlikely(res & (~0ull << 60))) {
+ if (res > div_u64(ULLONG_MAX - val, base))
+ overflow = 1;
+ }
+ res = res * base + val;
rv++;
s++;
}
+ *p = res;
if (overflow)
rv |= KSTRTOX_OVERFLOW;
return rv;