[llvm] Avoid merging instrumentation profiler globals (PR #172835)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 22 08:59:10 PST 2025
https://github.com/eleviant updated https://github.com/llvm/llvm-project/pull/172835
>From bb90fd11dc81f35545f8362178578dfc48eebc20 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <eleviant at accesssoftek.com>
Date: Thu, 18 Dec 2025 12:04:43 +0100
Subject: [PATCH] Avoid merging globals residing in different comdats
The global-merge pass may merge globals residing in different comdat
groups, which may later confuse linker if section GC is being used. In
particular this may happen when merging instrumentation profiler
counters when their corresponding __llvm_prf_cnts sections are being
merged into a single one and moved out of a comdat group, containing
__llvm_prf_cnts and __llvm_prf_data sections. After that __llvm_prf_data
section is becoming orphaned and is garbage-collected when --gc-sections
linker flag is used.
---
llvm/lib/CodeGen/GlobalMerge.cpp | 16 +++++++++-------
.../AArch64/global-merge-profile-sections.ll | 11 +++++++++++
.../GlobalMerge/global-merge-comdat.ll | 7 +++++++
3 files changed, 27 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/global-merge-profile-sections.ll
create mode 100644 llvm/test/Transforms/GlobalMerge/global-merge-comdat.ll
diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp
index b8b0d4d612742..653c4e8ee4389 100644
--- a/llvm/lib/CodeGen/GlobalMerge.cpp
+++ b/llvm/lib/CodeGen/GlobalMerge.cpp
@@ -562,6 +562,7 @@ bool GlobalMergeImpl::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
MergedGV->setAlignment(MaxAlign);
MergedGV->setSection(Globals[i]->getSection());
+ MergedGV->setComdat(Globals[i]->getComdat());
LLVM_DEBUG(dbgs() << "MergedGV: " << *MergedGV << "\n");
@@ -677,7 +678,8 @@ bool GlobalMergeImpl::run(Module &M) {
IsMachO = M.getTargetTriple().isOSBinFormatMachO();
auto &DL = M.getDataLayout();
- MapVector<std::pair<unsigned, StringRef>, SmallVector<GlobalVariable *, 0>>
+ MapVector<std::tuple<unsigned, StringRef, Comdat *>,
+ SmallVector<GlobalVariable *, 0>>
Globals, ConstGlobals, BSSGlobals;
bool Changed = false;
setMustKeepGlobalVariables(M);
@@ -735,11 +737,11 @@ bool GlobalMergeImpl::run(Module &M) {
if (CanMerge) {
if (TM &&
TargetLoweringObjectFile::getKindForGlobal(&GV, *TM).isBSS())
- BSSGlobals[{AddressSpace, Section}].push_back(&GV);
+ BSSGlobals[{AddressSpace, Section, GV.getComdat()}].push_back(&GV);
else if (GV.isConstant())
- ConstGlobals[{AddressSpace, Section}].push_back(&GV);
+ ConstGlobals[{AddressSpace, Section, GV.getComdat()}].push_back(&GV);
else
- Globals[{AddressSpace, Section}].push_back(&GV);
+ Globals[{AddressSpace, Section, GV.getComdat()}].push_back(&GV);
}
LLVM_DEBUG(dbgs() << "GV " << (CanMerge ? "" : "not ") << "to merge: " << GV
<< "\n");
@@ -747,16 +749,16 @@ bool GlobalMergeImpl::run(Module &M) {
for (auto &P : Globals)
if (P.second.size() > 1)
- Changed |= doMerge(P.second, M, false, P.first.first);
+ Changed |= doMerge(P.second, M, false, std::get<0>(P.first));
for (auto &P : BSSGlobals)
if (P.second.size() > 1)
- Changed |= doMerge(P.second, M, false, P.first.first);
+ Changed |= doMerge(P.second, M, false, std::get<0>(P.first));
if (Opt.MergeConstantGlobals)
for (auto &P : ConstGlobals)
if (P.second.size() > 1)
- Changed |= doMerge(P.second, M, true, P.first.first);
+ Changed |= doMerge(P.second, M, true, std::get<0>(P.first));
return Changed;
}
diff --git a/llvm/test/CodeGen/AArch64/global-merge-profile-sections.ll b/llvm/test/CodeGen/AArch64/global-merge-profile-sections.ll
new file mode 100644
index 0000000000000..7108d82ddaa2e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/global-merge-profile-sections.ll
@@ -0,0 +1,11 @@
+; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-enable-global-merge -global-merge-group-by-use=false < %s | FileCheck %s
+; CHECK-NOT: _MergedGlobals
+
+$__profc_begin = comdat nodeduplicate
+$__profc_end = comdat nodeduplicate
+
+ at __profc_begin = private global [2 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8
+ at __profd_begin = private global { i64, i64, i64, i64, ptr, ptr, i32, [3 x i16], i32 } { i64 -1301828029439649651, i64 172590168, i64 sub (i64 ptrtoint (ptr @__profc_begin to i64), i64 ptrtoint (ptr @__profd_begin to i64)), i64 0, ptr null, ptr null, i32 2, [3 x i16] zeroinitializer, i32 0 }, section "__llvm_prf_data", comdat($__profc_begin), align 8
+ at __profc_end = private global [2 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8
+ at __profd_end = private global { i64, i64, i64, i64, ptr, ptr, i32, [3 x i16], i32 } { i64 3274037854792712831, i64 172590168, i64 sub (i64 ptrtoint (ptr @__profc_end to i64), i64 ptrtoint (ptr @__profd_end to i64)), i64 0, ptr null, ptr null, i32 2, [3 x i16] zeroinitializer, i32 0 }, section "__llvm_prf_data", comdat($__profc_end), align 8
+
diff --git a/llvm/test/Transforms/GlobalMerge/global-merge-comdat.ll b/llvm/test/Transforms/GlobalMerge/global-merge-comdat.ll
new file mode 100644
index 0000000000000..fed568b566e16
--- /dev/null
+++ b/llvm/test/Transforms/GlobalMerge/global-merge-comdat.ll
@@ -0,0 +1,7 @@
+; RUN: opt -global-merge -global-merge-max-offset=16 -global-merge-group-by-use=false %s -S -o - | FileCheck %s
+; CHECK: @_MergedGlobals = private global <{ i64, i64 }> zeroinitializer, section "__foo", comdat($__foo), align 8
+
+$__foo = comdat nodeduplicate
+
+ at __bar = private global i64 0, section "__foo", comdat($__foo), align 8
+ at __baz = private global i64 0, section "__foo", comdat($__foo), align 8
More information about the llvm-commits
mailing list