Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Start with -O2, an explicit minimum CPU target, and measurements on the real device. Move to -Os/-Oz, -O3, LTO, PGO, or relaxed floating-point rules only when a controlled test proves they improve the resource that actually limits your product. There is no universal “best” GCC or Clang flag set: an application, kernel, shared library, and complete image have different constraints.

Define the bottleneck before changing flags

“Optimization” may mean lower latency, higher throughput, smaller resident memory, less flash, faster boot, lower energy, or tighter worst-case timing. Record the metric and its acceptance limit first.

  • CPU: wall-clock latency, throughput, cycles, instructions, branch and cache misses, CPU utilization, system calls and context switches.
  • Memory: peak and resident memory, heap-allocation rate, stack use, page faults, DMA/CMA pressure, and shared versus private pages.
  • Storage: ELF size, stripped size, compressed and uncompressed filesystem size, kernel/modules, symbols and relocations.
  • Energy and real time: energy per operation, thermal throttling, jitter, interrupt response and worst-case latency—not only averages.

A smaller image can require more decompression CPU; a faster build can consume more energy; and a throughput gain can worsen instruction-cache behavior or tail latency.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Freeze a reproducible baseline

Capture the toolchain and target before experimenting:

#1 Best Overall
For Beaglebone Black Embedded Development Board AM3358 Main Board Linux Single Board ARM Computer New For BeagleBone Black Embedded AM3358 Development Board For Linux Single Board ARM Computer
  • Featuring a 1GHz processor and SGX530 Graphics Engine.
  • IntegratedNEON SIMD coprocessor;
  • On board eMMC memory
  • This development board offer high-speed USBconnectivity, an HDMIcompatible interface, and expandable memory option.
  • Advanced for BeagleBone Black AM335x CortexA8 Development Board
gcc --version
clang --version
ld --version
ld.lld --version
gcc -dumpmachine
gcc -Q --help=target
gcc -Q -O2 --help=optimizers
clang --target=aarch64-linux-gnu -### -c test.c

Also record the target triple, CPU revision and extensions, ABI and floating-point ABI, glibc or musl version, sysroot, binutils/LLVM utilities, linker, kernel configuration, build-system version and release configuration. Clang’s -### output shows the commands its driver would invoke, helping reveal the assembler, linker, runtime and implicit target options (Clang command guide).

Keep the exact commands visible with make V=1, ninja -v, or:

cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo 
  -DCMAKE_C_FLAGS="-O2 -g" -DCMAKE_CXX_FLAGS="-O2 -g"
cmake --build build --verbose

Choose the CPU baseline deliberately

-march selects instructions the binary may use; -mtune primarily tunes scheduling and choices while retaining the selected ISA; -mcpu commonly combines both (the exact behavior is target-specific). GCC documents these choices for ARM, AArch64 and RISC-V.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
# AArch64 portable baseline plus tuning
aarch64-linux-gnu-gcc -O2 -march=armv8-a -mtune=cortex-a53 ...

# Product tied to one known CPU
aarch64-linux-gnu-gcc -O2 -mcpu=cortex-a72 ...

# 32-bit ARM: verify ABI and FPU for the board
arm-linux-gnueabihf-gcc -O2 -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard ...

# RISC-V: treat ISA and ABI as a pair
gcc -O2 -march=rv64gc -mabi=lp64d ...

Do not leak -march=native into a cross build. It describes the build host, not necessarily the device, and can produce illegal-instruction crashes; GCC explicitly documents host-feature selection for AArch64. For multiple boards, define the oldest supported ISA and ship separately named hardware-specific images when justified. Check NEON/SVE or RISC-V vector availability, endianness, PIE/PIC, atomics, C++ ABI and hard- versus soft-float compatibility.

Optimization levels: what to test

GCC’s optimization documentation describes trade-offs among speed, size, compile time and debuggability; an optimization level never guarantees a speedup. Clang offers familiar levels, but equal-looking options do not imply equal passes or machine code (Clang guide).

Level Use Cautions
-O0 Initial debugging and tiny diagnostics Timing, races and generated code differ greatly from release builds.
-Og Debuggable development that remains somewhat representative Still not a production performance result.
-O2 Default production baseline Measure against your workload.
-O3 Selected hot components May increase code size, register pressure, I-cache misses and build time.
-Os/-Oz Measured size constraint; Clang’s -Oz is more size-focused Less inlining can reduce speed, though cache effects can occasionally help.
-Ofast Specialized numerical code Can relax floating-point and language assumptions; never a blanket release preset.

