[llvm] [CloneModule] Clone ifunc by ShouldCloneDefinition (PR #197183)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 12 06:03:46 PDT 2026
https://github.com/weg0818 created https://github.com/llvm/llvm-project/pull/197183
None
>From 2b9c865bcef8405fc5a0c405ba28206e83603d5d Mon Sep 17 00:00:00 2001
From: maojiaping <maojiaping1 at huawei.com>
Date: Tue, 12 May 2026 20:58:04 +0800
Subject: [PATCH] [CloneModule] Clone ifunc by ShouldCloneDefinition
---
llvm/lib/Transforms/Utils/CloneModule.cpp | 19 +++++++++++++
llvm/test/tools/llvm-split/ifunc.ll | 34 +++++++++++++++++++++++
2 files changed, 53 insertions(+)
create mode 100644 llvm/test/tools/llvm-split/ifunc.ll
diff --git a/llvm/lib/Transforms/Utils/CloneModule.cpp b/llvm/lib/Transforms/Utils/CloneModule.cpp
index bb638f180bfbf..e1966aa39eb17 100644
--- a/llvm/lib/Transforms/Utils/CloneModule.cpp
+++ b/llvm/lib/Transforms/Utils/CloneModule.cpp
@@ -117,6 +117,22 @@ std::unique_ptr<Module> llvm::CloneModule(
for (const GlobalIFunc &I : M.ifuncs()) {
// Defer setting the resolver function until after functions are cloned.
+ if (!ShouldCloneDefinition(&I)) {
+ // An ifunc also cannot act as an external reference, so we need to create
+ // either a function or a global variable depending on the value type.
+ GlobalValue *GV;
+ if (I.getValueType()->isFunctionTy())
+ GV = Function::Create(cast<FunctionType>(I.getValueType()),
+ GlobalValue::ExternalLinkage, I.getAddressSpace(),
+ I.getName(), New.get());
+ else
+ GV = new GlobalVariable(*New, I.getValueType(), false,
+ GlobalValue::ExternalLinkage, nullptr,
+ I.getName(), nullptr, I.getThreadLocalMode(),
+ I.getType()->getAddressSpace());
+ VMap[&I] = GV;
+ continue;
+ }
auto *GI =
GlobalIFunc::create(I.getValueType(), I.getAddressSpace(),
I.getLinkage(), I.getName(), nullptr, New.get());
@@ -174,6 +190,9 @@ std::unique_ptr<Module> llvm::CloneModule(
}
for (const GlobalIFunc &I : M.ifuncs()) {
+ // We already dealt with undefined ifuncs above.
+ if (!ShouldCloneDefinition(&I))
+ continue;
GlobalIFunc *GI = cast<GlobalIFunc>(VMap[&I]);
if (const Constant *Resolver = I.getResolver())
GI->setResolver(MapValue(Resolver, VMap));
diff --git a/llvm/test/tools/llvm-split/ifunc.ll b/llvm/test/tools/llvm-split/ifunc.ll
new file mode 100644
index 0000000000000..fc6414d81499b
--- /dev/null
+++ b/llvm/test/tools/llvm-split/ifunc.ll
@@ -0,0 +1,34 @@
+; RUN: llvm-split -j2 -o %t %s
+; RUN: llvm-dis -o - %t0 | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-dis -o - %t1 | FileCheck --check-prefix=CHECK1 %s
+
+
+; CHECK0-DAG: declare void @foo_a.ifunc()
+; CHECK1-DAG: @foo_a.ifunc = ifunc void (), ptr @foo_a.resolver
+
+ at foo_a.ifunc = ifunc void (), ptr @foo_a.resolver
+
+; CHECK0-DAG: define hidden void @foo.impl()
+; CHECK1-DAG: declare hidden void @foo.impl()
+
+define internal void @foo.impl() {
+entry:
+ ret void
+}
+
+; CHECK0-DAG: declare hidden ptr @foo_a.resolver()
+; CHECK1-DAG: define hidden ptr @foo_a.resolver()
+
+define internal ptr @foo_a.resolver() {
+entry:
+ ret ptr @foo.impl
+}
+
+; CHECK0-DAG: declare void @bar_a()
+; CHECK1-DAG: define void @bar_a()
+
+define void @bar_a() {
+entry:
+ call void @foo_a.ifunc()
+ ret void
+}
\ No newline at end of file
More information about the llvm-commits
mailing list