[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