[clang] 651b2fb - [CodeGen] Function multi-versioning: don't set comdat for internal linkage resolvers
Fangrui Song via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 30 09:47:04 PDT 2023
Author: Fangrui Song
Date: 2023-08-30T09:46:48-07:00
New Revision: 651b2fbc1c7ec4992d2c80b8456c5c5a72394caf
URL: https://github.com/llvm/llvm-project/commit/651b2fbc1c7ec4992d2c80b8456c5c5a72394caf
DIFF: https://github.com/llvm/llvm-project/commit/651b2fbc1c7ec4992d2c80b8456c5c5a72394caf.diff
LOG: [CodeGen] Function multi-versioning: don't set comdat for internal linkage resolvers
For function multi-versioning using the target or target_clones
function attributes, currently we incorrectly set comdat for internal
linkage resolvers. This is problematic for ELF linkers
as GRP_COMDAT deduplication will kick in even with STB_LOCAL signature
(https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc
"GRP_COMDAT group with STB_LOCAL signature").
In short, two `__attribute((target_clones(...))) static void foo()`
in two translation units will be deduplicated. Fix this.
Fix #65114
Reviewed By: erichkeane
Differential Revision: https://reviews.llvm.org/D158963
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/attr-target-clones.c
clang/test/CodeGen/attr-target-mv.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1e273c1b7ce46a..ded58a369c7a03 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -205,6 +205,9 @@ Bug Fixes in This Version
- Clang's ``-Wunused-private-field`` no longer warns on fields whose type is
declared with ``[[maybe_unused]]``.
(`#61334 <https://github.com/llvm/llvm-project/issues/61334>`_)
+- For function multi-versioning using the ``target`` or ``target_clones``
+ attributes, remove comdat for internal linkage functions.
+ (`#65114 <https://github.com/llvm/llvm-project/issues/65114>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 21e1363b613e0e..f27fc019ccc53e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4052,7 +4052,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
- if (supportsCOMDAT())
+ if (!ResolverFunc->hasLocalLinkage() && supportsCOMDAT())
ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName()));
diff --git a/clang/test/CodeGen/attr-target-clones.c b/clang/test/CodeGen/attr-target-clones.c
index 5da9548067831a..98ffea40f56d88 100644
--- a/clang/test/CodeGen/attr-target-clones.c
+++ b/clang/test/CodeGen/attr-target-clones.c
@@ -16,6 +16,7 @@
// LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
// LINUX: @__cpu_features2 = external dso_local global [3 x i32]
+// LINUX: @internal.ifunc = internal ifunc i32 (), ptr @internal.resolver
// LINUX: @foo.ifunc = weak_odr ifunc i32 (), ptr @foo.resolver
// LINUX: @foo_dupes.ifunc = weak_odr ifunc void (), ptr @foo_dupes.resolver
// LINUX: @unused.ifunc = weak_odr ifunc void (), ptr @unused.resolver
@@ -23,6 +24,12 @@
// LINUX: @foo_inline2.ifunc = weak_odr ifunc i32 (), ptr @foo_inline2.resolver
// LINUX: @foo_used_no_defn.ifunc = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver
+static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }
+int use(void) { return internal(); }
+/// Internal linkage resolvers do not use comdat.
+// LINUX: define internal ptr @internal.resolver() {
+// WINDOWS: define internal i32 @internal() {
+
int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
// LINUX: define {{.*}}i32 @foo.sse4.2.0()
// LINUX: define {{.*}}i32 @foo.default.1()
@@ -192,7 +199,5 @@ int isa_level(int) { return 0; }
// CHECK: attributes #[[SSE42]] =
// CHECK-SAME: "target-features"="+crc32,+cx8,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87"
-// CHECK: attributes #[[DEF]] =
-// Don't bother checking features, we verified it is the same as a normal function.
// CHECK: attributes #[[SB]] =
// CHECK-SAME: "target-features"="+avx,+cmov,+crc32,+cx16,+cx8,+fxsr,+mmx,+pclmul,+popcnt,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c
index 261ce514763113..301cb704f20316 100644
--- a/clang/test/CodeGen/attr-target-mv.c
+++ b/clang/test/CodeGen/attr-target-mv.c
@@ -32,6 +32,13 @@ int bar(void) {
return foo();
}
+static int __attribute__((target("arch=meteorlake"))) foo_internal(void) {return 15;}
+static int __attribute__((target("default"))) foo_internal(void) { return 2; }
+
+int bar1(void) {
+ return foo_internal();
+}
+
inline int __attribute__((target("sse4.2"))) foo_inline(void) { return 0; }
inline int __attribute__((target("arch=sandybridge"))) foo_inline(void);
inline int __attribute__((target("arch=ivybridge"))) foo_inline(void) {return 1;}
@@ -128,6 +135,7 @@ void calls_pr50025c(void) { pr50025c(); }
// LINUX: @foo.ifunc = weak_odr ifunc i32 (), ptr @foo.resolver
+// LINUX: @foo_internal.ifunc = internal ifunc i32 (), ptr @foo_internal.resolver
// LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), ptr @foo_inline.resolver
// LINUX: @foo_decls.ifunc = weak_odr ifunc void (), ptr @foo_decls.resolver
// LINUX: @foo_multi.ifunc = weak_odr ifunc void (i32, double), ptr @foo_multi.resolver
@@ -254,6 +262,11 @@ void calls_pr50025c(void) { pr50025c(); }
// WINDOWS: call i32 @foo.sse4.2
// WINDOWS: call i32 @foo
+/// Internal linkage resolvers do not use comdat.
+// LINUX: define internal ptr @foo_internal.resolver() {
+
+// WINDOWS: define internal i32 @foo_internal.resolver() {
+
// LINUX: define{{.*}} i32 @bar2()
// LINUX: call i32 @foo_inline.ifunc()
More information about the cfe-commits
mailing list