avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] Gcc is weird sometimes...


From: George Spelvin
Subject: [avr-libc-dev] Gcc is weird sometimes...
Date: 17 Dec 2016 23:33:23 -0500

The following patch (analogous to one I made to the PRINTF_MIN code
which saved quite a bit of code space) has strangely contradictory code
size effects.

If anyone else feels like tying it with a different compiler version
(I'm using gcc-7 SVN trunk from a few days ago), I'd be interested in
the results.  ("size `find . -name vfprintf_std.o | sort`" is the heart
of these tables.)

Before  After   Delta   filename
1030    1036    + 6     ./avr/lib/avr2/tiny-stack/vfprintf_std.o
1030    1052    +22     ./avr/lib/avr2/vfprintf_std.o
 916     932    +16     ./avr/lib/avr25/tiny-stack/vfprintf_std.o
 916     948    +32     ./avr/lib/avr25/vfprintf_std.o
1064    1080    +16     ./avr/lib/avr3/vfprintf_std.o
1064    1080    +16     ./avr/lib/avr31/vfprintf_std.o
 950     978    +28     ./avr/lib/avr35/vfprintf_std.o
 916     948    +32     ./avr/lib/avr4/vfprintf_std.o
 946     974    +28     ./avr/lib/avr5/vfprintf_std.o
1028     974    -54     ./avr/lib/avr51/vfprintf_std.o
1026     974    -54     ./avr/lib/avr6/vfprintf_std.o
 946     962    +16     ./avr/lib/avrxmega2/vfprintf_std.o
1016     962    -54     ./avr/lib/avrxmega4/vfprintf_std.o
1016     962    -54     ./avr/lib/avrxmega5/vfprintf_std.o
1016     962    -54     ./avr/lib/avrxmega6/vfprintf_std.o
1016     962    -54     ./avr/lib/avrxmega7/vfprintf_std.o

What I'm doing is merging the signed decimal printing code with the
rest, so the "(flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int)"
code and the call to __ultoa_invert() is shared.

That requires a flag bit for "signed" which is hard to find; they're
nearly all in use.  Already, the FL_SPACE and FL_PLUS flags
do double duty; if FL_ALT is set (which never happens with decimal),
then they're used for the FL_ALTHEX and FL_ALTUPP flags.

(I can't use the FL_NEGATIVE flag because that's the same bit
as FL_LONG, and so not available until after the va_arg() call.)

So I use the FL_ALT flag again, but directly test if base == 10.
If so, it's a "signed" flag.

There's a little bit more flag manipulation, but I had hoped the net
effect would be beneficial.  Unfortunately, it's confusing.


diff --git a/avr-libc/libc/stdio/vfprintf.c b/avr-libc/libc/stdio/vfprintf.c
index 0d8c892a..0e1df5ba 100644
--- a/avr-libc/libc/stdio/vfprintf.c
+++ b/avr-libc/libc/stdio/vfprintf.c
@@ -615,19 +615,14 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap)
            }
        }
 
-       if (c == 'd' || c == 'i') {
-           long x = (flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int);
-           flags &= ~(FL_NEGATIVE | FL_ALT);
-           if (x < 0) {
-               x = -x;
-               flags |= FL_NEGATIVE;
-           }
-           c = __ultoa_invert (x, (char *)buf, 10) - (char *)buf;
-
-       } else {
+       {
            int base;
 
-           if (c == 'u') {
+           if (c == 'd' || c == 'i') {
+               flags |= FL_ALT;
+               base = 10;
+               goto ultoa;
+           } else if (c == 'u') {
                flags &= ~FL_ALT;
                base = 10;
                goto ultoa;
@@ -638,7 +633,7 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap)
            switch (c) {
              case 'o':
                base = 8;
-               goto ultoa;
+               break;
              case 'p':
                flags |= FL_ALT;
                /* FALLTHROUGH */
@@ -646,22 +641,28 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap)
                if (flags & FL_ALT)
                    flags |= FL_ALTHEX;
                base = 16;
-               goto ultoa;
+               break;
              case 'X':
                if (flags & FL_ALT)
                    flags |= (FL_ALTHEX | FL_ALTUPP);
                base = 16 | XTOA_UPPER;
-             ultoa:
-               c = __ultoa_invert ((flags & FL_LONG)
-                                   ? va_arg(ap, unsigned long)
-                                   : va_arg(ap, unsigned int),
-                                   (char *)buf, base)  -  (char *)buf;
-               flags &= ~FL_NEGATIVE;
                break;
-
              default:
                goto ret;
            }
+         ultoa:
+           {
+               long x = (flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int);
+               flags &= ~FL_LONG;
+               if (flags & FL_ALT && base == 10) {
+                   flags &= ~FL_ALT;
+                   if (x < 0) {
+                       x = -x;
+                       flags |= FL_NEGATIVE;
+                   }
+               }
+               c = __ultoa_invert (x, (char *)buf, base)  -  (char *)buf;
+           }
        }
 
        {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]