Useful starting configurations are -O2 -g for a symbol-bearing build and -O2 for deployment. Keep symbols externally and strip the artifact only after confirming unwind and crash-reporting needs:

aarch64-linux-gnu-strip --strip-unneeded app

Keep strict floating-point semantics globally. Isolate and review -ffast-math, -funsafe-math-optimizations or -fno-math-errno only after testing NaN, infinity, signed zero, rounding, exceptions and convergence boundaries.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reduce image size beyond an optimization level

-fdata-sections -ffunction-sections
-Wl,--gc-sections

Section garbage collection, feature removal at configuration time, carefully chosen shared libraries, external debug symbols and linker-map inspection often matter more than switching from -O2 to -Os. Inspect with:

Rank #3
Waveshare Luckfox Lyra RK3506G2 Linux Micro Development Board, Integrates Tripe-core ARM Cortex-A7 and ARM Cortex-M0 Processors, with Header
  • There are several options for this item, this option is with header. Please click the image 2 to check the package content.
  • Luckfox Lyra is a cost-effective Linux micro development board based on the Rockchip RK3506G2 to provide a simple and efficient development platform. Onboard multiple high-speed interfaces including MIPI DSl, RMll, USB, etc. to meet various application scenarios.
  • The low-speed interfaces utilize Rockchip Matrix l0 design which supports multiplexing 98 function siqnals on GPlO pins, and can freely combine PWM, UART, 12C, SPl, and l2S for quick development and debugging.
  • Tripe-core ARM Cortex-A7 32-bit core, with integrated VFP to support single- and double-precision floating-point operations. Built-in ARM Cortex-M0 MCU design, supports SMP and AMP configuration. Built-in 128MB DDRL3 for multi-core applications
  • The low-speed interfaces adopt Rockchip Matrix IO design, which allows rich function signals to share the limited chip pins, making peripheral circuit adaptation more flexible. Built-in audio and video codec, supports multiple audio inputs and outputs, providing high-quality audio playback and recording functions
size app
readelf -S app
readelf -Ws app
nm -S --size-sort app | tail

Garbage collection can remove indirectly referenced registration tables, constructors or plugin entry points. Add appropriate linker-script KEEP() rules and startup tests rather than assuming every referenced symbol is visible to the linker.

LTO: powerful, but a build-system feature

GCC:

gcc -O2 -flto -c a.c
gcc -O2 -flto -c b.c
gcc -O2 -flto a.o b.o -o app

Clang supports full and scalable ThinLTO:

clang -O2 -flto=full ...
clang -O2 -flto=thin ...

See Clang ThinLTO documentation. LTO can enable cross-module inlining, constant propagation and dead-code elimination, but increases link memory and complexity. GCC notes that linker-plugin-aware archive tools such as ar, nm and ranlib may be required (GCC options); Clang LTO is natively supported by ld.lld and can use a gold plugin (Clang toolchain). Binary-only objects, inline assembly, mixed compiler versions and linker scripts are common failure points. Keep a non-LTO fallback and use -fno-lto for an isolated component when necessary.

PGO is a workload process, not a magic switch

For Clang’s instrumentation flow:

clang -O2 -fprofile-instr-generate -fcoverage-mapping source.c -o app-instrumented
LLVM_PROFILE_FILE="app-%p.profraw" ./app-instrumented
llvm-profdata merge -output=app.profdata app-*.profraw
clang -O2 -fprofile-instr-use=app.profdata source.c -o app-pgo

Use representative hardware and traffic, include error and recovery paths, then validate trained and untrained workloads. Profiles become stale after significant source, compiler or workload changes. LLVM’s PGO guide covers the workflow. Advanced kernel workflows such as AutoFDO, ThinLTO and Propeller have their own requirements; the documented kernel Propeller workflow requires LLVM 19 or later (kernel documentation).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

GCC versus Clang/LLVM

GCC is often the lowest-risk choice for vendor BSPs, GNU extensions and broad architecture support. Clang/LLVM offers integrated tools, ThinLTO, sanitizers, ld.lld, llvm-ar and strong analysis workflows. Clang is not a complete environment by itself: compiler runtime, C library, C++ ABI, startup objects, assembler, linker and sysroot must agree (toolchain components). Compare matched versions, target, linker, libraries, flags and workloads; do not claim a universal speed winner.

