Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions content/install-guides/llvm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
title: LLVM toolchain for Linux on Arm

additional_search_terms:
- llvm
- clang
- compiler
- lld
- pgo
- lto
- profdata
- profgen

minutes_to_complete: 10

author: Paschalis Mpeis

official_docs: https://releases.llvm.org/download.html
description: Install the LLVM toolchain on Arm Linux to use Clang, LLD, and profiling utilities.

test_images:
- ubuntu:latest
test_maintenance: false

layout: installtoolsall
tool_install: true
multi_install: false
multitool_install_part: false
weight: 1
---

The LLVM toolchain includes Clang, LLD, and other LLVM utilities for compiling, linking, and optimizing applications.

In this guide, you’ll learn how to download, extract, and install the LLVM toolchain from a prebuilt binary release on Arm Linux.

## Before you begin

Confirm you are using an Arm machine by running:

Run:

```bash
uname -m
```

The output is similar to:

```output
aarch64
```

If you see a different result, you are not using an Arm computer running 64-bit Linux.

Install the tools needed to download and extract the archive.
For Debian-based Linux distributions, including Ubuntu, install `wget` and `xz-utils`:


```bash { target="ubuntu:latest" }
sudo apt update
sudo apt install wget xz-utils -y
```

## Install LLVM

You can install LLVM by downloading a prebuilt binary release from GitHub.

