Skip to content

Instantly share code, notes, and snippets.

@kees
Created February 12, 2021 22:51
Show Gist options
  • Save kees/32fe16c4dfb0d9ab73e60d3682718725 to your computer and use it in GitHub Desktop.
Save kees/32fe16c4dfb0d9ab73e60d3682718725 to your computer and use it in GitHub Desktop.
Build Profiling-Guided Optimized Clang for the Linux kernel
#!/bin/bash
# This expects a specific directory layout and contents:
#
# $HOME/src/linux - clone of Linux repo (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git)
# $HOME/src/llvm-project - clone of LLVM repo (https://github.com/llvm/llvm-project.git)
# $HOME/src/linux-build - place to keep kernel builds
# $HOME/src/llvm-build - place to keep LLVM builds
#
#!/bin/bash
set -e
BUILD="$HOME/src/llvm-build"
PROJECT="$HOME/src/llvm-project/llvm"
# Stage 1 (for when we don't already have Clang)
CLANG=$(which clang)
if [ -z "$CLANG" ] ; then
echo "Stage 1"
cd "$BUILD"
OUT="$BUILD/stage1"
rm -rf "$OUT"
mkdir "$OUT" && cd "$OUT"
cmake -G Ninja --log-level=NOTICE \
-DLLVM_TARGETS_TO_BUILD=X86 -DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS='clang;lld;compiler-rt;polly' \
-DLLVM_ENABLE_LLD=ON \
-DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ \
-DCMAKE_ASM_COMPILER=gcc \
-DCMAKE_INSTALL_PREFIX="$OUT/install" \
"$PROJECT"
time ninja install
STAGE1="$BUILD/stage1/install/bin"
else
echo "Using existing $CLANG -- to rebuild, remove it first."
STAGE1="$(dirname "$CLANG")"
fi
# Stage 2 (to enable collecting profiling data)
echo "Stage 2"
cd "$BUILD"
OUT="$BUILD/stage2-prof-gen"
if [ ! -d "$OUT" ]; then
mkdir "$OUT" && cd "$OUT"
cmake -G Ninja --log-level=NOTICE \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS='clang;lld;compiler-rt;polly' \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD='CSKY' \
-DLLVM_ENABLE_LTO=Thin \
-DLLVM_USE_LINKER=lld \
-DCMAKE_C_COMPILER="$STAGE1"/clang \
-DCMAKE_CXX_COMPILER="$STAGE1"/clang++ \
-DCMAKE_RANLIB="$STAGE1"/llvm-ranlib \
-DCMAKE_AR="$STAGE1"/llvm-ar \
-DLLVM_BUILD_INSTRUMENTED=ON \
-DCMAKE_INSTALL_PREFIX="$OUT/install" \
"$PROJECT"
time ninja install
else
echo "Using existing $OUT -- to rebuild, remove it first."
fi
STAGE2="$OUT/install/bin"
PROFILES="$OUT/profiles"
rm -rf "$PROFILES"/*
# Train PGO
cd "$HOME"/src/linux
WORKTREE="$HOME"/src/linux-build/clang
rm -rf "$WORKTREE"
git worktree prune
git worktree add --detach "$WORKTREE" master
cd "$WORKTREE"
echo "Training x86"
make -s allmodconfig CC="$STAGE2"/clang LD="$STAGE2"/ld.lld
time make -s -j$(getconf _NPROCESSORS_ONLN) --keep-going \
CC="$STAGE2"/clang LD="$STAGE2"/ld.lld || true
echo "Training arm64"
make -s allmodconfig \
CC="$STAGE2"/clang LD="$STAGE2"/ld.lld CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64
time make -s -j$(getconf _NPROCESSORS_ONLN) --keep-going \
CC="$STAGE2"/clang LD="$STAGE2"/ld.lld CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 || true
echo "Training arm"
make -s allmodconfig \
CC="$STAGE2"/clang LD="$STAGE2"/ld.lld CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm
time make -s -j$(getconf _NPROCESSORS_ONLN) --keep-going \
CC="$STAGE2"/clang LD="$STAGE2"/ld.lld CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm || true
# Merge training
cd "$PROFILES"
"$STAGE2"/llvm-profdata merge -output=clang.profdata *
# Stage 3 (built with PGO profile data)
echo "Stage 3"
cd "$BUILD"
OUT="$BUILD/stage3"
rm -rf "$OUT"
mkdir "$OUT" && cd "$OUT"
cmake -G Ninja --log-level=NOTICE \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS='clang;lld;compiler-rt;polly' \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD='CSKY' \
-DLLVM_ENABLE_LTO=Thin \
-DLLVM_USE_LINKER=lld \
-DCMAKE_C_COMPILER="$STAGE1"/clang \
-DCMAKE_CXX_COMPILER="$STAGE1"/clang++ \
-DCMAKE_RANLIB="$STAGE1"/llvm-ranlib \
-DCMAKE_AR="$STAGE1"/llvm-ar \
-DLLVM_PROFDATA_FILE="$PROFILES"/clang.profdata \
-DCMAKE_INSTALL_PREFIX="$OUT/install" \
"$PROJECT"
time ninja install
STAGE3="$OUT/install/bin"
echo "$STAGE3" 109,1 Bo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment