Mistake on this page?
Report an issue in GitHub or email us

Link Time Optimization

Link Time Optimization (LTO) is a program memory usage optimization mechanism that the compiler performs at link time. At compile time, the compiler creates a special intermediate representation of all translation units. It then optimizes them as a single unit at link time, which uses less memory than non-LTO builds.

Using LTO in Mbed OS

The Mbed OS build system implements LTO as an optional profile extension in tools\profiles\extensions\lto.json. Enabling LTO amends the build profile with LTO flags.

Note: LTO performs heavy memory optimizations that break debugging, so we recommend using it only with the release profile, not debugging and develop.

To enable LTO, add the --profile option with the LTO file path tools\profiles\extensions\lto.json to the build command.

Note: For profile extensions you have to put the full path relative to the project's root folder.

To enable LTO with the release profile:

mbed compile -t TOOLCHAIN -m TARGET --profile release --profile mbed-os/tools/profiles/extensions/lto.json

Example LTO profile memory savings for mbed-os-example-blinky:

Build type Total static RAM memory (data + BSS) Total flash memory (text + data)
GCC_ARM - release - no LTO 12,096B 44,628B
GCC_ARM - release - LTO 11,800B 41,088B
saved memory 296B 3,540B
ARM - release - no LTO 10,365B 35,496B
ARM - release - LTO 10,153B 31,514B
saved memory 212B ‭3,982‬B

LTO profile build results for mbed-cloud-client-example:

Build type Total static RAM memory (data + BSS) Total flash memory (text + data)
GCC_ARM - release - no LTO 59,760B 389,637B
GCC_ARM - release - LTO 59,432B 354,167B
saved memory 328B ‭35,470‬B
ARM - release - no LTO 58,099B 353,849B
ARM - release - LTO 57,150B 322,500B
saved memory 949B ‭31,349‬B


  • LTO slows down the build process.
  • It’s very hard to control memory placement when using LTO.
  • LTO performs heavy memory optimizations that break debugging.
  • In LTO builds, the compiler produces bytecode/bitcode instead of regular object code. It's hard to analyze this output with object code analysis tools.
  • LTO could cause increases to the stack space needed due to cross-object inlining.

Arm Compiler 6

  • No bitcode libraries: armlink only supports bitcode objects on the command line. It does not support bitcode objects coming from libraries. armlink gives an error message if it encounters a file containing bitcode while loading from a library.
  • Partial Linking is not supported with LTO as it only works with ELF objects not bitcode files.
  • Arm recommends that link time optimization is only performed on code and data that does not require precise placement in the scatter file, with general input section selectors such as *(+RO) and .ANY(+RO) used to select sections generated by link time optimization. It is not possible to match bitcode in .llvmbc sections by name in a scatter file.
  • Bitcode objects are not guaranteed to be compatible across compiler versions. This means that you should ensure all your bitcode files are built using the same version of the compiler when linking with LTO.


  • The minimal required version of GCC_ARM is the GNU Arm Embedded Toolchain Version 9-2019-q4-major. Earlier GCC_ARM versions can cause various issues when the -flto flag is used, for example a platform-specific error during the final link stage on Windows hosts with GCC8.
  • You must use the noinline attribute for every function that must be placed into a specific section (specified with a section(".section_name") attribute). In general, when a function is considered for inlining, the section attribute is always ignored. However, with the link time optimizer enabled, the chances for inlining are much higher because the inliner works across multiple translation units. As a result, the output sections' sizes change compared to a non-LTO build. This may lead to section ".section_name" will not fit in region "region_name" type errors.
  • In all GCC versions, LTO removes C functions declared as weak in assembler (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967 https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966). For Mbed OS, the problem emerges when exporting Mbed OS projects to other build systems. You can fix this by changing the order of object files in the linker command: Objects providing the weak symbols and compiled from assembly must be listed before the objects providing the strong symbols.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.