diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1e273c1b7ce46..ded58a369c7a0 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 `_) +- For function multi-versioning using the ``target`` or ``target_clones`` + attributes, remove comdat for internal linkage functions. + (`#65114 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 21e1363b613e0..f27fc019ccc53 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 5da9548067831..98ffea40f56d8 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 261ce51476311..301cb704f2031 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()