-
-
Notifications
You must be signed in to change notification settings - Fork 7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable link-time optimization (after switching to avr-gcc 4.5 or greater) [imported] #660
Comments
Here's a comment copied from Google Code:
I've been looking at LTO and whole program optimization as well, since it greatly increases optimization opportunities for a templated I/O library I've been working on. To get this working, -flto needs to be passed to all C/C++ compiler commands and linker commands. It seems sensible to pass -O0 to the compiler commands since optimization is done in the linker stage, but a quick test shows that this greatly increases resulting binary size, so I guess not all optimizations are run at link time and -Os must still be passed both when compiling and linking. I've tested this here on avr-gcc 4.7 in Debian using Arduino-mk and it indeed helps to reduce code size (haven't looked closely at code speed yet). However, for optimal LTO, gcc needs a "linker plugin", which doesn't seem to be available in my setup (not sure if this is a limitation of the AVR target and/or if this was / will be fixed in a more recent GCC version, thogh). AFAIU this linker plugin serves two purposes: It allows gcc to get LTO information out of archives (allowing the arduino core code in libcore.a to be included in the LTO process) and it allows gcc to know which functions are externally visible (in this case, only main()) so it can really tell if a function is used or not. As an alternative for such a linker plugin, -fwhole-program can be passed to the linker. This flag tells gcc, "I've passed you all the code for this program and only main() and any functions with the externally_visible attribute are externally visible". However, since no linker plugin is used, any .o files compiled without -flto and any .a files included in the link are not included in the LTO and the optimizer will pretend they don't exist. In the Arduino case, the LTO will not see the actual main() function (which is in libcore.a) referencing setup() and loop(), making it remove the setup() and loop() functions (and probably all of the rest of your code as well). After LTO, the linker will then try to link your (now-empty) program with libcore.a and error out with "undefined symbol setup" and "undefined symbol loop". Making -fwhole-program can be done by marking setup and loop as externally visible. e.g. put this in Arduino.h (or any other place included in the .ino file, just in main.cpp isn't enough):
Doing this makes the program a bit smaller and probably faster as well (it allows inlining and removing functions that are called in on place only, for example). However, it is probably a bit error prone to manually keep this list of externally visible functions, so I would advise only applying it if linker plugin support for AVR isn't going to happen soon and it turns out the optimization gain of -fwhole-program is significant. |
It seems that since gcc 4.8, avr-gcc has the linker plugin working, meaning we can enable -flto and it should just work :-) |
This may be enable after merging #1903 (just to keep a note inside the pull request). |
The -flto option needs to be passed to the linker as well (compiler.c.elf). Below are the extra flags I am using for Cosa build (See https://github.com/mikaelpatel/Cosa/blob/master/platform.txt-gcc-4.8.1)
This work nicely for the Cosa Arduino Framework. So far have all tests passed. Please note that some warnings from the link needs to suppressed (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396) Cheers! Mikael |
Current toolchain supports link time optimization, which is disabled by default. If you wish to use you can either modify platform.txt or provide your own custom core |
There are still problems with the LTO plugin (for Windows). It is not always included and "collect" will fail. I have disabled LTO in the Arduino IDE build (platform.txt) and only use this from the Cosa command line build (Makefile). |
Is it still the ambition to enable LTO, if this is possible without introducing any broken behaviour? If so, perhaps this issue should be left open, to track any problems and solutions with LTO found so far? I just noticed a problem with LTO giving incorrect ISR warnings. This is reported upstream and fixed in 4.8.3. |
I guess so, let's reopen this one and collect all the problems around LTO: @mikaelpatel @Lauszus @xxxajk if anyone has information and links, please post here. |
Dev-list discussion here: |
@cmaglie we disable optimization in the code for the versions of GCC that we know have the problem. |
Some goodies for the weekend: Windows x86 All the toolchains has been cross compiled on Linux using this script (in case you want to compile it by yourself). To enable LTO simply add the following flags to your compiler.c.extra_flags=-Wextra -flto
compiler.c.elf.extra_flags=-w -flto -fuse-linker-plugin
compiler.S.extra_flags=-flto
compiler.cpp.extra_flags=-Wextra -flto
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags= and a platform-dependant
As usual, testing and error reporting is VERY well accepted 😉 @matthijskooijman - could you give this compiler+flags a spin with your arduino-mass-builder to get some metrics? |
Cool! This script, is it based on on in the avr-toolchain repo? And the patch you linked is the only one applied, or does this include patches from Atmel too (like the ones in the avr-toolchain repo)? In your compiler flags, I assume I didn't realize about Finally, it seems that I'll run this through my mass-builder script, but I don't have a laptop adapter with me, so can't do that right now :-) |
@cmaglie I just tried enabling LTO with the current toolchain bundled with the Arduino IDE and unfortunately the issue is still present: Without LTO:
With LTO:
@facchinm I tried to test it with the updated toolchain you linked to, but I am getting the following error:
|
@Lauszus it seems that the default x86_64 toolchain from Xcode was chosen for linking... |
@matthijskooijman , you are clearly right about I've tested also with Finally, the script is loosely based on avr-toolchain repo but its main target is to enable canadian cross compiling for all the platform with the same flags on a single machine. No Atmel patch applied at the moment (except one for the GCC linker bug) Eagerly waiting for the results of your tests! |
@harryboo |
Thanx with zip as extension the link is working. But i cannot get this toolchain to work. Do you know how to get the toolchain to work? Thanx |
The first error shows that the IDE didn't recognize the installed core, probably because overwriting the folder content you missed
(even if we are using newer version, the builtin core must be related to the published cores). |
FYI the build params on arch (from the official repos):
|
This is fixed in 1.6.10. |
I am trying to use the upstream avr-gcc from archlinux with arduino now. However I now have this problem. It also seem to occur with older versios of gcc, but Those are quite incompatible with the latest arch now, so its hard to debug.
I've searched this online, but I could not find much information about this. Any ideas? |
Obviously it is too old and lacks the feature/fix. :-) I doubt much can be done about it, unless you track down those functions On Tue, Sep 20, 2016 at 12:25 PM, Nico [email protected] wrote:
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
It is too old? I am using avr-gcc 6.2!? The problem is caused by the deconstructor. If I disable LTO I get the same long error as above. LTO just gives a segfault then, but this is not the cause. The cause is that the deconstructor does not work for some reason. |
In that case, it could be any of the following in all 8 combinations:
On Tue, Sep 20, 2016 at 12:45 PM, Nico [email protected] wrote:
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
The avr-gcc 5.1 from above works fine. The minimum avr-gcc that I can get working on archlinux is 5.2. 5.1 was never compiled for archlinux. So the options are:
I will try to find out more about this and edit my findings. I currently try to recompile 5.3 with the settings that worked before: |
@NicoHood, those symbols look like symbols that libstdc++ or something like that normally supplies, but AVR's libc is a bit lacking in some areas. OTOH, DSO apparently means Dynamic Shared Object, which I don't think should apply here, so perhaps there is some other issue with the compilation options or so? |
I've got problems recompiling avr-gcc 5.3 with the script above on arch. But I found a backup from my old ubuntu installation. And with this setup, avr-gcc 5.3 works fine! This means archlinux configures avr-gcc somehow wrong. avr-gcc 5.3 built with the script at this commit on elementary os freya (ubuntu 14.04) but possibly with a newer gcc (4.9.x or 5.x) -> working (tested without lto)
avr-gcc 5.3.0-2 on archlinux (downgraded) -> does not work (tested with and without lto, error as described above)
|
Looks like one of the suggestions was right that I made. :-) On Tue, Sep 20, 2016 at 1:42 PM, Nico [email protected] wrote:
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
Bug already filed here: I am currently trying to recompile with different settings, but recompiling avr-gcc takes even longer than recompiling a kernel (at least inside the vm). |
I could track down this issue a bit further: The Issue
could be fixed with The LTO bug could be disabled with removing So there seem to be another LTO related bug (for c++ files). Since @facchinm also had this bug with 6.x I am not sure if this is an avr-gcc 6.x bug or just how we configure avr-gcc. Building older avr-gccs might be tricky on arch. The LTO bug does not appear with all sketches. CPP In general does work. For example |
From your arch bug report, I see that the atexit problem is fixed with newer avr-libc versions (which makes sense, since
That sounds like a compiler bug in the optimizer to me. If you can reduce that to a self-contained c++ file, it should be reported to gcc. |
This makes firmware size small but need to be tested more. https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options arduino/Arduino#660 https://github.com/arduino/ArduinoCore-avr/blob/master/platform.txt * No `-fno-fat-lto-objects` is needed, it is the default. https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-ffat-lto-objects * No `-fuse-linker-plugin` is needed, it is the default. https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fuse-linker-plugin
This is Issue 660 moved from a Google Code project.
Added by 2011-09-27T22:38:57.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
Original description
avr-gcc 4.5 has support for LTO. Enabling it would probably allow sizable object size reductions, especially with -Os when linking libraries spanning multiple compilation units.
The text was updated successfully, but these errors were encountered: