aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2015-04-15 19:17:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 19:35:23 -0400
commit51be17dfff753e72872f096ce1e654734f2fec50 (patch)
treece599aed4449d1357479ae4c07a6100fdc625a40 /lib/vsprintf.c
parent7b1460eccad0621e0c48f52bbedeb7adddc55ac9 (diff)
lib/vsprintf.c: eliminate some branches
Since FORMAT_TYPE_INT is simply 1 more than FORMAT_TYPE_UINT, and similarly for BYTE/UBYTE, SHORT/USHORT, LONG/ULONG, we can eliminate a few instructions by making SIGN have the value 1 instead of 2, and then use arithmetic instead of branches for computing the right spec->type. It's a little hacky, but certainly in the same spirit as SMALL needing to have the value 0x20. For example for the spec->qualifier == 'l' case, gcc now generates 75e: 0f b6 53 01 movzbl 0x1(%rbx),%edx 762: 83 e2 01 and $0x1,%edx 765: 83 c2 09 add $0x9,%edx 768: 88 13 mov %dl,(%rbx) instead of 763: 0f b6 53 01 movzbl 0x1(%rbx),%edx 767: 83 e2 02 and $0x2,%edx 76a: 80 fa 01 cmp $0x1,%dl 76d: 19 d2 sbb %edx,%edx 76f: 83 c2 0a add $0xa,%edx 772: 88 13 mov %dl,(%rbx) Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c30
1 files changed, 11 insertions, 19 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b235c96167d3..318d583fe862 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -340,8 +340,8 @@ int num_to_str(char *buf, int size, unsigned long long num)
340 return len; 340 return len;
341} 341}
342 342
343#define ZEROPAD 1 /* pad with zero */ 343#define SIGN 1 /* unsigned/signed, must be 1 */
344#define SIGN 2 /* unsigned/signed long */ 344#define ZEROPAD 2 /* pad with zero */
345#define PLUS 4 /* show plus */ 345#define PLUS 4 /* show plus */
346#define SPACE 8 /* space if plus */ 346#define SPACE 8 /* space if plus */
347#define LEFT 16 /* left justified */ 347#define LEFT 16 /* left justified */
@@ -447,7 +447,7 @@ char *number(char *buf, char *end, unsigned long long num,
447 spec.precision = i; 447 spec.precision = i;
448 /* leading space padding */ 448 /* leading space padding */
449 spec.field_width -= spec.precision; 449 spec.field_width -= spec.precision;
450 if (!(spec.flags & (ZEROPAD+LEFT))) { 450 if (!(spec.flags & (ZEROPAD | LEFT))) {
451 while (--spec.field_width >= 0) { 451 while (--spec.field_width >= 0) {
452 if (buf < end) 452 if (buf < end)
453 *buf = ' '; 453 *buf = ' ';
@@ -1738,29 +1738,21 @@ qualifier:
1738 if (spec->qualifier == 'L') 1738 if (spec->qualifier == 'L')
1739 spec->type = FORMAT_TYPE_LONG_LONG; 1739 spec->type = FORMAT_TYPE_LONG_LONG;
1740 else if (spec->qualifier == 'l') { 1740 else if (spec->qualifier == 'l') {
1741 if (spec->flags & SIGN) 1741 BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
1742 spec->type = FORMAT_TYPE_LONG; 1742 spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
1743 else
1744 spec->type = FORMAT_TYPE_ULONG;
1745 } else if (_tolower(spec->qualifier) == 'z') { 1743 } else if (_tolower(spec->qualifier) == 'z') {
1746 spec->type = FORMAT_TYPE_SIZE_T; 1744 spec->type = FORMAT_TYPE_SIZE_T;
1747 } else if (spec->qualifier == 't') { 1745 } else if (spec->qualifier == 't') {
1748 spec->type = FORMAT_TYPE_PTRDIFF; 1746 spec->type = FORMAT_TYPE_PTRDIFF;
1749 } else if (spec->qualifier == 'H') { 1747 } else if (spec->qualifier == 'H') {
1750 if (spec->flags & SIGN) 1748 BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
1751 spec->type = FORMAT_TYPE_BYTE; 1749 spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
1752 else
1753 spec->type = FORMAT_TYPE_UBYTE;
1754 } else if (spec->qualifier == 'h') { 1750 } else if (spec->qualifier == 'h') {
1755 if (spec->flags & SIGN) 1751 BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
1756 spec->type = FORMAT_TYPE_SHORT; 1752 spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
1757 else
1758 spec->type = FORMAT_TYPE_USHORT;
1759 } else { 1753 } else {
1760 if (spec->flags & SIGN) 1754 BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
1761 spec->type = FORMAT_TYPE_INT; 1755 spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
1762 else
1763 spec->type = FORMAT_TYPE_UINT;
1764 } 1756 }
1765 1757
1766 return ++fmt - start; 1758 return ++fmt - start;