[llvm] [LTO] Hash CSIR configuration in the ThinLTO cache key (PR #214162)
Karim Alweheshy via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 5 02:03:34 PDT 2026
https://github.com/karim-alweheshy created https://github.com/llvm/llvm-project/pull/214162
## Summary
- Include CSIR instrumentation mode and its output path in the ThinLTO cache
key.
- Include consumed CSIR profile and remapping contents in the cache key.
- Add shared-cache versus fresh-cache regressions for both generation and use.
## Problem
`Config::RunCSIRInstr` and `Config::CSIRProfile` affect ThinLTO backend output,
but neither currently contributes to `computeLTOCacheKey`.
Two reduced current-`main` controls reproduce stale reuse:
- A cache populated without CS instrumentation returns the same uninstrumented
object when CS instrumentation is then enabled. A fresh cache emits the
expected profile-runtime references and data.
- Replacing a consumed CSIR profile at a stable path returns the object built
with the previous profile. A fresh cache reflects the new branch counts.
## Fix
Hash the CS instrumentation mode and, while generating, the configured profile
output path because it is embedded in the instrumented object. While consuming
a CSIR profile, hash the profile contents and optional remapping contents, as is
already done for sample profiles.
## Testing
- Verified both stale-reuse cases on unpatched current `main`.
- Compiled the changed LTO translation unit from current `main`.
- Ran the focused patched controls:
- shared-cache instrumentation output is byte-identical to the instrumented
fresh-cache output and contains the profile runtime reference;
- after an in-place CSIR profile change, shared-cache output is byte-identical
to the fresh-cache output and distinct from the first profile's output.
- `git diff --check`.
>From 065c867d9cef08108bc61c7ae686abdf51557fa0 Mon Sep 17 00:00:00 2001
From: Karim Alweheshy <karim.alweheshy at gmail.com>
Date: Wed, 5 Aug 2026 11:02:28 +0200
Subject: [PATCH] [LTO] Hash CSIR configuration in the ThinLTO cache key
---
llvm/lib/LTO/LTO.cpp | 16 +++++
llvm/test/ThinLTO/AArch64/cspgo-cache.ll | 88 ++++++++++++++++++++++++
2 files changed, 104 insertions(+)
create mode 100644 llvm/test/ThinLTO/AArch64/cspgo-cache.ll
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index c8c5b0880819a..51b6976115a1b 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -204,6 +204,9 @@ std::string llvm::computeLTOCacheKey(
AddString(Conf.DefaultTriple);
AddString(Conf.DwoDir);
AddUint8(Conf.Dtlto);
+ AddUint8(Conf.RunCSIRInstr);
+ if (Conf.RunCSIRInstr)
+ AddString(Conf.CSIRProfile);
// Include the hash for the current module
auto ModHash = Index.getModuleHash(ModuleID);
@@ -388,6 +391,19 @@ std::string llvm::computeLTOCacheKey(
}
}
+ if (!Conf.RunCSIRInstr && !Conf.CSIRProfile.empty()) {
+ auto FileOrErr = MemoryBuffer::getFile(Conf.CSIRProfile);
+ if (FileOrErr) {
+ Hasher.update(FileOrErr.get()->getBuffer());
+
+ if (!Conf.ProfileRemapping.empty()) {
+ FileOrErr = MemoryBuffer::getFile(Conf.ProfileRemapping);
+ if (FileOrErr)
+ Hasher.update(FileOrErr.get()->getBuffer());
+ }
+ }
+ }
+
return toHex(Hasher.result());
}
diff --git a/llvm/test/ThinLTO/AArch64/cspgo-cache.ll b/llvm/test/ThinLTO/AArch64/cspgo-cache.ll
new file mode 100644
index 0000000000000..299b0eebb5fc0
--- /dev/null
+++ b/llvm/test/ThinLTO/AArch64/cspgo-cache.ll
@@ -0,0 +1,88 @@
+; Verify that the ThinLTO cache key includes CSIR instrumentation mode and
+; profile inputs.
+;
+; RUN: rm -rf %t; split-file %s %t
+; RUN: opt -module-summary -module-hash %t/input.ll -o %t/input.bc
+;
+; Changing only CS instrumentation mode must not reuse an uninstrumented
+; object. The shared-cache result must match a fresh-cache control.
+; RUN: llvm-lto2 run -cache-dir=%t/gen-cache %t/input.bc -o %t/gen-off \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: llvm-lto2 run -cache-dir=%t/gen-cache -lto-cspgo-gen \
+; RUN: -lto-cspgo-profile-file=%t/default_%m.profraw \
+; RUN: %t/input.bc -o %t/gen-on-shared \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: llvm-lto2 run -cache-dir=%t/gen-fresh-cache -lto-cspgo-gen \
+; RUN: -lto-cspgo-profile-file=%t/default_%m.profraw \
+; RUN: %t/input.bc -o %t/gen-on-fresh \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: llvm-nm %t/gen-on-shared.1 | FileCheck %s --check-prefix=INSTRUMENTED
+; RUN: cmp %t/gen-on-shared.1 %t/gen-on-fresh.1
+;
+; INSTRUMENTED: __llvm_profile_runtime
+;
+; Changing only the contents of a CSIR profile at a stable path must likewise
+; invalidate the cache. The two profiles reverse the hot loop edge.
+; RUN: llvm-profdata merge %t/hot-loop.proftext -o %t/active.profdata
+; RUN: llvm-lto2 run -cache-dir=%t/use-cache -pgo-instrument-entry=false \
+; RUN: -lto-cspgo-profile-file=%t/active.profdata \
+; RUN: %t/input.bc -o %t/use-hot \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: llvm-profdata merge %t/cold-loop.proftext -o %t/active.profdata
+; RUN: llvm-lto2 run -cache-dir=%t/use-cache -pgo-instrument-entry=false \
+; RUN: -lto-cspgo-profile-file=%t/active.profdata \
+; RUN: %t/input.bc -o %t/use-cold-shared \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: llvm-lto2 run -cache-dir=%t/use-fresh-cache \
+; RUN: -pgo-instrument-entry=false \
+; RUN: -lto-cspgo-profile-file=%t/active.profdata \
+; RUN: %t/input.bc -o %t/use-cold-fresh \
+; RUN: -r %t/input.bc,_foo,px -r %t/input.bc,_bar,
+; RUN: cmp %t/use-cold-shared.1 %t/use-cold-fresh.1
+; RUN: not cmp %t/use-hot.1 %t/use-cold-shared.1
+;
+;--- input.ll
+source_filename = "cspgo.c"
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-apple-ios12.0.0"
+
+define void @foo() {
+entry:
+ br label %for.body
+
+for.body:
+ %i = phi i32 [ 0, %entry ], [ %next, %for.body ]
+ call void @bar(i32 %i)
+ %odd = or i32 %i, 1
+ call void @bar(i32 %odd)
+ %next = add nuw nsw i32 %i, 2
+ %cmp = icmp ult i32 %next, 200000
+ br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+ ret void
+}
+
+declare void @bar(i32)
+
+;--- hot-loop.proftext
+:csir
+foo
+# Func Hash:
+1936928561113927580
+# Num Counters:
+2
+# Counter Values:
+100000
+1
+
+;--- cold-loop.proftext
+:csir
+foo
+# Func Hash:
+1936928561113927580
+# Num Counters:
+2
+# Counter Values:
+1
+100000
More information about the llvm-commits
mailing list