diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2011-07-07 01:18:49 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-07 04:52:24 -0700 |
commit | be0e1e788b0973147b6b83cc940676cc26009eb7 (patch) | |
tree | 75083bdb5b5d9e266b0c632406d67f69505d527c /lib | |
parent | 97bc3633bec7ed0fdfbda6b9cf86c51e4f58f8e2 (diff) | |
download | linux-be0e1e788b0973147b6b83cc940676cc26009eb7.tar.gz linux-be0e1e788b0973147b6b83cc940676cc26009eb7.tar.bz2 linux-be0e1e788b0973147b6b83cc940676cc26009eb7.zip |
lib/checksum.c: optimize do_csum a bit
Reduce the number of variables modified by the loop in do_csum() by 1,
which seems like a good idea. On Nios II (a RISC CPU with 3-operand
instruction set) it reduces the loop from 7 to 6 instructions, including
the conditional branch.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/checksum.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/lib/checksum.c b/lib/checksum.c index 097508732f34..8df2f91e6d98 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -49,7 +49,7 @@ static inline unsigned short from32to16(unsigned int x) static unsigned int do_csum(const unsigned char *buff, int len) { - int odd, count; + int odd; unsigned int result = 0; if (len <= 0) @@ -64,25 +64,22 @@ static unsigned int do_csum(const unsigned char *buff, int len) len--; buff++; } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { + if (len >= 2) { if (2 & (unsigned long) buff) { result += *(unsigned short *) buff; - count--; len -= 2; buff += 2; } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { + if (len >= 4) { + const unsigned char *end = buff + ((unsigned)len & ~3); unsigned int carry = 0; do { unsigned int w = *(unsigned int *) buff; - count--; buff += 4; result += carry; result += w; carry = (w > result); - } while (count); + } while (buff < end); result += carry; result = (result & 0xffff) + (result >> 16); } |