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()));
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()));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits