[llvm] Avoid merging instrumentation profiler globals (PR #172835)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 22 08:17:01 PST 2025


https://github.com/eleviant updated https://github.com/llvm/llvm-project/pull/172835

>From 4ade16626da42a576defcd71cfd3bbfb44af7e1a 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 instrumentation profiler globals

The global-merge pass attempts to merge instumentation profiler counters,
e.g __profc_foo and __profc_bar, which results in their corresponding
__llvm_prf_cnts sections being merged into a single one and moved out
from a comdat group, which originally gropus __llvm_prf_cnts and
__llvm_prf_data sections. This, in turn, results in __llvm_prf_data
becoming an orphaned section, which is garbage-collected when
--gc-sections linker flag is used.
---
 llvm/lib/CodeGen/GlobalMerge.cpp                 | 16 +++++++++-------
 llvm/test/CodeGen/AArch64/global-merge-comdat.ll |  7 +++++++
 .../AArch64/global-merge-profile-sections.ll     | 11 +++++++++++
 3 files changed, 27 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/global-merge-comdat.ll
 create mode 100644 llvm/test/CodeGen/AArch64/global-merge-profile-sections.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-comdat.ll b/llvm/test/CodeGen/AArch64/global-merge-comdat.ll
new file mode 100644
index 0000000000000..fed568b566e16
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/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
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
+



More information about the llvm-commits mailing list