diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index acf6e4d63cc3..fb16c8f2607d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2185,6 +2185,9 @@ void CodeGenModule::emitMultiVersionFunctions() { llvm::Function *ResolverFunc = cast( GetGlobalValue((getMangledName(GD) + ".resolver").str())); + if (supportsCOMDAT()) + ResolverFunc->setComdat( + getModule().getOrInsertComdat(ResolverFunc->getName())); std::stable_sort( Options.begin(), Options.end(), std::greater()); diff --git a/clang/test/CodeGen/attr-target-mv-va-args.c b/clang/test/CodeGen/attr-target-mv-va-args.c index c5d92dbfadc1..b33f841dba5e 100644 --- a/clang/test/CodeGen/attr-target-mv-va-args.c +++ b/clang/test/CodeGen/attr-target-mv-va-args.c @@ -18,7 +18,7 @@ int bar() { // CHECK: define i32 @bar() // CHECK: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double // CHECK: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds -// CHECK: define i32 (i32, ...)* @foo.resolver() +// CHECK: define i32 (i32, ...)* @foo.resolver() comdat // CHECK: ret i32 (i32, ...)* @foo.arch_sandybridge // CHECK: ret i32 (i32, ...)* @foo.arch_ivybridge // CHECK: ret i32 (i32, ...)* @foo.sse4.2 diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c index a877fd6e8d44..ca3d7d297161 100644 --- a/clang/test/CodeGen/attr-target-mv.c +++ b/clang/test/CodeGen/attr-target-mv.c @@ -38,7 +38,7 @@ inline __attribute__((target("sse4.2"))) void foo_decls(void) {} // CHECK: define i32 @bar() // CHECK: call i32 @foo.ifunc() -// CHECK: define i32 ()* @foo.resolver() +// CHECK: define i32 ()* @foo.resolver() comdat // CHECK: call void @__cpu_indicator_init() // CHECK: ret i32 ()* @foo.arch_sandybridge // CHECK: ret i32 ()* @foo.arch_ivybridge @@ -48,7 +48,7 @@ inline __attribute__((target("sse4.2"))) void foo_decls(void) {} // CHECK: define i32 @bar2() // CHECK: call i32 @foo_inline.ifunc() -// CHECK: define i32 ()* @foo_inline.resolver() +// CHECK: define i32 ()* @foo_inline.resolver() comdat // CHECK: call void @__cpu_indicator_init() // CHECK: ret i32 ()* @foo_inline.arch_sandybridge // CHECK: ret i32 ()* @foo_inline.arch_ivybridge @@ -58,7 +58,7 @@ inline __attribute__((target("sse4.2"))) void foo_decls(void) {} // CHECK: define void @bar3() // CHECK: call void @foo_decls.ifunc() -// CHECK: define void ()* @foo_decls.resolver() +// CHECK: define void ()* @foo_decls.resolver() comdat // CHECK: ret void ()* @foo_decls.sse4.2 // CHECK: ret void ()* @foo_decls diff --git a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp index 1852750e4695..4dc2b67b4644 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp @@ -38,13 +38,13 @@ int bar() { // CHECK: call i32 @_Z3fooi.ifunc(i32 1) // CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2) -// CHECK: define i32 (i32)* @_Z3fooi.resolver() +// CHECK: define i32 (i32)* @_Z3fooi.resolver() comdat // CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge // CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge // CHECK: ret i32 (i32)* @_Z3fooi.sse4.2 // CHECK: ret i32 (i32)* @_Z3fooi // -// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() +// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat // CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge // CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge // CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2 diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp index 2c201c5d5297..2e5db3b705e4 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -81,15 +81,15 @@ int templ_use() { // CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 // CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) -// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() +// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat // CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge // CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_ -// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() +// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat // CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge // CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv -// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 @@ -97,7 +97,7 @@ int templ_use() { // CHECK: define i32 @_Z4bar2v() // CHECK:call i32 @_ZN2S23fooEi.ifunc -// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() +// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat // CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge // CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge // CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2 @@ -112,13 +112,13 @@ int templ_use() { // CHECK: call i32 @_ZN5templIdE3fooEi.ifunc -// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() +// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi // -// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() +// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2 diff --git a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp index 7072dec5031c..63353c12d29a 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp @@ -30,7 +30,7 @@ int bar() { // CHECK: %s = alloca %struct.S, align 1 // CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) -// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 diff --git a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp index a1b12c304e10..c72ea77fa46f 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp @@ -34,13 +34,13 @@ int bar2() { // CHECK: call i32 @_Z12foo_overloadv.ifunc() // CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1) -// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() +// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() comdat // CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge // CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge // CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2 // CHECK: ret i32 ()* @_Z12foo_overloadv -// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() +// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat // CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge // CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge // CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2