From c035fd0d02a5ecae4f36bf414528a5268eed3286 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Mon, 20 Jan 2025 22:07:17 -0800 Subject: [PATCH] llvmPackages.bolt: add experimental bolt hook --- lib/systems/default.nix | 2 ++ pkgs/build-support/cc-wrapper/default.nix | 8 ++++++++ .../compilers/llvm/common/bolt/default.nix | 9 +++++++++ .../compilers/llvm/common/bolt/setup-hook.sh.in | 16 ++++++++++++++++ pkgs/development/libraries/glibc/common.nix | 3 +++ pkgs/stdenv/cross/default.nix | 3 +++ pkgs/top-level/release-attrpaths-superset.nix | 1 + pkgs/top-level/release.nix | 1 + pkgs/top-level/stage.nix | 14 ++++++++++++++ 9 files changed, 57 insertions(+) create mode 100644 pkgs/development/compilers/llvm/common/bolt/setup-hook.sh.in diff --git a/lib/systems/default.nix b/lib/systems/default.nix index ec0106a13dacf..7dff3fd8c67d1 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -93,6 +93,8 @@ let # Derived meta-data useLLVM = final.isFreeBSD || final.isOpenBSD; + useBolt = false; + libc = /**/ if final.isDarwin then "libSystem" else if final.isMinGW then "msvcrt" diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 8558a9f3d8d26..3b24742d9a4fe 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -728,6 +728,14 @@ stdenvNoCC.mkDerivation { substituteAll ${./add-clang-cc-cflags-before.sh} $out/nix-support/add-local-cc-cflags-before.sh '' + ### + ### Bolt support + ### Binaries need to be linked with relocations. + ### + + optionalString targetPlatform.useBolt '' + echo " --emit-relocs" >> $out/nix-support/cc-ldflags + '' + ## ## Extra custom steps ## diff --git a/pkgs/development/compilers/llvm/common/bolt/default.nix b/pkgs/development/compilers/llvm/common/bolt/default.nix index 9bc078df0e444..0c361d7146b03 100644 --- a/pkgs/development/compilers/llvm/common/bolt/default.nix +++ b/pkgs/development/compilers/llvm/common/bolt/default.nix @@ -12,6 +12,7 @@ libclang, version, python3, + substituteAll, buildLlvmTools, patches ? [ ], devExtraCmakeFlags ? [ ], @@ -71,6 +72,9 @@ stdenv.mkDerivation (finalAttrs: { postInstall = '' mkdir -p $dev/lib mv $out/lib/libLLVMBOLT*.a $dev/lib + + mkdir -p $out/nix-support + cp $setupHook $out/nix-support/setup-hook ''; outputs = [ @@ -78,6 +82,11 @@ stdenv.mkDerivation (finalAttrs: { "dev" ]; + setupHook = substituteAll { + src = ./setup-hook.sh.in; + env.readelf = lib.getExe' libllvm "llvm-readelf"; + }; + meta = llvm_meta // { homepage = "https://github.com/llvm/llvm-project/tree/main/bolt"; description = "LLVM post-link optimizer."; diff --git a/pkgs/development/compilers/llvm/common/bolt/setup-hook.sh.in b/pkgs/development/compilers/llvm/common/bolt/setup-hook.sh.in new file mode 100644 index 0000000000000..7fd930121b0b5 --- /dev/null +++ b/pkgs/development/compilers/llvm/common/bolt/setup-hook.sh.in @@ -0,0 +1,16 @@ +# shellcheck shell=bash + +function boltFixupPhase { + local i + while IFS= read -r -d $'\0' i; do + if ! isELF "$i"; then continue; fi + if ! @readelf@ --program-headers "$i" | grep -q LOAD; then continue; fi + + llvm-bolt "$i" -o $(dirname "$i")/.bolt-$(basename "$i") "${boltFlags[@]-}" + mv $(dirname "$i")/.bolt-$(basename "$i") "$i" + done < <(find "$prefix" -type f -print0) +} + +if [ -z "${dontUseBolt-}" ]; then + appendToVar preFixupPhases boltFixupPhase +fi diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index 4e2c245dddced..aa39f939a0d0b 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -349,4 +349,7 @@ stdenv.mkDerivation ( } // (args.meta or { }); } + // lib.optionalAttrs stdenv.hostPlatform.useBolt { + dontUseBolt = stdenv.cc.isGNU; + } ) diff --git a/pkgs/stdenv/cross/default.nix b/pkgs/stdenv/cross/default.nix index 69ea14be5c83d..eace479b806a8 100644 --- a/pkgs/stdenv/cross/default.nix +++ b/pkgs/stdenv/cross/default.nix @@ -69,6 +69,9 @@ lib.init bootStages extraNativeBuildInputs = old.extraNativeBuildInputs ++ lib.optionals (hostPlatform.isLinux && !buildPlatform.isLinux) [ buildPackages.patchelf ] + ++ lib.optionals hostPlatform.useBolt [ + buildPackages.llvmPackages.bolt + ] ++ lib.optional ( let f = diff --git a/pkgs/top-level/release-attrpaths-superset.nix b/pkgs/top-level/release-attrpaths-superset.nix index c306a64be585e..e4ee9c6511b76 100644 --- a/pkgs/top-level/release-attrpaths-superset.nix +++ b/pkgs/top-level/release-attrpaths-superset.nix @@ -51,6 +51,7 @@ let # cross packagesets pkgsLLVM = true; pkgsLLVMLibc = true; + pkgsBolt = true; pkgsMusl = true; pkgsStatic = true; pkgsCross = true; diff --git a/pkgs/top-level/release.nix b/pkgs/top-level/release.nix index 97e64f73c510d..a5c0a1b70cfc9 100644 --- a/pkgs/top-level/release.nix +++ b/pkgs/top-level/release.nix @@ -345,6 +345,7 @@ let agdaPackages = packagePlatforms pkgs.agdaPackages; pkgsLLVM.stdenv = [ "x86_64-linux" "aarch64-linux" ]; + pkgsBolt.stdenv = [ "x86_64-linux" "aarch64-linux" ]; pkgsLLVMLibc.stdenv = [ "x86_64-linux" "aarch64-linux" ]; pkgsArocc.stdenv = [ "x86_64-linux" "aarch64-linux" ]; pkgsZig.stdenv = [ "x86_64-linux" "aarch64-linux" ]; diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 64bc2308f6da7..f1ee4df1b297d 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -211,6 +211,20 @@ let }; }; + pkgsBolt = nixpkgsFun { + overlays = [ + (self': super': { + pkgsBolt = super'; + }) + ] ++ overlays; + # Bootstrap a cross stdenv and apply the Bolt post-link optimizer. + # This is currently not possible when compiling natively, + # so we don't need to check hostPlatform != buildPlatform. + crossSystem = stdenv.hostPlatform // { + useBolt = true; + }; + }; + pkgsLLVMLibc = nixpkgsFun { overlays = [ (self': super': { pkgsLLVMLibc = super';