Gcc is weird sometimes...

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Gcc is weird sometimes...

George Spelvin
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;
+    }
  }
 
  {

_______________________________________________
AVR-libc-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/avr-libc-dev