[PATCH] D158963: [CodeGen] Function multi-versioning: don't set comdat for internal linkage resolvers

Fangrui Song via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 27 22:02:32 PDT 2023


MaskRay created this revision.
MaskRay added reviewers: erichkeane, ilinpv, pengfei, RKSimon.
Herald added a project: All.
MaskRay requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

For function multi-versioning using the target and target_clones
function attributes, currently we incorrectly set comdat for internal
linkage functions. 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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158963

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGen/attr-target-clones.c
  clang/test/CodeGen/attr-target-mv.c


Index: clang/test/CodeGen/attr-target-mv.c
===================================================================
--- clang/test/CodeGen/attr-target-mv.c
+++ clang/test/CodeGen/attr-target-mv.c
@@ -32,6 +32,13 @@
   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 @@
 
 
 // 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 @@
 // 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()
 
Index: clang/test/CodeGen/attr-target-clones.c
===================================================================
--- clang/test/CodeGen/attr-target-clones.c
+++ 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 @@
 
 // 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"
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4059,7 +4059,7 @@
 
     ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
 
-    if (supportsCOMDAT())
+    if (!ResolverFunc->hasLocalLinkage() && supportsCOMDAT())
       ResolverFunc->setComdat(
           getModule().getOrInsertComdat(ResolverFunc->getName()));
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D158963.553837.patch
Type: text/x-patch
Size: 3689 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230828/78829a7c/attachment.bin>


More information about the cfe-commits mailing list