[llvm] [ThinLTO] Reduce the number of renaming due to promotions in distribu… (PR #188074)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 18 08:31:30 PDT 2026
https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/188074
>From 41ea9015cb2657be28283dc7042eaf84c94fa5ef Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Sun, 22 Mar 2026 11:47:16 -0700
Subject: [PATCH 1/2] [ThinLTO] Reduce the number of renaming due to promotions
in distributed mode
For thin-lto, the pull request [1] reduced the number of renaming due to
promotions in process mode. This has been used in linux kernel ([2]) as
it helps kernel live patching a lot.
Recently, I found Rong Xu has added thin-lto distributed mode support in
linux kenrel ([3]) and it is likely to be merged in kernel as well.
So it would be a good idea for llvm to support reducing the number of
renaming in distributed mode too.
To implement this, in function gatherImportedSummariesForModule(),
import functions into summaries if those functions does not need rename.
This will ensure that imported functions have the same name as in there
original module.
[1] https://github.com/llvm/llvm-project/pull/183793
[2] https://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux.git/commit/?h=kbuild-for-next&id=dc3b90751d6ffa8865e09a81645a539b9de6d642
[3] https://lore.kernel.org/linux-kbuild/20251028182822.3210436-3-xur@google.com/
---
llvm/lib/Transforms/IPO/FunctionImport.cpp | 17 +++++
.../X86/reduce-promotion-distributed.ll | 56 +++++++++++++++
...e-promotion-same-local-name-distributed.ll | 70 +++++++++++++++++++
3 files changed, 143 insertions(+)
create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 82fbab5e1857f..3b913ea3e5a48 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -1607,6 +1607,23 @@ void llvm::gatherImportedSummariesForModule(
SummariesForIndex[GUID] = DS->second;
}
+
+ // For each source module we import from, also include summaries for local
+ // functions that have NoRenameOnPromotion set. This is needed for distributed
+ // ThinLTO. Otherwise, the local funciton of the source module will keep its
+ // origin name, e.g., foo() while the function in destination module will have
+ // name foo.llvm.<...>() and this will cause a link failure.
+ for (auto &[ModPath, SummariesForIndex] : ModuleToSummariesForIndex) {
+ if (ModPath == ModulePath)
+ continue;
+ auto It = ModuleToDefinedGVSummaries.find(ModPath);
+ if (It == ModuleToDefinedGVSummaries.end())
+ continue;
+ for (const auto &[GUID, Summary] : It->second) {
+ if (Summary->noRenameOnPromotion())
+ SummariesForIndex.try_emplace(GUID, Summary);
+ }
+ }
}
/// Emit the files \p ModulePath will import from into \p OutputFilename.
diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll b/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
new file mode 100644
index 0000000000000..6b1d5c52d9cf2
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
@@ -0,0 +1,56 @@
+; This is to test the support for avoiding always renaming in distributed mode.
+
+; RUN: rm -rf %t
+; RUN: mkdir -p %t
+; RUN: split-file %s %t
+
+; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc
+; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc
+;
+; RUN: llvm-lto2 run %t/a.bc %t/b.bc \
+; RUN: -thinlto-distributed-indexes \
+; RUN: --whole-program-visibility-enabled-in-lto=true \
+; RUN: -always-rename-promoted-locals=false \
+; RUN: -save-temps -o %t/lto-out \
+; RUN: -r %t/a.bc,m1,px \
+; RUN: -r %t/b.bc,m2,p \
+; RUN: -r %t/a.bc,m2,x
+
+; RUN: opt -passes=function-import -always-rename-promoted-locals=false -import-all-index -enable-import-metadata -summary-file %t/a.bc.thinlto.bc %t/a.bc -o %t/a.bc.out
+; RUN: opt -passes=function-import -always-rename-promoted-locals=false -import-all-index -summary-file %t/b.bc.thinlto.bc %t/b.bc -o %t/b.bc.out
+; RUN: llvm-dis %t/a.bc.out -o - | FileCheck %s --check-prefix=CHECK-A
+; RUN: llvm-dis %t/b.bc.out -o - | FileCheck %s --check-prefix=CHECK-B
+
+; CHECK-A: define available_externally hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+; CHECK-B: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+
+;--- a.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr {
+ %2 = tail call i32 @m2(i32 noundef %0)
+ ret i32 %2
+}
+
+declare i32 @m2(i32 noundef) local_unnamed_addr
+
+;--- b.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr {
+ %2 = tail call fastcc i32 @foo(i32 noundef %0)
+ %3 = shl nsw i32 %0, 1
+ %4 = tail call fastcc i32 @foo(i32 noundef %3)
+ %5 = add nsw i32 %4, %2
+ ret i32 %5
+}
+
+define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 {
+ %2 = add nsw i32 %0, 5
+ %3 = sdiv i32 %2, %0
+ ret i32 %3
+}
+
+attributes #1 = { noinline }
diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
new file mode 100644
index 0000000000000..817c89ae398b7
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
@@ -0,0 +1,70 @@
+; This is to test the support for avoiding always renaming in distributed mode,
+; and ensure that one copy is still renamed despite having different GUIDs.
+
+; RUN: rm -rf %t
+; RUN: mkdir -p %t
+; RUN: split-file %s %t
+
+; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc
+; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc
+;
+; RUN: llvm-lto2 run %t/a.bc %t/b.bc \
+; RUN: -thinlto-distributed-indexes \
+; RUN: --whole-program-visibility-enabled-in-lto=true \
+; RUN: -always-rename-promoted-locals=false \
+; RUN: -save-temps -o %t/lto-out \
+; RUN: -r %t/a.bc,m1,px \
+; RUN: -r %t/b.bc,m2,p \
+; RUN: -r %t/a.bc,m2,x
+
+; RUN: opt -passes=function-import -always-rename-promoted-locals=false -import-all-index -enable-import-metadata -summary-file %t/a.bc.thinlto.bc %t/a.bc -o %t/a.bc.out
+; RUN: opt -passes=function-import -always-rename-promoted-locals=false -import-all-index -summary-file %t/b.bc.thinlto.bc %t/b.bc -o %t/b.bc.out
+; RUN: llvm-dis %t/a.bc.out -o - | FileCheck %s --check-prefix=CHECK-A
+; RUN: llvm-dis %t/b.bc.out -o - | FileCheck %s --check-prefix=CHECK-B
+
+; CHECK-A: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo.llvm.
+; CHECK-A: define available_externally hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+; CHECK-B: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+
+;--- a.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr {
+ %2 = shl nsw i32 %0, 1
+ %3 = tail call fastcc i32 @foo(i32 noundef %2)
+ %4 = tail call i32 @m2(i32 noundef %0)
+ %5 = add nsw i32 %4, %3
+ ret i32 %5
+}
+
+define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 {
+ %2 = add nsw i32 %0, 5
+ %3 = sdiv i32 %2, %0
+ ret i32 %3
+}
+
+declare i32 @m2(i32 noundef) local_unnamed_addr
+
+attributes #1 = { noinline }
+
+;--- b.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
+define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr {
+ %2 = tail call fastcc i32 @foo(i32 noundef %0)
+ %3 = shl nsw i32 %0, 1
+ %4 = tail call fastcc i32 @foo(i32 noundef %3)
+ %5 = add nsw i32 %4, %2
+ ret i32 %5
+}
+
+define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 {
+ %2 = add nsw i32 %0, 5
+ %3 = sdiv i32 %2, %0
+ ret i32 %3
+}
+
+attributes #1 = { noinline }
>From a1f3887b4453dec4122118f25cbae7d21525d33d Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Fri, 17 Apr 2026 22:59:36 -0700
Subject: [PATCH 2/2] import as declaration and add summary assertions
---
llvm/lib/Transforms/IPO/FunctionImport.cpp | 4 +++-
llvm/lib/Transforms/Utils/FunctionImportUtils.cpp | 4 ++++
llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll | 2 +-
.../X86/reduce-promotion-same-local-name-distributed.ll | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 3b913ea3e5a48..8ac69b6dad8c8 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -1620,8 +1620,10 @@ void llvm::gatherImportedSummariesForModule(
if (It == ModuleToDefinedGVSummaries.end())
continue;
for (const auto &[GUID, Summary] : It->second) {
- if (Summary->noRenameOnPromotion())
+ if (Summary->noRenameOnPromotion()) {
+ DecSummaries.insert(Summary);
SummariesForIndex.try_emplace(GUID, Summary);
+ }
}
}
}
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 475699c42b21e..e73a83c5c1132 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -317,6 +317,10 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
Summary = ImportIndex.findSummaryInModule(
VI, GV.getParent()->getModuleIdentifier());
+ assert((!Summary || !Summary->noRenameOnPromotion() ||
+ shouldPromoteLocalToGlobal(&GV, Summary)) &&
+ "noRenameOnPromotion requires promotion to external linkage");
+
if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, Summary)) {
// Save the original name string before we rename GV below.
auto Name = GV.getName().str();
diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll b/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
index 6b1d5c52d9cf2..f609dee378a6d 100644
--- a/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
+++ b/llvm/test/ThinLTO/X86/reduce-promotion-distributed.ll
@@ -21,7 +21,7 @@
; RUN: llvm-dis %t/a.bc.out -o - | FileCheck %s --check-prefix=CHECK-A
; RUN: llvm-dis %t/b.bc.out -o - | FileCheck %s --check-prefix=CHECK-B
-; CHECK-A: define available_externally hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+; CHECK-A: declare hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
; CHECK-B: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
;--- a.ll
diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
index 817c89ae398b7..5f8cd9ed3bbee 100644
--- a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
+++ b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name-distributed.ll
@@ -23,7 +23,7 @@
; RUN: llvm-dis %t/b.bc.out -o - | FileCheck %s --check-prefix=CHECK-B
; CHECK-A: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo.llvm.
-; CHECK-A: define available_externally hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
+; CHECK-A: declare hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
; CHECK-B: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo(
;--- a.ll
More information about the llvm-commits
mailing list