STM32: Arm GNU Toolchain vs Arm Toolchain for Embedded
Introdução
A escolha da cadeia de ferramentas de compilação (toolchain) pode influenciar o tamanho do firmware e seu desempenho em tempo de execução. No ecossistema STM32, duas das opções disponíveis gratuitamente são a Arm Toolchain for Embedded, baseada em LLVM/Clang, e a Arm GNU Toolchain, baseada em GCC. Embora ambas permitam desenvolver software para microcontroladores com arquitetura Arm, os resultados podem variar de acordo com o código-fonte, as opções de otimização, a configuração de compilação e o núcleo de destino.
A Arm GNU Toolchain possui uma longa trajetória de desenvolvimento e uso, o que contribuiu para sua ampla adoção no ecossistema de sistemas embarcados. Por sua vez, a Arm Toolchain for Embedded, lançada em 2025, representa uma alternativa mais recente, baseada em LLVM/Clang. Essa diferença de maturidade torna interessante investigar como as duas soluções se comportam em condições equivalentes.
Este artigo compara os resultados obtidos com essas duas toolchains em três famílias de microcontroladores da STMicroelectronics: STM32C0, STM32C5 e STM32WB. A escolha dessas plataformas foi motivada pela disponibilidade dos kits de desenvolvimento utilizados nos experimentos, e não por uma seleção arbitrária. As famílias contemplam diferentes núcleos de processamento: Cortex-M0+ na STM32C0, Cortex-M33 na STM32C5 e Cortex-M4 na STM32WB.
Foram avaliados o consumo de memória Flash e RAM, bem como os tempos de execução registrados em diferentes benchmarks. O objetivo é observar como os resultados produzidos por GCC e Clang diferem quando aplicados ao mesmo alvo e sob configurações equivalentes.
As conclusões se restringem aos códigos-fonte, às opções de compilação, às versões das toolchains e às plataformas utilizadas neste experimento. A partir dos resultados, busca-se oferecer subsídios para que o leitor compreenda as diferenças observadas e avalie qual toolchain e quais opções de otimização são mais adequadas às necessidades de seu próprio projeto.
Configuração testadas
Foram avaliadas as seguintes plataformas de microcontroladores:
- STM32C031: núcleo Arm Cortex-M0+, com 32 KB de Flash e 12 KB de RAM.
- STM32C542: núcleo Arm Cortex-M33, com 256 KB de Flash e 64 KB de RAM.
- STM32WB5M: núcleo Arm Cortex-M4, com 512 KB de Flash e aproximadamente 192 KB de RAM considerados na configuração de memória utilizada nos testes.
A frequência de operação da CPU foi fixada em 48 MHz em todas as plataformas.
Foram comparadas as seguintes toolchains:
- Arm Toolchain for Embedded, baseada em LLVM/Clang, versão 22.1.0.
- Arm GNU Toolchain, baseada em GCC, versão 15.2.Rel1.
As opções de otimização avaliadas foram -O0, -Os, -Oz e -O2, com e sem -flto, conforme detalhado a seguir:
- O0: desativa a maioria das otimizações, facilitando a depuração, mas geralmente produz código maior e mais lento.
- Os: habilita otimizações que priorizam a redução do tamanho do código gerado.
- Oz: prioriza ainda mais a redução do tamanho do código, podendo sacrificar desempenho para economizar memória.
- O2: habilita um conjunto amplo de otimizações voltadas ao desempenho, sem priorizar o menor tamanho possível.
- flto: habilita otimizações entre diferentes arquivos durante a linkagem, podendo reduzir o tamanho e melhorar o desempenho, sem garantir ambos os ganhos simultaneamente.
As métricas de desempenho são expressas em microssegundos (µs). Os percentuais de utilização de Flash e RAM são calculados em relação às regiões de memória declaradas para cada alvo nos respectivos arquivos de linker. Por esse motivo, os percentuais não devem ser comparados diretamente entre famílias diferentes sem considerar as capacidades e configurações de memória de cada plataforma.
Observação metodológica
Para tornar a comparação entre as toolchains tão justa quanto possível, foram mantidos equivalentes o código-fonte, as condições de execução, as frequências de operação e as opções de compilação que permitiam uma comparação direta. Também foram controladas, sempre que aplicável, as versões e as opções das ferramentas auxiliares.
A seguir, é apresentado um trecho de exemplo do arquivo CMakeLists.txt utilizado na configuração dos testes.
Figura 1 – Exemplo do trecho do CmakeList utilizado com as flags de otimização
Tipo de testes avaliados
A avaliação contempla métricas de tamanho e benchmarks de execução. O tamanho é apresentado como percentual de uso de Flash e RAM. Os tempos, expressos em microssegundos (µs), correspondem ao tempo médio de uma chamada ao respectivo cálculo durante a janela de medição.
- fixed_q15: cálculo escalar de produto escalar com valores de ponto fixo Q15.
- integer: sequência de operações aritméticas com inteiros.
- float: cálculo de produto escalar utilizando números de ponto flutuante.
- memory: preenchimento de um vetor em memória e cópia dos dados para outro vetor.
- division: operações de divisão inteira e cálculo do resto.
- branch: execução de condicionais com decisões dependentes dos dados.
Resultados obtidos
Tabela 1 – Resultados do benchmark no STM32C0
| Flags | Métrica | GCC | Clang | Diferença | Menor valor |
|---|---|---|---|---|---|
| -O0 | Flash (%) | 59.27 | 38.04 | -35.82% | Clang |
| -O0 | RAM (%) | 18.62 | 18.36 | -1.40% | Clang |
| -O0 | fixed_q15 (µs) | 3619 | 3145 | -13.10% | Clang |
| -O0 | integer (µs) | 2374 | 1789 | -24.64% | Clang |
| -O0 | float (µs) | 13147 | 11791 | -10.31% | Clang |
| -O0 | memory (µs) | 1849 | 1577 | -14.71% | Clang |
| -O0 | division (µs) | 3325 | 2899 | -12.81% | Clang |
| -O0 | branch (µs) | 1671 | 1393 | -16.64% | Clang |
| -O0 -flto | Flash (%) | 59.28 | 37.15 | -37.33% | Clang |
| -O0 -flto | RAM (%) | 18.62 | 18.29 | -1.77% | Clang |
| -O0 -flto | fixed_q15 (µs) | 3619 | 3196 | -11.69% | Clang |
| -O0 -flto | integer (µs) | 2374 | 1768 | -25.53% | Clang |
| -O0 -flto | float (µs) | 13118 | 11628 | -11.36% | Clang |
| -O0 -flto | memory (µs) | 1849 | 1566 | -15.31% | Clang |
| -O0 -flto | division (µs) | 3328 | 2894 | -13.04% | Clang |
| -O0 -flto | branch (µs) | 1671 | 1371 | -17.95% | Clang |
| -Os | Flash (%) | 46.41 | 29.04 | -37.43% | Clang |
| -Os | RAM (%) | 17.58 | 17.32 | -1.48% | Clang |
| -Os | fixed_q15 (µs) | 1754 | 2065 | +17.73% | GCC |
| -Os | integer (µs) | 1570 | 1253 | -20.19% | Clang |
| -Os | float (µs) | 11154 | 10581 | -5.14% | Clang |
| -Os | memory (µs) | 987 | 653 | -33.84% | Clang |
| -Os | division (µs) | 1668 | 1476 | -11.51% | Clang |
| -Os | branch (µs) | 1202 | 756 | -37.10% | Clang |
| -Os -flto | Flash (%) | 42.4 | 25 | -41.04% | Clang |
| -Os -flto | RAM (%) | 17.51 | 17.19 | -1.83% | Clang |
| -Os -flto | fixed_q15 (µs) | 1619 | 1916 | +18.34% | GCC |
| -Os -flto | integer (µs) | 1468 | 1289 | -12.19% | Clang |
| -Os -flto | float (µs) | 11007 | 10573 | -3.94% | Clang |
| -Os -flto | memory (µs) | 926 | 679 | -26.67% | Clang |
| -Os -flto | division (µs) | 1640 | 1513 | -7.74% | Clang |
| -Os -flto | branch (µs) | 1182 | 838 | -29.10% | Clang |
| -Oz | Flash (%) | 46.41 | 27.1 | -41.61% | Clang |
| -Oz | RAM (%) | 17.58 | 17.32 | -1.48% | Clang |
| -Oz | fixed_q15 (µs) | 1754 | 2128 | +21.32% | GCC |
| -Oz | integer (µs) | 1570 | 1195 | -23.89% | Clang |
| -Oz | float (µs) | 11154 | 10757 | -3.56% | Clang |
| -Oz | memory (µs) | 987 | 731 | -25.94% | Clang |
| -Oz | division (µs) | 1669 | 1499 | -10.19% | Clang |
| -Oz | branch (µs) | 1202 | 769 | -36.02% | Clang |
| -Oz -flto | Flash (%) | 42.4 | 22.52 | -46.89% | Clang |
| -Oz -flto | RAM (%) | 17.51 | 17.19 | -1.83% | Clang |
| -Oz -flto | fixed_q15 (µs) | 1619 | 2189 | +35.21% | GCC |
| -Oz -flto | integer (µs) | 1468 | 1183 | -19.41% | Clang |
| -Oz -flto | float (µs) | 11007 | 10823 | -1.67% | Clang |
| -Oz -flto | memory (µs) | 926 | 731 | -21.06% | Clang |
| -Oz -flto | division (µs) | 1640 | 1519 | -7.38% | Clang |
| -Oz -flto | branch (µs) | 1182 | 767 | -35.11% | Clang |
| -O2 | Flash (%) | 50.43 | 43.81 | -13.13% | Clang |
| -O2 | RAM (%) | 17.58 | 17.32 | -1.48% | Clang |
| -O2 | fixed_q15 (µs) | 1441 | 1719 | +19.29% | GCC |
| -O2 | integer (µs) | 1420 | 1186 | -16.48% | Clang |
| -O2 | float (µs) | 11035 | 10396 | -5.79% | Clang |
| -O2 | memory (µs) | 746 | 520 | -30.29% | Clang |
| -O2 | division (µs) | 1620 | 1470 | -9.26% | Clang |
| -O2 | branch (µs) | 977 | 743 | -23.95% | Clang |
| -O2 -flto | Flash (%) | 44.47 | 44.65 | +0.40% | GCC |
| -O2 -flto | RAM (%) | 17.58 | 17.19 | -2.22% | Clang |
| -O2 -flto | fixed_q15 (µs) | 1700 | 1725 | +1.47% | GCC |
| -O2 -flto | integer (µs) | 1477 | 1203 | -18.55% | Clang |
| -O2 -flto | float (µs) | 11286 | 10312 | -8.63% | Clang |
| -O2 -flto | memory (µs) | 772 | 514 | -33.42% | Clang |
| -O2 -flto | division (µs) | 1688 | 1471 | -12.86% | Clang |
| -O2 -flto | branch (µs) | 1036 | 826 | -20.27% | Clang |
Tabela 2 – Resultados do benchmark no STM32C5
| Flags | Métrica | GCC | Clang | Diferença | Menor valor |
|---|---|---|---|---|---|
| -O0 | Flash (%) | 7.34 | 5.8 | -20.98% | Clang |
| -O0 | RAM (%) | 1.81 | 1.77 | -2.21% | Clang |
| -O0 | fixed_q15 (µs) | 5954 | 4125 | -30.72% | Clang |
| -O0 | integer (µs) | 2477 | 1402 | -43.40% | Clang |
| -O0 | float (µs) | 15471 | 5407 | -65.05% | Clang |
| -O0 | memory (µs) | 2788 | 1820 | -34.72% | Clang |
| -O0 | division (µs) | 1783 | 1119 | -37.24% | Clang |
| -O0 | branch (µs) | 2184 | 1573 | -27.98% | Clang |
| -O0 -flto | Flash (%) | 7.36 | 5.35 | -27.31% | Clang |
| -O0 -flto | RAM (%) | 1.81 | 1.77 | -2.21% | Clang |
| -O0 -flto | fixed_q15 (µs) | 5954 | 4129 | -30.65% | Clang |
| -O0 -flto | integer (µs) | 2477 | 1567 | -36.74% | Clang |
| -O0 -flto | float (µs) | 15471 | 5352 | -65.41% | Clang |
| -O0 -flto | memory (µs) | 2787 | 2248 | -19.34% | Clang |
| -O0 -flto | division (µs) | 1783 | 1376 | -22.83% | Clang |
| -O0 -flto | branch (µs) | 2184 | 1839 | -15.80% | Clang |
| -Os | Flash (%) | 4.22 | 3.97 | -5.92% | Clang |
| -Os | RAM (%) | 1.61 | 1.57 | -2.48% | Clang |
| -Os | fixed_q15 (µs) | 1498 | 1776 | +18.56% | GCC |
| -Os | integer (µs) | 710 | 554 | -21.97% | Clang |
| -Os | float (µs) | 11672 | 2694 | -76.92% | Clang |
| -Os | memory (µs) | 780 | 618 | -20.77% | Clang |
| -Os | division (µs) | 513 | 457 | -10.92% | Clang |
| -Os | branch (µs) | 1029 | 723 | -29.74% | Clang |
| -Os -flto | Flash (%) | 3.48 | 3.16 | -9.20% | Clang |
| -Os -flto | RAM (%) | 1.61 | 1.56 | -3.11% | Clang |
| -Os -flto | fixed_q15 (µs) | 1477 | 1527 | +3.39% | GCC |
| -Os -flto | integer (µs) | 933 | 515 | -44.80% | Clang |
| -Os -flto | float (µs) | 11719 | 2481 | -78.83% | Clang |
| -Os -flto | memory (µs) | 1034 | 620 | -40.04% | Clang |
| -Os -flto | division (µs) | 592 | 494 | -16.55% | Clang |
| -Os -flto | branch (µs) | 964 | 706 | -26.76% | Clang |
| -Oz | Flash (%) | 4.22 | 3.44 | -18.48% | Clang |
| -Oz | RAM (%) | 1.61 | 1.57 | -2.48% | Clang |
| -Oz | fixed_q15 (µs) | 1498 | 1888 | +26.03% | GCC |
| -Oz | integer (µs) | 710 | 524 | -26.20% | Clang |
| -Oz | float (µs) | 11672 | 2809 | -75.93% | Clang |
| -Oz | memory (µs) | 780 | 708 | -9.23% | Clang |
| -Oz | division (µs) | 513 | 417 | -18.71% | Clang |
| -Oz | branch (µs) | 1029 | 764 | -25.75% | Clang |
| -Oz -flto | Flash (%) | 3.48 | 2.69 | -22.70% | Clang |
| -Oz -flto | RAM (%) | 1.61 | 1.56 | -3.11% | Clang |
| -Oz -flto | fixed_q15 (µs) | 1477 | 2026 | +37.17% | GCC |
| -Oz -flto | integer (µs) | 933 | 929 | -0.43% | Clang |
| -Oz -flto | float (µs) | 11719 | 2927 | -75.02% | Clang |
| -Oz -flto | memory (µs) | 1034 | 955 | -7.64% | Clang |
| -Oz -flto | division (µs) | 592 | 603 | +1.86% | GCC |
| -Oz -flto | branch (µs) | 964 | 864 | -10.37% | Clang |
| -O2 | Flash (%) | 4.59 | 6.57 | +43.14% | GCC |
| -O2 | RAM (%) | 1.61 | 1.57 | -2.48% | Clang |
| -O2 | fixed_q15 (µs) | 1591 | 1925 | +20.99% | GCC |
| -O2 | integer (µs) | 694 | 398 | -42.65% | Clang |
| -O2 | float (µs) | 10794 | 2884 | -73.28% | Clang |
| -O2 | memory (µs) | 825 | 316 | -61.70% | Clang |
| -O2 | division (µs) | 533 | 316 | -40.71% | Clang |
| -O2 | branch (µs) | 779 | 535 | -31.32% | Clang |
| -O2 -flto | Flash (%) | 3.84 | 5.97 | +55.47% | GCC |
| -O2 -flto | RAM (%) | 1.62 | 1.56 | -3.70% | Clang |
| -O2 -flto | fixed_q15 (µs) | 3072 | 1842 | -40.04% | Clang |
| -O2 -flto | integer (µs) | 1019 | 393 | -61.43% | Clang |
| -O2 -flto | float (µs) | 12469 | 2815 | -77.42% | Clang |
| -O2 -flto | memory (µs) | 1386 | 318 | -77.06% | Clang |
| -O2 -flto | division (µs) | 522 | 332 | -36.40% | Clang |
| -O2 -flto | branch (µs) | 1095 | 537 | -50.96% | Clang |
Tabela 3 – Resultados do benchmark no STM32WB
| Flags | Métrica | GCC | Clang | Diferença | Menor valor |
|---|---|---|---|---|---|
| -O0 | Flash (%) | 3.87 | 3.13 | -19.12% | Clang |
| -O0 | RAM (%) | 1.16 | 1.15 | -0.86% | Clang |
| -O0 | fixed_q15 (µs) | 2494 | 2167 | -13.11% | Clang |
| -O0 | integer (µs) | 1201 | 788 | -34.39% | Clang |
| -O0 | float (µs) | 5979 | 2676 | -55.24% | Clang |
| -O0 | memory (µs) | 1177 | 1012 | -14.02% | Clang |
| -O0 | division (µs) | 951 | 693 | -27.13% | Clang |
| -O0 | branch (µs) | 1032 | 778 | -24.61% | Clang |
| -O0 -flto | Flash (%) | 3.88 | 3.06 | -21.13% | Clang |
| -O0 -flto | RAM (%) | 1.16 | 1.15 | -0.86% | Clang |
| -O0 -flto | fixed_q15 (µs) | 2494 | 2172 | -12.91% | Clang |
| -O0 -flto | integer (µs) | 1201 | 788 | -34.39% | Clang |
| -O0 -flto | float (µs) | 5990 | 2655 | -55.68% | Clang |
| -O0 -flto | memory (µs) | 1177 | 1012 | -14.02% | Clang |
| -O0 -flto | division (µs) | 951 | 693 | -27.13% | Clang |
| -O0 -flto | branch (µs) | 1032 | 784 | -24.03% | Clang |
| -Os | Flash (%) | 2.34 | 2.25 | -3.85% | Clang |
| -Os | RAM (%) | 1.1 | 1.09 | -0.91% | Clang |
| -Os | fixed_q15 (µs) | 604 | 669 | +10.76% | GCC |
| -Os | integer (µs) | 247 | 183 | -25.91% | Clang |
| -Os | float (µs) | 4392 | 1141 | -74.02% | Clang |
| -Os | memory (µs) | 282 | 249 | -11.70% | Clang |
| -Os | division (µs) | 216 | 194 | -10.19% | Clang |
| -Os | branch (µs) | 317 | 234 | -26.18% | Clang |
| -Os -flto | Flash (%) | 1.95 | 1.87 | -4.10% | Clang |
| -Os -flto | RAM (%) | 1.09 | 1.07 | -1.83% | Clang |
| -Os -flto | fixed_q15 (µs) | 603 | 668 | +10.78% | GCC |
| -Os -flto | integer (µs) | 279 | 183 | -34.41% | Clang |
| -Os -flto | float (µs) | 4492 | 1116 | -75.16% | Clang |
| -Os -flto | memory (µs) | 313 | 249 | -20.45% | Clang |
| -Os -flto | division (µs) | 231 | 194 | -16.02% | Clang |
| -Os -flto | branch (µs) | 325 | 243 | -25.23% | Clang |
| -Oz | Flash (%) | 2.34 | 2.03 | -13.25% | Clang |
| -Oz | RAM (%) | 1.1 | 1.09 | -0.91% | Clang |
| -Oz | fixed_q15 (µs) | 604 | 788 | +30.46% | GCC |
| -Oz | integer (µs) | 247 | 210 | -14.98% | Clang |
| -Oz | float (µs) | 4392 | 1195 | -72.79% | Clang |
| -Oz | memory (µs) | 282 | 279 | -1.06% | Clang |
| -Oz | division (µs) | 216 | 205 | -5.09% | Clang |
| -Oz | branch (µs) | 317 | 271 | -14.51% | Clang |
| -Oz -flto | Flash (%) | 1.95 | 1.63 | -16.41% | Clang |
| -Oz -flto | RAM (%) | 1.09 | 1.07 | -1.83% | Clang |
| -Oz -flto | fixed_q15 (µs) | 603 | 789 | +30.85% | GCC |
| -Oz -flto | integer (µs) | 279 | 263 | -5.73% | Clang |
| -Oz -flto | float (µs) | 4492 | 1216 | -72.93% | Clang |
| -Oz -flto | memory (µs) | 313 | 310 | -0.96% | Clang |
| -Oz -flto | division (µs) | 231 | 221 | -4.33% | Clang |
| -Oz -flto | branch (µs) | 325 | 282 | -13.23% | Clang |
| -O2 | Flash (%) | 2.6 | 3.33 | +28.08% | GCC |
| -O2 | RAM (%) | 1.1 | 1.09 | -0.91% | Clang |
| -O2 | fixed_q15 (µs) | 545 | 943 | +73.03% | GCC |
| -O2 | integer (µs) | 242 | 153 | -36.78% | Clang |
| -O2 | float (µs) | 4189 | 1416 | -66.20% | Clang |
| -O2 | memory (µs) | 264 | 146 | -44.70% | Clang |
| -O2 | division (µs) | 215 | 170 | -20.93% | Clang |
| -O2 | branch (µs) | 284 | 190 | -33.10% | Clang |
| -O2 -flto | Flash (%) | 2.09 | 3.3 | +57.89% | GCC |
| -O2 -flto | RAM (%) | 1.1 | 1.07 | -2.73% | Clang |
| -O2 -flto | fixed_q15 (µs) | 818 | 896 | +9.54% | GCC |
| -O2 -flto | integer (µs) | 300 | 155 | -48.33% | Clang |
| -O2 -flto | float (µs) | 4476 | 1411 | -68.48% | Clang |
| -O2 -flto | memory (µs) | 329 | 144 | -56.23% | Clang |
| -O2 -flto | division (µs) | 210 | 169 | -19.52% | Clang |
| -O2 -flto | branch (µs) | 305 | 189 | -38.03% | Clang |
Como interpretar os resultados: cada linha compara GCC e Clang no mesmo microcontrolador e com as mesmas opções de compilação. Em todas as métricas, valores menores indicam menor uso de memória ou menor tempo de execução. A diferença percentual é calculada por (Clang / GCC − 1) × 100, usando o GCC como referência: valores negativos favorecem o Clang, positivos favorecem o GCC e zero indica empate. Os tempos são expressos em microssegundos (µs), e o uso de Flash e RAM, em percentual das regiões de memória definidas para cada alvo.
Conclusão
Os resultados mostram que a escolha da toolchain deve considerar tanto o microcontrolador quanto o perfil da aplicação. Neste experimento, o Clang destacou-se pelo menor uso de RAM em todas as comparações e pelos menores tempos na maioria dos benchmarks. O GCC, por sua vez, manteve vantagens importantes no processamento de ponto fixo e em algumas configurações de uso de Flash.
No STM32C0, o Clang apresentou o melhor equilíbrio entre tamanho e desempenho, com redução média de 31,6% no uso de Flash e menor tempo em todos os testes de integer, float, memory, division e branch. A principal exceção foi fixed_q15, em que o GCC venceu nas configurações otimizadas. Para esta plataforma, os resultados favorecem o Clang quando a prioridade é economizar Flash sem comprometer o desempenho das demais cargas avaliadas.
No STM32C5, a vantagem do Clang foi mais expressiva no desempenho, especialmente em float, cujo tempo foi, em média, 73,5% menor. Também houve ganhos relevantes em operações inteiras e memória. Em contrapartida, o GCC produziu binários menores nas configurações com -O2 e foi mais rápido na maioria das comparações de fixed_q15. Assim, a escolha depende do compromisso desejado: os resultados favorecem o Clang para as cargas gerais de execução, mas mantêm o GCC como alternativa relevante para ponto fixo ou menor Flash com -O2.
No STM32WB, o Clang também se destacou na maioria dos benchmarks, com redução média de 67,6% no tempo de float. O GCC, entretanto, foi mais rápido em fixed_q15 nas configurações otimizadas e utilizou menos Flash com -O2. Embora o Clang tenha produzido binários menores na maioria das combinações, essas duas exceções foram suficientes para tornar seu uso médio de Flash ligeiramente superior. Isso reforça a importância de avaliar a configuração específica da aplicação, em vez de escolher apenas pelo resultado agregado.
A opção -O0 não se mostrou vantajosa para versões finais cujo objetivo seja reduzir o tamanho do firmware ou melhorar o desempenho. Em relação à configuração de menor Flash de cada compilador e plataforma, sua ocupação foi aproximadamente 40% a 116% maior, além de apresentar tempos geralmente superiores aos das configurações otimizadas. Seu uso pode ser adequado durante a depuração, mas os resultados favorecem a adoção de otimizações para builds de produção com restrições de memória ou velocidade.
Para minimizar Flash, Clang -Oz -flto foi a melhor combinação nas três plataformas. Já o uso de LTO não assegurou ganhos de velocidade e, em alguns casos, esteve associado a regressões. Reduzir o binário e acelerar a execução são, portanto, objetivos que precisam ser avaliados separadamente.
Em síntese, o Clang apresentou os resultados gerais mais favoráveis neste conjunto de testes, sem eliminar as vantagens específicas do GCC. Mais do que apontar um vencedor, a comparação mostra que a combinação entre toolchain e opções de otimização deve acompanhar as prioridades de cada projeto, seja para reduzir o uso de memória, acelerar a execução ou equilibrar esses dois objetivos.
Referências
[1] ALHERAKI, Ayman. C++ Low-Level Optimization: Performance Secrets in a Concise Guide. [S. l.]: Simplify C++, nov. 2025. Disponível em: https://simplifycpp.org/books/minibooklet/mini_booklet_CPP_Low_Level_Optimization.pdf.
[2] ARM. Arm Support: documentação técnica — KA006435. [S. l.], [s. d.]. Disponível em: https://support.arm.com/documentation/ka006435/latest.
[3] STMICROELECTRONICS. STM32Cube further facilitates code development with Clang/LLVM support. STMicroelectronics Community, 8 jul. 2025. Disponível em: https://community.st.com/stm32-software-tools-165/stm32cube-further-facilitates-code-development-with-clang-llvm-support-153936.
[4] ARM. GNU Compiler: Arm GNU Toolchain installation guides. Arm Learning Paths, [s. d.]. Disponível em: https://learn.arm.com/install-guides/gcc/.
[5] STMICROELECTRONICS. STM32CubeC5 MCU Software Package. GitHub, [s. d.]. Disponível em: https://github.com/STMicroelectronics/STM32CubeC5.
[6] STMICROELECTRONICS. STM32CubeWB MCU Firmware Package. GitHub, [s. d.]. Disponível em: https://github.com/STMicroelectronics/STM32CubeWB.
[7] STMICROELECTRONICS. STM32CubeC0 MCU Firmware Package. GitHub, [s. d.]. Disponível em: https://github.com/STMicroelectronics/STM32CubeC0.
Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.