The following commands use LLVM version 22.1.8. To install a different version, replace the filename in the commands below. For the latest releases, see [LLVM Project releases](https://github.com/llvm/llvm-project/releases).

The commands extract LLVM to `$HOME/toolchain`. To install LLVM in a different location, adjust the extraction path and update the PATH environment variable accordingly.

1. Download a binary release

For Arm Linux, use the archive with `Linux-ARM64` in its filename:


```bash
mkdir -p $HOME/toolchain
cd $HOME/toolchain
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/LLVM-22.1.8-Linux-ARM64.tar.xz
```

2. Extract the downloaded file

```bash
tar -xvf LLVM-22.1.8-Linux-ARM64.tar.xz
```

3. Add the LLVM `bin` directory to your `PATH`

This enables you to run LLVM tools such as `clang` and `lld` from any directory.
The command updates `PATH` for your current terminal session.
To make the change persistent, add the same command to your shell profile, such as `~/.bashrc`.

```bash
export PATH="$HOME/toolchain/LLVM-22.1.8-Linux-ARM64/bin:$PATH"
```
## Verify LLVM is installed {#verify}

Run the following commands:

```console
clang --version
clang++ --version
ld.lld --version
```

The output is similar to:

```output
clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/ubuntu/toolchain/LLVM-22.1.8-Linux-ARM64/bin

clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/ubuntu/toolchain/LLVM-22.1.8-Linux-ARM64/bin

LLD 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1) (compatible with GNU linkers)
```

Each command should print LLVM version information.

## Compile and run a C++ example

Use a text editor to copy and paste the following code into a file named `hello.cpp`:

```cpp { file_name="hello.cpp" }
#include <iostream>

int main()
{
std::cout << "Hello, LLVM on Arm\n";
return 0;
}
```

Compile the example with `clang++` and link it with LLD:

```bash
clang++ -fuse-ld=lld hello.cpp -o hello
```

Run the example:

```bash
./hello
```

The output is:

```output
Hello, LLVM on Arm
```

You are now ready to use LLVM on your Arm Linux system.
70 changes: 70 additions & 0 deletions content/learning-paths/servers-and-cloud-computing/pgo/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: "Optimize AArch64 code with LLVM LTO and PGO"
description: Learn how to use LLVM Link-Time Optimization and Profile-Guided Optimization on AArch64 Linux.
minutes_to_complete: 45
aliases:
- /learning-paths/servers-and-cloud-computing/pgo-test/

who_is_this_for: This is an introductory topic for developers who compile C or C++ applications on AArch64 Linux and want to use Link-Time Optimization (LTO) with Profile-Guided Optimization (PGO).


learning_objectives:
- Understand the basics of Link-Time Optimization (LTO) and Profile-Guided Optimization (PGO)
- Build Thin-LTO and Full-LTO binaries with Clang on AArch64
- Generate instrumentation-based profile data with Clang on AArch64
- Generate sample-based profile data with Clang on AArch64
- Use generated profile data to optimize a small example application


prerequisites:
- LLVM installed with Clang, LLD, `llvm-profdata`, and `llvm-profgen` available in your `PATH`. For setup instructions, see [LLVM toolchain for Linux on Arm](/install-guides/llvm/).
- Linux kernel version 6.17 or later for the Branch Record Buffer Extension (BRBE) profile-guided optimization workflow


author: Paschalis Mpeis

### Tags
skilllevels: Introductory
subjects: Performance and Architecture
armips:
- Neoverse
- Cortex-A
tools_software_languages:
- Clang
- LLVM
- LTO
- PGO
- perf

operatingsystems:
- Linux

further_reading:
- resource:
title: Clang profile-guided optimization
link: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization
type: documentation
- resource:
title: llvm-profdata command guide
link: https://llvm.org/docs/CommandGuide/llvm-profdata.html
type: documentation
- resource:
title: llvm-profgen command guide
link: https://llvm.org/docs/CommandGuide/llvm-profgen.html
type: documentation
- resource:
title: LLVM LTO
link: https://llvm.org/docs/LinkTimeOptimization.html
type: documentation
- resource:
title: LLVM Thin-LTO
link: https://clang.llvm.org/docs/Thin-LTO.html
type: documentation


### FIXED, DO NOT MODIFY
# ================================================================================
weight: 1 # _index.md always has weight of 1 to order correctly
layout: "learningpathall" # All files under learning paths have this same wrapper
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# ================================================================================
# FIXED, DO NOT MODIFY THIS FILE
# ================================================================================
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
title: "Next Steps" # Always the same, html page title.
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
---
86 changes: 86 additions & 0 deletions content/learning-paths/servers-and-cloud-computing/pgo/csir-pgo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Optimize with CSIR-PGO
weight: 8

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## What is CSIR-PGO?

CSIR-PGO extends IR-PGO by adding a second, context-sensitive profiling pass.
The first pass is the standard IR-PGO instrumentation pass. The second pass instruments the program after inlining, which enables LLVM to distinguish execution counts from different calling contexts.
The additional context can improve optimization when function behavior depends on the call site, but it does not guarantee better performance for every program.

Use CSIR-PGO when you want to provide LLVM with more detailed profile information and can afford an extra build and training run.

## Build the context-sensitive instrumented binary

First, generate a standard IR-PGO profile as described in the [previous section](/learning-paths/servers-and-cloud-computing/pgo/ir-pgo/).
We reuse the resulting `prof/ir.profdata` profile to build a second instrumented binary with `-fcs-profile-generate`, which adds context-sensitive instrumentation after inlining.

```bash
clang++ -O3 -flto -fuse-ld=lld \
-fprofile-use=prof/ir.profdata \
-fcs-profile-generate=prof/csir \
bsort.cpp -o out/bsort.csirpgo.instr
```

Run the context-sensitive instrumented binary:

```bash
./out/bsort.csirpgo.instr
```

After the program exits, the raw profiles are written to:

```bash
ls prof/csir/*.profraw
```

## Merge, Convert, and Inspect the profile

As with IR-PGO, the context-sensitive training run can produce one or more raw `.profraw` files. Merge those files together with the existing `prof/ir.profdata` profile using `llvm-profdata` before using the merged profile during the final optimized build.


```bash
llvm-profdata merge prof/ir.profdata prof/csir -output=prof/csir.profdata
```

You can inspect the merged profile to see block counts. In the example below, the function `sort_array` has 6 context-sensitive counters with several recorded hits. You can inspect all functions with `--all-functions`, but the output can be extensive for large applications.

```bash { command_line="user@host | 2-13" }
llvm-profdata show --showcs --counts --function=sort_array prof/csir.profdata
Counters:
ld-temp.o;_Z10sort_arrayPi:
Hash: 0x18c2aba34f0cfff9
Counters: 6
Block counts: [24763682, 25224415, 9999, 9882, 1, 9881]
Instrumentation level: IR entry_first = 0 instrument_loop_entries = 0
Functions shown: 1
Total functions: 12
Maximum function count: 24763682
Maximum internal block count: 25224415
Total number of blocks: 32
Total count: 75242276
```

## Build with CSIR-PGO and LTO

Build the optimized binary using the merged CS-IR profile:


```bash
clang++ -O3 -flto -fuse-ld=lld -fprofile-use=prof/csir.profdata \
bsort.cpp -o out/bsort.csirpgo.opt
```

Run the optimized binary:

```bash { command_line="user@host | 2-3" }
./out/bsort.opt.csir
```

## What you've learned and what's next

You've added a second context-sensitive profiling pass on top of IR-PGO and built a CSIR-PGO optimized binary with LTO.
Loading
Loading