Optimize AArch64 code with LLVM link-time optimization and profile-guided optimization
Introduction
Understand PGO and LTO for AArch64 code
Prepare your AArch64 environment and verify LLVM tool availability
Build AArch64 code with LTO
Optimize AArch64 code with S-PGO
Optimize AArch64 code with FE-PGO
Optimize AArch64 code with IR-PGO
Optimize AArch64 code with CSIR-PGO
Next Steps
Optimize AArch64 code with LLVM link-time optimization and profile-guided optimization
Combine LTO and PGO
You’ll use LLVM link-time optimization (LTO) and profile-guided optimization (PGO) together on AArch64 Linux.
LTO gives the compiler visibility across source-file boundaries during the link stage. Without LTO, LLVM optimizes each translation unit separately before linking it into the application. PGO adds information about runtime behavior. LLVM can use function frequencies and branch counts to guide inlining, code layout, and other optimization decisions.
LTO and PGO are complementary. LTO enables whole-program optimizations, while PGO provides runtime profile data that guides optimization decisions.
The example that you’ll use is a deliberately small C++ application. The application demonstrates the LLVM workflow and compiler options, but its single source file doesn’t show the cross-module optimization opportunities that LTO provides in a larger application.
For useful PGO results, train the instrumented or sampled binary with inputs that represent your production workload. LLVM can optimize code that the profile identifies as hot and reduce optimization of unexecuted code. An unrepresentative profile can therefore reduce performance for important use cases.
The following sections cover LLVM LTO and several LLVM PGO workflows, each with different trade-offs:
LLVM LTO gives the compiler visibility across source file boundaries at link time. This provides the baseline for the later profile-guided workflows.
LLVM sample-based PGO (S-PGO) uses sampled execution data collected with
perfinstead of compiler-inserted instrumentation. S-PGO has lower profiling overhead, but the Branch Record Buffer Extension (BRBE) workflow requires supported Arm hardware and Linux kernel 6.17 or later.LLVM frontend PGO (FE-PGO) instruments the program in the Clang frontend to record execution counts. FE-PGO can be useful when profile data needs to map closely to the source code, but IR-PGO is usually the better starting point for optimization.
LLVM intermediate representation-level PGO (IR-PGO) instruments the program at the LLVM IR level to record execution counts. IR-PGO is the default instrumentation-based workflow in this Learning Path. It’s typically the preferred option for performance optimization with Clang.
LLVM context-sensitive IR-PGO (CSIR-PGO) adds a second, context-sensitive profiling pass after an initial IR-PGO build. CSIR-PGO can give LLVM more precise profile data, but it requires an extra build and profiling run.
What you’ve learned and what’s next
You now understand how LTO expands the scope of LLVM optimization and how the available PGO workflows collect runtime behavior.
Next, you’ll prepare the test directory and verify the LLVM tools.