The GNU GCC compiler and associated tools are of very high quality nowadays, in particular for the ARM Cortex cores. If you are a Cortex-M developer using popular device families like STM32, Kinetis, EFM32 or LPC, you are in a good position to use the GNU tools as your primary toolchain, as the GCC compiler and its various commercial distributions have excellent target support.
But what about code size optimizations? The GNU compiler for ARM produces highly optimized machine code these days. Still many developers report poor code size results with the GNU compiler. Why is that? In almost all cases, the reason is ARM developers new to the GNU GCC compiler do not know how to configure it correctly. Our free checklist 7 steps to reduce GNU GCC code-size show you how to do it right.
One of the rare disadvantages of the GCC compiler is it do not have the best (for code-size) compiler and linker options enabled by default. Thus, inexperienced GCC developers may use the compiler and linker tools with their default options, or otherwise poorly optimized settings. This is bound to generate poor code-size results. Luckily, it is easy to correct the situation by using the right compiler and linker options.
A project with the best GCC compiler and LD linker options can generate 40% less code (or even better), compared to the default settings (your mileage will vary dependent on your specific project). So, what is the trick here?
First of all, enable the right compiler options to make the GNU compiler optimize for size. This is done differently for the highest optimization level for production code (release mode), compared to code that should still be debuggable (debug mode).
Secondly, you should enable the linker to remove unused code (functions) and data (variables). This is not done with the default GNU compiler and linker settings, and is of course a must if you want to achieve optimal code size.
If you use C++, you should disable Runtime Type Information (RTTI) and exception handling (C++ exceptions, not hardware interrupts), as these two language features use a lot of space. RTTI and exception handling is rarely used in small to mid-size embedded systems, such as projects using Cortex-M based devices like STM32, Kinetis, LPC or EFM32
The C language runtime library is also a common source of misunderstandings when it comes to code size. The GNU compiler produces highly optimized and compact machine code, but the default runtime library (Newlib) is not as compact as some commercial alternatives. That may result in code size bloat, if care is not taken and a better runtime library is used. This is particularly true for small projects, where the runtime library is relatively large compared to the application code.
A relatively new feature of the GNU gcc compiler and ld linker is LTO (Link Time Optimization), also known as “whole program analysis” in some parts of the compiler industry. This term is however already used for something else in the GNU gcc compiler and so LTO should be used with the GNU tools.
With LTO, the GNU compiler and linker combination can optimize the code size also across the C files (the compiler can normally only optimize the code within a C file). This enable the GNU tools to optimize the whole program globally (instead of just inside each file locally) using code resequencing techniques performed by the linker.
All-in-all, the GNU gcc compiler is a very high quality compiler for ARM Cortex-M targets, producing highly optimized and very compact code. However, with the default command line options and runtime library selections, matters can quickly deteriorate and poor code size numbers show up. On the other hand, with the right settings, the GNU gcc compiler is an excellent choice for embedded developers using popular Cortex-M devices like STM32, Kinetis, LPC, etc.
For a clear and concise guide on reducing code size using the GNU tools, download our free GCC code-size optimization checklist here: