[llvm] [NFC][ModuleUtils] Move externalize() from module splitting utilities (PR #221181)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 06:02:30 PDT 2026


https://github.com/mmjjpp updated https://github.com/llvm/llvm-project/pull/221181

>From 53ce8b2ca7d5f3879d916915e406e8ebf9878b23 Mon Sep 17 00:00:00 2001
From: maojiaping <maojiaping1 at huawei.com>
Date: Fri, 4 Sep 2026 16:26:53 +0800
Subject: [PATCH 1/3] [NFC][ModuleUtils] Move externalize() from module
 splitting utilities

SplitModule.cpp and AMDGPUSplitModule.cpp each carry an identical
static externalize() helper. Move it to ModuleUtils as
llvm::externalize so existing and future module splitting utilities
can share a single implementation.
---
 .../llvm/Transforms/Utils/ModuleUtils.h       |  8 +++++++
 llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp  | 14 +------------
 llvm/lib/Transforms/Utils/ModuleUtils.cpp     | 12 +++++++++++
 llvm/lib/Transforms/Utils/SplitModule.cpp     | 21 +++++--------------
 4 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index baafc078039ec..09eafbd0389cb 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -136,6 +136,14 @@ filterDeadComdatFunctions(SmallVectorImpl<Function *> &DeadComdatFunctions);
 /// unique identifier for this module, so we return the empty string.
 LLVM_ABI std::string getUniqueModuleId(Module *M);
 
+/// If \p GV has local linkage, promote it to external + hidden visibility so
+/// it can be referenced across module partitions. Unnamed entities are given
+/// a stable name so they are named consistently across partitions.
+///
+/// Used by module splitting utilities (SplitModule, AMDGPUSplitModule, ...)
+/// to prepare a module for partitioning.
+LLVM_ABI void externalize(GlobalValue &GV);
+
 /// Embed the memory buffer \p Buf into the module \p M as a global using the
 /// specified section name. Also provide a metadata entry to identify it in the
 /// module using the same section name. If \p SectionExclude is true !exclude
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
index 05857d88a597c..80e246ac8eed2 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
@@ -56,6 +56,7 @@
 #include "llvm/Support/Timer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <cassert>
 #include <cmath>
 #include <utility>
@@ -164,19 +165,6 @@ static bool isNonCopyable(const Function &F) {
          AMDGPU::isEntryFunctionCC(F.getCallingConv());
 }
 
-/// If \p GV has local linkage, make it external + hidden.
-static void externalize(GlobalValue &GV) {
-  if (GV.hasLocalLinkage()) {
-    GV.setLinkage(GlobalValue::ExternalLinkage);
-    GV.setVisibility(GlobalValue::HiddenVisibility);
-  }
-
-  // Unnamed entities must be named consistently between modules. setName will
-  // give a distinct name to each such entity.
-  if (!GV.hasName())
-    GV.setName("__llvmsplit_unnamed");
-}
-
 /// Cost analysis function. Calculates the cost of each function in \p M
 ///
 /// \param GetTTI Abstract getter for TargetTransformInfo.
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 71e9c70cbf9a5..98f60873bdb7c 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -381,6 +381,18 @@ std::string llvm::getUniqueModuleId(Module *M) {
   return ("." + Str).str();
 }
 
+void llvm::externalize(GlobalValue &GV) {
+  if (GV.hasLocalLinkage()) {
+    GV.setLinkage(GlobalValue::ExternalLinkage);
+    GV.setVisibility(GlobalValue::HiddenVisibility);
+  }
+
+  // Unnamed entities must be named consistently between modules. setName will
+  // give a distinct name to each such entity.
+  if (!GV.hasName())
+    GV.setName("__llvmsplit_unnamed");
+}
+
 GlobalVariable *llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
                                           StringRef SectionName,
                                           Align Alignment,
diff --git a/llvm/lib/Transforms/Utils/SplitModule.cpp b/llvm/lib/Transforms/Utils/SplitModule.cpp
index 8e70902c4dac2..5ae3c6922e609 100644
--- a/llvm/lib/Transforms/Utils/SplitModule.cpp
+++ b/llvm/lib/Transforms/Utils/SplitModule.cpp
@@ -36,6 +36,7 @@
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
 #include <cassert>
 #include <iterator>
@@ -203,18 +204,6 @@ static void findPartitions(Module &M, ClusterIDMapType &ClusterIDMap,
   }
 }
 
