-
Notifications
You must be signed in to change notification settings - Fork 586
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 LTO/remove unused symbols when compiling BIOS/firmware #682
Comments
@DurandA -- There was some discussion about enabling link time option. |
See #401 |
@DurandA - We most certainly want to get LTO enabled again. Maybe you could work with @mateusz-holenko to figure out what is needed to done to do that? |
I am now into the realms of a GCC bug (riscvarchive/riscv-gcc#201) so that might not happen anytime soon. Note that precompiled GCC from SiFive (both version |
I'm going to reopen this issue so that @mateusz-holenko can give us an updated on the status around LTO and how to move forward here. |
I guess that linked tasks/PRs provide all the status - we didn't work on the LTO issue lately. Another problem was that LiteX lacked good testing suite (is it better now?). Changes like globally enabling LTO influence a lot of targets and it was quite hard to make sure that they don't break anything :( Perhaps we should think about extending LiteX CI and add more test cases first? |
@mateusz-holenko Did you ever encounter the internal error of the lto-wrapper described in riscvarchive/riscv-gcc#201? |
@DurandA No, I don't recall that error. Our problem was that the linker couldn't find one of the functions that was a part of the code - it looked like it was wronly optimized-out by the LTO mechanism (event though it was actually used). |
I forgot to add For reference, here is the current issue when compiling the bios with LTO:
It seems that the linker is dropping some libgcc functions when using LTO. |
@DurandA From what I understand, the issue is either;
|
Selectively disabling the LTO for lib runtime and libc (DurandA@f15bcce) seems to solve all issues. Apparently, GCC optimizes out functions that are not in source without caring that it inserted calls to these functions (1) for arithmetic operations on architecture that do not support it natively and (2) during optimization process. See riscvarchive/riscv-gcc#207 and riscv-collab/riscv-gnu-toolchain#758. Before doing any PR and proceeding with extensive testing, further validation is necessary (according to 979f98e):
|
FYI - @mateusz-holenko |
@DurandA -- We may be able to mark specific functions in lib runtime / libc as used (even though not referenced)? |
I was not able to install a proper LM32 toolchain to check for potential issues. I compiled gcc-9.3.0 with litex/litex/soc/cores/cpu/lm32/core.py Lines 35 to 38 in 081d883
If I remove them, I get a bunch of |
I am not sure if this is possible. My current approach would be to split libc into several files (i.e. at least memset.c and libc.c for others). I didn't investigate yet if GCC can generate calls to something else than |
@enjoy-digital Can you please point to the LM32 toolchain you are using? 🙂 |
We (@timvideos / litex-buildenv, @antmicro and @SymbiFlow) use the toolchain from https://github.com/litex-hub/litex-conda-compilers/tree/master |
Some (old, because that's what the search engine found first) GCC documentation implies that the The LLVM design document for LTO impiles it also looks for "externally visible" symbols, but I'm not sure if it respects the same attribute. Hopefully there'd be relatively few such symbols that need marking like that. (The LM32 issues I had I think were more to do with Makefile complications that sort of enabled LTO but sort of didn't, for LM32, which then caused other things not to build due to confusion over compile/link flags; that part seems easier to resolve, even with just a "no LTO" off switch to try when there are compile/link problems.) Ewen |
@ewenmcneill Thanks for mentioning it. Unfortunately, if I remove the |
I created a minimal repo with LTO to experiment with LTO behaviour and to be able to discuss about this with external people. @enjoy-digital Why did you add mulsi3.c to the libcompiler_rt dir in 17f6cb1 and not to the |
@DurandA: thanks for looking at this. Before using |
:-( It sounds like the "compiler replacements for missing instructions" (which that looks like -- signed multiply for integers), are at the biggest risk of LTO not realising they're needed until it's too late. Your approach of creating a minimal example to experiment with that particular bit seems like a good approach. Thanks for tackling it. Good luck! Ewen |
@ewenmcneill We really should be filing bugs against gcc / clang for this failure mode. |
If someone comes up with a minimal reproducible example that shows that the compiler-replacements of mul/div/etc are not surviving LTO optimisation (ideally with glibc), on a particular supported CPU architecture (it seems like RV32I might be the best modern option without MUL/DIV) then I agree it'd be worth reporting upstream. I did wonder if the GNU (GCC/Glibc) versions of MUL/DIV replacements were being marked in some different manner that made them survive LTO, but that doesn't seem to be the case (eg, https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/microblaze/mulsi3.S, https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/epiphany/mulsi3.c to pick random examples searching found). And maybe that's part of the problem.... Ewen PS: For future reference, possible symbol attributes in Clang; it seems that "externally visible" isn't a supported Clang attribute, nor can I see "used". So I'm unclear how one tweaks functions to be retained over LTO in Clang :-( |
Here is a minimal example that will trigger both A few remarks about it:
This example shows the behaviour of GCC pretty clearly: calls to libc or libgcc are not marked to be retained by the LTO. This is an issue when using As to what we can do about it, I have a branch with LTO enabled that sets @mithro @enjoy-digital Are you interested in a PR enabling LTO with the above changes? If yes, please tell me how do you want to split libc and I will make a draft PR. I will need some help to properly test this. I tested these changes on a few platforms that caused problems in previous revisions but not with litex-buildenv. Also I did not try using LTO with LLVM/Clang yet. |
As far as I can remember/find, the ARM instruction set almost always includes at least some MUL (eg, 32x32) (since ARMv2 AFAICT), so it might not be the best choice for an upstream demo. (it looks like even Thumb normally includes a shorter MUL). If we could induce an implicit DIV, and have the same LTO issues, then ARM might work (as DIV is much less commonly implemented in ARM instruction sets than MUL). It looks like MUL is optional in LM32 (Lattice Mico 32), and there seems to be a gcc flag for LM32 to indicate whether multiply instructions can be generated. As far as I can tell LM32 is still upstream in gcc. So maybe LM32 is still a better alternative? I'd still state that it was an issue found with RISC V first though, so they don't dismiss it as "just LM32"; RV32I is probably going to be a common "tiny CPU' target for the next 10 years. (FYI, from memory there's a gcc LM32 cross compiler in the same litex-hub compiler builds as the RISC V one; LM32 was the small soft CPU we were using for the RISC V soft CPU implementations became "production ready".) Well done on all the other discoveries. It makes sense that the functions being inlined mostly hiding this LTO issue from the compiler/linker developers (and especially that they're mostly testing on CPU architectures which don't need MUL/DIV emulated :-) ). Ewen |
Sorry for the lack of updates. I still plan to create a PR once we decided what is the best strategy to solve this issue. |
Has this now been fixed with the introduction of picolibc? I see that |
@gregdavill: Indeed, LTO has been enabled by default when integrating picolibc. We can now close this issue. |
The current GCC build (I did not try Clang) for BIOS/firmware does not strip away unused symbols, resulting in large binaries (especially when adding dependencies).
I tried adding various flags in common.mak according to answers on Stack Overflow but without much success. It either resulted in no effect or the build failed. With
-flto
I was not able to fix aplugin needed to handle lto object
error.The text was updated successfully, but these errors were encountered: