[llvm] [AMDGPU] Fix alias handling in module splitting functionality (PR #187295)

Joseph Huber via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 18 08:11:27 PDT 2026


https://github.com/jhuber6 created https://github.com/llvm/llvm-project/pull/187295

Summary:
The module splitting used for `-flto-partitions=8` support (which is
passed by default) did not correctly handle aliases. We mainly need to
do two things: keep the aliases in the they are used in and externalize
them. Internalize linkage needs to be handled conservatively.

This is needed because these aliases show up in PGO contexts.


>From 396b70778a849b11c8f7e35d20d423bcdee0641a Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Wed, 18 Mar 2026 10:04:18 -0500
Subject: [PATCH] [AMDGPU] Fix alias handling in module splitting functionality

Summary:
The module splitting used for `-flto-partitions=8` support (which is
passed by default) did not correctly handle aliases. We mainly need to
do two things: keep the aliases in the they are used in and externalize
them. Internalize linkage needs to be handled conservatively.

This is needed because these aliases show up in PGO contexts.
---
 llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp  | 22 ++++++++++++++-----
 .../llvm-split/AMDGPU/kernels-dependencies.ll | 11 ++++++++--
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
index c155d85df1769..105ce9a245f5c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp
@@ -43,6 +43,7 @@
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalAlias.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Module.h"
@@ -1285,7 +1286,9 @@ namespace {
 static bool needsConservativeImport(const GlobalValue *GV) {
   if (const auto *Var = dyn_cast<GlobalVariable>(GV))
     return Var->hasLocalLinkage();
-  return isa<GlobalAlias>(GV);
+  if (const auto *GA = dyn_cast<GlobalAlias>(GV))
+    return GA->hasLocalLinkage();
+  return false;
 }
 
 /// Prints a summary of the partition \p N, represented by module \p M, to \p
@@ -1394,8 +1397,6 @@ static void splitAMDGPUModule(
   // visible copy, then internalize all other copies" for some functions?
   if (!NoExternalizeOnAddrTaken) {
     for (auto &Fn : M) {
-      // TODO: Should aliases count? Probably not but they're so rare I'm not
-      // sure it's worth fixing.
       if (Fn.hasLocalLinkage() && Fn.hasAddressTaken()) {
         LLVM_DEBUG(dbgs() << "[externalize] "; Fn.printAsOperand(dbgs());
                    dbgs() << " because its address is taken\n");
@@ -1414,6 +1415,13 @@ static void splitAMDGPUModule(
     }
   }
 
+  for (auto &GA : M.aliases()) {
+    if (GA.hasLocalLinkage()) {
+      LLVM_DEBUG(dbgs() << "[externalize] alias " << GA.getName() << '\n');
+      externalize(GA);
+    }
+  }
+
   // Start by calculating the cost of every function in the module, as well as
   // the module's overall cost.
   FunctionsCostMap FnCosts;
@@ -1510,15 +1518,17 @@ static void splitAMDGPUModule(
             return false;
           }
 
+          // Aliases should not be separated from their underlying object.
+          if (const auto *GA = dyn_cast<GlobalAlias>(GV))
+            if (const auto *Fn = dyn_cast<Function>(GA->getAliaseeObject()))
+              return FnsInPart.contains(Fn);
+
           // Everything else goes in the first non-empty module we create.
           return ImportAllGVs || needsConservativeImport(GV);
         }));
 
     ImportAllGVs = false;
 
-    // FIXME: Aliases aren't seen often, and their handling isn't perfect so
-    // bugs are possible.
-
     // Clean-up conservatively imported GVs without any users.
     for (auto &GV : make_early_inc_range(MPart->global_values())) {
       if (needsConservativeImport(&GV) && GV.use_empty())
diff --git a/llvm/test/tools/llvm-split/AMDGPU/kernels-dependencies.ll b/llvm/test/tools/llvm-split/AMDGPU/kernels-dependencies.ll
index bea527f15bbaa..2e555ad0266eb 100644
--- a/llvm/test/tools/llvm-split/AMDGPU/kernels-dependencies.ll
+++ b/llvm/test/tools/llvm-split/AMDGPU/kernels-dependencies.ll
@@ -4,23 +4,30 @@
 ; RUN: llvm-dis -o - %t2 | FileCheck --check-prefix=CHECK2 %s
 
 ; 3 kernels with each their own dependencies should go into 3
-; distinct partitions.
+; distinct partitions. Aliases should follow their aliasee's partition
+; and not be cleaned up even if unused in that partition.
 
+; CHECK0-NOT: @HelperA_alias = {{.*}}alias
 ; CHECK0-NOT: define
 ; CHECK0: define amdgpu_kernel void @C
 ; CHECK0: define internal void @HelperC
+; CHECK0-NOT: @HelperA_alias = {{.*}}alias
 ; CHECK0-NOT: define
 
+; CHECK1-NOT: @HelperA_alias = {{.*}}alias
 ; CHECK1-NOT: define
 ; CHECK1: define amdgpu_kernel void @B
 ; CHECK1: define internal void @HelperB
+; CHECK1-NOT: @HelperA_alias = {{.*}}alias
 ; CHECK1-NOT: define
 
+; CHECK2: @HelperA_alias = hidden alias void (), ptr @HelperA
 ; CHECK2-NOT: define
 ; CHECK2: define amdgpu_kernel void @A
-; CHECK2: define internal void @HelperA
+; CHECK2: define hidden void @HelperA
 ; CHECK2-NOT: define
 
+ at HelperA_alias = internal alias void (), ptr @HelperA
 
 define amdgpu_kernel void @A() {
   call void @HelperA()



More information about the llvm-commits mailing list