Messages in this thread Patch in this message | | | From | Linus Torvalds <> | Date | Thu, 9 Feb 2012 09:08:05 -0800 | Subject | Re: [PATCH] Reduce the number of expensive division instructions done by _parse_integer() |
| |
On Thu, Feb 9, 2012 at 8:58 AM, Linus Torvalds <torvalds@linux-foundation.org> 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; | |