avr-gcc-list
[Top][All Lists]
Advanced

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

Re: [avr-gcc-list] binutils 2.22 blow up program size with -flto


From: Georg-Johann Lay
Subject: Re: [avr-gcc-list] binutils 2.22 blow up program size with -flto
Date: Sun, 12 Aug 2012 11:15:32 +0200
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

CCing Jörg and Marek

Volker Kuhlmann schrieb:
Weddington, Eric wrote:

There are known issues with LTO and AVR, though unknown reasons why.

Would you have a link to that known issues list?

GCC PR50616: [mingw32] ICE: lto1.exe: invalid resolution in the
             resolution file

GCC PR52692: [avr] Add support for avr-specific built-ins + LTO

BIN PR12742: [mingw32] mingw32 and --enable-lto in Canadian cross build

Moreover, I observed problems with LTO and unfriendly installation
paths, e.g. such containing blanks.

* binutils 2.22 really increases program size, and the combination with
avr-gcc 4.6.2 and LTO fails. What actually is the reason for this?
And is this a gcc problem?

It's hard to imagine how binutils would be capable of increasing the
program size.  Maybe you are observing a different artifact and it's
just incidental.

* Program size from avr-gcc 4.3 to 4.6 decreases steadily, generally
speaking. LTO with 4.6 has a positive effect with binutils 2.19.1
and is non-functional with 2.22.

Binutils has/had bugs that are unrelated to LTO, e.g.
PR13812, PR12494, PR14058, PR13899, PR13697.

* 4.7 is, from previous posts on this list, the best optimised and least
buggy gcc version. However its program size gives no advantage over 4.3
in any of the ways I have tried, which is unfortunate. More precisely,
without LTO it produces larger code than 4.3 - no incentive to upgrade.

There is no /guarantee/ for a smaller code size.  I still see 4.7 being
outperformed by 3.4.6 for real-world programs.

GCC has many optimization flaws nobody cares about:

PR52278, PR52025, PR49857, PR49807, PR49491, PR43745, PR41076, PR36884,
PR27663, ...

And at least one that's fixed in 4.7.2+ only: PR53595.

You might also check the command options if any of these can improve the
situation:

http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Feinabstimmung_der_Optimizer

And you might get wrong code because your AVR-Libc version does not
implement #35407, see also the GCC 4.7 release notes.

See also GCC PR52737, PR51345.

* binutils 2.22 make programs *bigger*. I wouldn't have expected binutils
to do something like that, what could be the reason?

How is anybody supposed to know an answer without a test case?

* gcc 4.7, with all the work Johann has put into it, produces code that
is at least as big as the one from 4.3. Is this expected, or did I build
the tool(s) wrong?

As said, there is no guarantee for code reduction.
Also it highly depends on command options and programming style.

One known problem is the way AVR-Libc "supplies" basic single float (SF)
routines:  It "overrides" the routines from libgcc for some reasons.

This relies on a specific -library sequence during the final link.

Suppose the following small program:

/* foo.c */
float volatile f;

int main (void)
{
    return f;
}

And compile it to foo.o with, say

$ avr-gcc -mmcu=atmega8 foo.c -Os -flto -c

Then link with

$ avr-gcc -mmcu=atmega8 foo.o -Os -o foo.elf -lm -v

and with by setup (avr-gcc 4.7.1, binutils ~2.23, AVR-Libc 1.8.0)
the elf has a size of 278 bytes.

$ avr-gcc -mmcu=atmega8 foo.o -Os -o foo.elf -lm -v -flto

gives a size of 582 bytes because the SF routines from libgcc are
linked:

COLLECT_GCC_OPTIONS='-mmcu=atmega8' '-Os' '-o' 'foo.elf' '-v' '-flto'
.../collect2.exe ... -plugin-opt=-pass-through=-lgcc 
-plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -flto -m avr4 -o 
foo.elf ... -lm -lgcc -lc -lgcc

The -v options does not show how the final link is actually performed,
but the result indicates that it's similar to

$ ld ... -lgcc -lc -lgcc -m avr4 -o foo.elf ... -lm -lgcc -lc -lgcc

For the test case a hack around is to link with

$ avr-gcc ... -nodefaultlibs -lm -lgcc -lc -lgcc

instead of with -lm.  Thus we have just another déjà-vu of PR28718...

One proposed hack was to add a configure option to GCC:

From 2011-11-10 [off-list] PR28718 Infos?

As Georg-Johann Lay wrote:

>> Dazu habe ich folgende Fragen:
>> >> o Ist sowas überhaupt sinnvoll (per extra configure-Option)?

Sinnvoller würde ich es finden, die avr-libc-Teile stattdessen in die
libgcc zu packen, aber ich fürchte, dass das mit all dem copyright
assignment Krams für die beteiligten Leute zumindest ein jahrelanger
Prozess wäre, einschließlich des Umschreibens der Lizenz.  Teilweise
stammt der Code noch von Michael Stumpf (2002 geschrieben), und ihn
hatten wir damals extra noch um die Genehmigung gebeten, seinen Code
unter BSD-Lizenz zu stellen (ursprünglich war er unter GPL), damit er
zur Lizenz der übrigen avr-libc passt.

>> o Falls ja: Welche libgcc-Funktionen werden auch von der
>>    avr-libc dargestellt und können über den geplanten Mechanismus
>>    rausgekickt werden?

Gute Frage. ;-)
% nm /usr/local/avr/lib/libm.a | grep 'T __'

00000002 T __addsf3
00000000 T __subsf3
00000000 T __cmpsf2
00000000 T __eqsf2
00000000 T __lesf2
00000000 T __ltsf2
00000000 T __nesf2
00000000 T __divsf3
00000000 T __fixsfdi
0000000a T __fixunssfdi
00000000 T __fixsfsi
00000000 T __fixunssfsi
00000000 T __floatdisf
00000004 T __floatsisf
00000000 T __floatunsisf
00000000 T __floatundisf
00000000 T __gesf2
00000000 T __gtsf2
00000000 T __mulsf3
00000000 T __negsf2
00000000 T __unordsf2

I cut down that list to possible candidates (__fp_* are not).

Das müssten sie sein, oder?

Maybe there are some missing like ffs, parity, popcount, etc.

Disclaimer: das oben ist erstmal nur für avr3 direkt aus den binären
Bibliotheken gezogen.  Wir sollten dafür in der avr-libc noch eine
Methode finden, eine solche Liste explizit zu pflegen und dann auch zu
testen, dass genau die in dieser Liste genannten Symbole auch
tatsächlich vorhanden sind.

Schwierig wird das natürlich mit der relativen Unabhängigkeit von
Compiler und Bibliothek bei irgendwelchen Änderungen.

Or instead of --with-avrlibc=yes or --with-avrlibc=1.8.0 there could
be --with-lib2funcs-exclude=<list> append to LIB2FUNCS_EXCLUDE.

avr.h currently has no macro to define LINK_GCC_C_SEQUENCE_SPEC which
defaults to "%G %L %G".

Maybe there could be "%{lm:-lm %G %L %G} %{!lm: %G %L %G}" or something like that.

Or AVR-Libc could move -lm into -lc and then "%L %G %L %G" but I don't
know if that breaks newlib, for example.

Again it's likely this must be factored out by --with-avrlibc

But that's all hack.

The only proper solution is to move that stuff from AVR-Libc to libgcc.

Johann




reply via email to

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