Rank #4
ZYNQ 7000 FPGA Development Board PZ7010 PZ7020 Starlite XC7Z010 XC7Z020 DDR3 USB Ethernet HDMI JTAG for Embedded Linux and FPGA Learning (PZ7020-SL-C, FPGA Board)
  • ZYNQ-7000 ARM+FPGA SoC: Powered by Xilinx ZYNQ XC7Z010/020 with dual-core ARM Cortex-A9 and programmable logic—ideal for embedded and FPGA development.
  • Integrated Interfaces for Versatile Applications: Features HDMI, USB 2.0 Host, UART, JTAG, Gigabit Ethernet (PS & PL), SD card, and 40-pin expansion for AD/DA, LCD, and camera modules.
  • Robust Memory & Storage: Equipped with 512MB/1GB DDR3, 128Mb QSPI Flash, 64Kbit EEPROM, and boot selection via JTAG/QSPI/SD for flexible design setups.
  • Industrial-Grade Design: Compact 90x60mm board with immersion gold finish, suitable for industrial environments. 5V/1A power input supports stable operation.
  • Support for Linux and Hardware Demos: Supports embedded Linux system, MIPI CSI camera input (7020 only), and comes with HDL demos—perfect for research and education.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Kernel builds with LLVM

The Linux kernel supports LLVM-based builds:

make LLVM=1 defconfig
make LLVM=1 -j"$(nproc)"

Or specify tools explicitly:

make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip

LLVM=1 selects LLVM utilities, while cross compilation uses a target triple rather than simply prefixing a GNU compiler name. Architecture, kernel version, external modules, assembler and vendor drivers can change the required command. Consult the kernel LLVM build documentation.

Keep build purposes separate

debug:             -Og -g3 -fno-omit-frame-pointer
release-debuggable:-O2 -g -fno-omit-frame-pointer
release:           -O2 (or measured alternative), symbols archived
size:              -Os or -Oz plus section GC
sanitized:         -O1 or -O2 -g with target-supported runtime

Clang sanitizers generally require flags at compile and link time. For example:

clang -O1 -g -fsanitize=address,undefined 
  -fno-omit-frame-pointer app.c -o app-sanitize

AddressSanitizer, UBSan, ThreadSanitizer, CFI and related tools can add substantial size and timing overhead; not all combinations or target runtimes are supported. Trap-style sanitizer operation can suit constrained systems (Clang User’s Manual). Never report sanitized measurements as production performance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A disciplined experiment loop

  1. Baseline: freeze source, toolchain, sysroot, kernel, frequency governor and workload.
  2. Measure: use /usr/bin/time -v, perf stat, perf record -g, perf report and strace -c where target support permits. Include cold/warm startup, RSS, page faults, image size and energy.
  3. Change one variable: -O2 → target selection → -Os/-Oz → selected -O3 → section GC → LTO → PGO.
  4. Validate: unit, integration, hardware-in-loop, soak, thermal, watchdog, power-cycle, network/storage fault and upgrade/rollback tests.
  5. Inspect: file, readelf -h -A -d, ldd in a compatible environment, size, hardening properties and disassembly. Test the oldest supported board.
  6. Retain: archive flags, versions, profile workload, benchmark data, artifact hashes and a reproducible rollback build.

Common failures and recovery

  • -O3 is slower: check I-cache misses, branch behavior, inlining and register pressure; return to -O2 or limit -O3 to hot units.
  • Illegal instruction: remove host-native options, inspect attributes/disassembly and rebuild for the minimum ISA.
  • LTO link failure: verify plugin-aware tools and consistent compiler versions; disable LTO for the offending library.
  • PGO regression: collect multiple representative profiles, include rare paths and define profile invalidation rules.
  • Sanitized image will not start: provide the matching runtime, reduce sanitizers, use a development target or trap mode.
  • Size optimization breaks startup: inspect the map, restore retained sections and test constructors/plugins.
  • Clang fails where GCC works: isolate GCC extensions, inline assembly, runtime, assembler, linker or vendor patches before deciding whether to change source or compiler.

Practical policy

For most products, adopt -O2 with an explicit minimum ISA and ABI as the reproducible baseline. Use -Os/-Oz for measured image constraints, LTO for components that can absorb its build cost, and PGO only with stable representative workloads. Treat -O3, -Ofast, fast math, AutoFDO and layout tools as reviewed experiments. Benchmark on target hardware, preserve symbols outside the deployed image, and keep the baseline build as rollback insurance.

Open-source GCC or Clang is usually sufficient. Consider a commercial Arm compiler or development suite only when vendor support, qualification evidence, traceability, diagnostics or integrated profiling has measurable business value; do not buy a toolchain simply because a flag sounds more aggressive.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.