-static void externalize(GlobalValue *GV) {
-  if (GV->hasLocalLinkage()) {
-    GV->setLinkage(GlobalValue::ExternalLinkage);
-    GV->setVisibility(GlobalValue::HiddenVisibility);
-  }
-
-  // Unnamed entities must be named consistently between modules. setName will
-  // give a distinct name to each such entity.
-  if (!GV->hasName())
-    GV->setName("__llvmsplit_unnamed");
-}
-
 // Returns whether GV should be in partition (0-based) I of N.
 static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) {
   if (const GlobalObject *Root = getGVPartitioningRoot(GV))
@@ -242,13 +231,13 @@ void llvm::SplitModule(
     bool PreserveLocals, bool RoundRobin) {
   if (!PreserveLocals) {
     for (Function &F : M)
-      externalize(&F);
+      externalize(F);
     for (GlobalVariable &GV : M.globals())
-      externalize(&GV);
+      externalize(GV);
     for (GlobalAlias &GA : M.aliases())
-      externalize(&GA);
+      externalize(GA);
     for (GlobalIFunc &GIF : M.ifuncs())
-      externalize(&GIF);
+      externalize(GIF);
   }
 
   // This performs splitting without a need for externalization, which might not

>From 987c41169d31dd03a333d6c5221206d1bc45dc54 Mon Sep 17 00:00:00 2001
From: maojiaping <maojiaping1 at huawei.com>
Date: Fri, 4 Sep 2026 17:35:39 +0800
Subject: [PATCH 2/3] [NFC][ModuleUtils] Rename externalize to
 externalizeGlobal

---
 llvm/include/llvm/Transforms/Utils/ModuleUtils.h | 2 +-
 llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp     | 6 +++---
 llvm/lib/Transforms/Utils/ModuleUtils.cpp        | 2 +-
 llvm/lib/Transforms/Utils/SplitModule.cpp        | 8 ++++----
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 09eafbd0389cb..5be166b7b92b9 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -142,7 +142,7 @@ LLVM_ABI std::string getUniqueModuleId(Module *M);
 ///
 /// Used by module splitting utilities (SplitModule, AMDGPUSplitModule, ...)
 /// to prepare a module for partitioning.
-LLVM_ABI void externalize(GlobalValue &GV);
+LLVM_ABI void externalizeGlobal(GlobalValue &GV);
 
 /// Embed the memory buffer \p Buf into the module \p M as a global using the
 /// specified section name. Also provide a metadata entry to identify it in the
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
index 80e246ac8eed2..71b74b00a9a33 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
@@ -1385,7 +1385,7 @@ static void splitAMDGPUModule(
       if (Fn.hasLocalLinkage() && Fn.hasAddressTaken()) {
         LLVM_DEBUG(dbgs() << "[externalize] "; Fn.printAsOperand(dbgs());
                    dbgs() << " because its address is taken\n");
-        externalize(Fn);
+        externalizeGlobal(Fn);
       }
     }
   }
@@ -1396,14 +1396,14 @@ static void splitAMDGPUModule(
     for (auto &GV : M.globals()) {
       if (GV.hasLocalLinkage())
         LLVM_DEBUG(dbgs() << "[externalize] GV " << GV.getName() << '\n');
-      externalize(GV);
+      externalizeGlobal(GV);
     }
   }
 
   for (auto &GA : M.aliases()) {
     if (GA.hasLocalLinkage()) {
       LLVM_DEBUG(dbgs() << "[externalize] alias " << GA.getName() << '\n');
-      externalize(GA);
+      externalizeGlobal(GA);
     }
   }
 
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 98f60873bdb7c..61d601f8b6aa9 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -381,7 +381,7 @@ std::string llvm::getUniqueModuleId(Module *M) {
   return ("." + Str).str();
 }
 
-void llvm::externalize(GlobalValue &GV) {
+void llvm::externalizeGlobal(GlobalValue &GV) {
   if (GV.hasLocalLinkage()) {
     GV.setLinkage(GlobalValue::ExternalLinkage);
     GV.setVisibility(GlobalValue::HiddenVisibility);
diff --git a/llvm/lib/Transforms/Utils/SplitModule.cpp b/llvm/lib/Transforms/Utils/SplitModule.cpp
index 5ae3c6922e609..7c34421fd722a 100644
--- a/llvm/lib/Transforms/Utils/SplitModule.cpp
+++ b/llvm/lib/Transforms/Utils/SplitModule.cpp
@@ -231,13 +231,13 @@ void llvm::SplitModule(
     bool PreserveLocals, bool RoundRobin) {
   if (!PreserveLocals) {
     for (Function &F : M)
-      externalize(F);
+      externalizeGlobal(F);
     for (GlobalVariable &GV : M.globals())
-      externalize(GV);
+      externalizeGlobal(GV);
     for (GlobalAlias &GA : M.aliases())
-      externalize(GA);
+      externalizeGlobal(GA);
     for (GlobalIFunc &GIF : M.ifuncs())
-      externalize(GIF);
+      externalizeGlobal(GIF);
   }
 
   // This performs splitting without a need for externalization, which might not

>From 5e1976bf364476197ce045d0f01de6d62d725801 Mon Sep 17 00:00:00 2001
From: maojiaping <maojiaping1 at huawei.com>
Date: Thu, 10 Sep 2026 20:30:02 +0800
Subject: [PATCH 3/3] [SplitModule] Move externalize helpers to
 SplitModuleCommon

Create a dedicated home for utilities shared by the module splitting
implementations, and rename __llvmsplit_unnamed to
__llvmsplit_externalize_unnamed to reflect where the name comes from.
---
 .../llvm/Transforms/Utils/ModuleUtils.h       |  8 -----
 .../llvm/Transforms/Utils/SplitModuleCommon.h | 33 +++++++++++++++++++
 llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp  |  2 +-
 llvm/lib/Transforms/Utils/CMakeLists.txt      |  1 +
 llvm/lib/Transforms/Utils/ModuleUtils.cpp     | 12 -------
 llvm/lib/Transforms/Utils/SplitModule.cpp     |  5 ++-
 .../Transforms/Utils/SplitModuleCommon.cpp    | 33 +++++++++++++++++++
 llvm/test/tools/llvm-split/unnamed.ll         | 12 +++----
 8 files changed, 76 insertions(+), 30 deletions(-)
 create mode 100644 llvm/include/llvm/Transforms/Utils/SplitModuleCommon.h
 create mode 100644 llvm/lib/Transforms/Utils/SplitModuleCommon.cpp

diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 5be166b7b92b9..baafc078039ec 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -136,14 +136,6 @@ filterDeadComdatFunctions(SmallVectorImpl<Function *> &DeadComdatFunctions);
 /// unique identifier for this module, so we return the empty string.
 LLVM_ABI std::string getUniqueModuleId(Module *M);
 
-/// If \p GV has local linkage, promote it to external + hidden visibility so
-/// it can be referenced across module partitions. Unnamed entities are given
-/// a stable name so they are named consistently across partitions.
-///
-/// Used by module splitting utilities (SplitModule, AMDGPUSplitModule, ...)
-/// to prepare a module for partitioning.
-LLVM_ABI void externalizeGlobal(GlobalValue &GV);
-
 /// Embed the memory buffer \p Buf into the module \p M as a global using the
 /// specified section name. Also provide a metadata entry to identify it in the
 /// module using the same section name. If \p SectionExclude is true !exclude
diff --git a/llvm/include/llvm/Transforms/Utils/SplitModuleCommon.h b/llvm/include/llvm/Transforms/Utils/SplitModuleCommon.h
new file mode 100644
index 0000000000000..f611717bc5a97
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/SplitModuleCommon.h
@@ -0,0 +1,33 @@
+//===----- SplitModuleCommon.h - shared module splitting helpers ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Common utilities shared by the module splitting implementations
+// (SplitModule, AMDGPUSplitModule, ...).
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SPLITMODULECOMMON_H
+#define LLVM_TRANSFORMS_UTILS_SPLITMODULECOMMON_H
+
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class GlobalValue;
+
+/// Assign a stable name to \p GV if it is unnamed, so that it is named
+/// consistently across the split partitions. setName will give a distinct
+/// name (e.g. __llvmsplit_externalize_unnamed.1) to each such entity.
+LLVM_ABI void nameUnnamedGlobalValue(GlobalValue &GV);
+
+/// If \p GV has local linkage, promote it to external + hidden visibility so
+/// it can be referenced across module partitions, and assign a stable name
+/// to unnamed entities (see nameUnnamedGlobalValue).
+LLVM_ABI void externalizeGlobal(GlobalValue &GV);
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_SPLITMODULECOMMON_H
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
index 71b74b00a9a33..5878d2c86eb6a 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
@@ -56,7 +56,7 @@
 #include "llvm/Support/Timer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/Transforms/Utils/SplitModuleCommon.h"
 #include <cassert>
 #include <cmath>
 #include <utility>
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 3b7a134b49e2e..103221325f912 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -91,6 +91,7 @@ add_llvm_component_library(LLVMTransformUtils
   SizeOpts.cpp
   SplitModule.cpp
   SplitModuleByCategory.cpp
+  SplitModuleCommon.cpp
   StripNonLineTableDebugInfo.cpp
   SymbolRewriter.cpp
   UnifyLoopExits.cpp
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 61d601f8b6aa9..71e9c70cbf9a5 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -381,18 +381,6 @@ std::string llvm::getUniqueModuleId(Module *M) {
   return ("." + Str).str();
 }
 
-void llvm::externalizeGlobal(GlobalValue &GV) {
-  if (GV.hasLocalLinkage()) {
-    GV.setLinkage(GlobalValue::ExternalLinkage);
-    GV.setVisibility(GlobalValue::HiddenVisibility);
-  }
-
-  // Unnamed entities must be named consistently between modules. setName will
-  // give a distinct name to each such entity.
-  if (!GV.hasName())
-    GV.setName("__llvmsplit_unnamed");
-}
-
 GlobalVariable *llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
                                           StringRef SectionName,
                                           Align Alignment,
diff --git a/llvm/lib/Transforms/Utils/SplitModule.cpp b/llvm/lib/Transforms/Utils/SplitModule.cpp
index 7c34421fd722a..be577b14c4660 100644
--- a/llvm/lib/Transforms/Utils/SplitModule.cpp
+++ b/llvm/lib/Transforms/Utils/SplitModule.cpp
@@ -36,7 +36,7 @@
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/Transforms/Utils/SplitModuleCommon.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
 #include <cassert>
 #include <iterator>
@@ -126,8 +126,7 @@ static void findPartitions(Module &M, ClusterIDMapType &ClusterIDMap,
     if (GV.isDeclaration())
       return;
 
-    if (!GV.hasName())
-      GV.setName("__llvmsplit_unnamed");
+    nameUnnamedGlobalValue(GV);
 
     // Comdat groups must not be partitioned. For comdat groups that contain
     // locals, record all their members here so we can keep them together.
diff --git a/llvm/lib/Transforms/Utils/SplitModuleCommon.cpp b/llvm/lib/Transforms/Utils/SplitModuleCommon.cpp
new file mode 100644
index 0000000000000..a1a10a7755d87
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/SplitModuleCommon.cpp
@@ -0,0 +1,33 @@
+//===----- SplitModuleCommon.cpp - shared module splitting helpers --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the utilities shared by the module splitting
+// implementations (SplitModule, AMDGPUSplitModule, ...).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/SplitModuleCommon.h"
+#include "llvm/IR/GlobalValue.h"
+
+using namespace llvm;
+
+void llvm::nameUnnamedGlobalValue(GlobalValue &GV) {
+  // Unnamed entities must be named consistently between modules. setName will
+  // give a distinct name to each such entity.
+  if (!GV.hasName())
+    GV.setName("__llvmsplit_externalize_unnamed");
+}
+
+void llvm::externalizeGlobal(GlobalValue &GV) {
+  if (GV.hasLocalLinkage()) {
+    GV.setLinkage(GlobalValue::ExternalLinkage);
+    GV.setVisibility(GlobalValue::HiddenVisibility);
+  }
+
+  nameUnnamedGlobalValue(GV);
+}
diff --git a/llvm/test/tools/llvm-split/unnamed.ll b/llvm/test/tools/llvm-split/unnamed.ll
index fd24b4ca92bb3..66255bd41611d 100644
--- a/llvm/test/tools/llvm-split/unnamed.ll
+++ b/llvm/test/tools/llvm-split/unnamed.ll
@@ -2,16 +2,16 @@
 ; RUN: llvm-dis -o - %t0 | FileCheck --check-prefix=CHECK0 %s
 ; RUN: llvm-dis -o - %t1 | FileCheck --check-prefix=CHECK1 %s
 
-; CHECK0: declare hidden void @__llvmsplit_unnamed()
-; CHECK1: define hidden void @__llvmsplit_unnamed()
+; CHECK0: declare hidden void @__llvmsplit_externalize_unnamed()
+; CHECK1: define hidden void @__llvmsplit_externalize_unnamed()
 define internal void @0() {
   ; CHECK1: call void @foo()
   call void @foo()
   ret void
 }
 
-; CHECK0: declare hidden void @__llvmsplit_unnamed.1()
-; CHECK1: define hidden void @__llvmsplit_unnamed.1()
+; CHECK0: declare hidden void @__llvmsplit_externalize_unnamed.1()
+; CHECK1: define hidden void @__llvmsplit_externalize_unnamed.1()
 define internal void @1() {
   ; CHECK1: call void @foo()
   ; CHECK1: call void @foo()
@@ -23,8 +23,8 @@ define internal void @1() {
 ; CHECK0: define void @foo()
 ; CHECK1: declare void @foo()
 define void @foo() {
-  ; CHECK0: call void @__llvmsplit_unnamed.1()
-  ; CHECK0: call void @__llvmsplit_unnamed()
+  ; CHECK0: call void @__llvmsplit_externalize_unnamed.1()
+  ; CHECK0: call void @__llvmsplit_externalize_unnamed()
   call void @1()
   call void @0()
   ret void



More information about the llvm-commits mailing list