From 7ef210d0531eb74c45d5f16ddd3ca48e87b601db Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 22 Oct 2018 21:20:45 +0000 Subject: [PATCH] Give Multiversion-inline functions linkonce linkage Since multiversion variant functions can be inline, in C they become available-externally linkage. This ends up causing the variants to not be emitted, and not available to the linker. The solution is to make sure that multiversion functions are always emitted by marking them linkonce. Change-Id: I897aa37c7cbba0c1eb2c57ee881d5000a2113b75 llvm-svn: 344957 --- clang/lib/CodeGen/CodeGenModule.cpp | 4 ++++ clang/test/CodeGen/attr-target-mv.c | 16 ++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c8aea635a7e7..c8e672a56728 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3669,6 +3669,10 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( return llvm::GlobalVariable::WeakAnyLinkage; } + if (const auto *FD = D->getAsFunction()) + if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally) + return llvm::GlobalVariable::LinkOnceAnyLinkage; + // We are guaranteed to have a strong definition somewhere else, // so we can use available_externally linkage. if (Linkage == GVA_AvailableExternally) diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c index 48e155835697..3ccb5b319954 100644 --- a/clang/test/CodeGen/attr-target-mv.c +++ b/clang/test/CodeGen/attr-target-mv.c @@ -88,19 +88,19 @@ void bar4() { // CHECK: declare i32 @foo.arch_sandybridge() -// CHECK: define available_externally i32 @foo_inline.sse4.2() +// CHECK: define linkonce i32 @foo_inline.sse4.2() // CHECK: ret i32 0 // CHECK: declare i32 @foo_inline.arch_sandybridge() // -// CHECK: define available_externally i32 @foo_inline.arch_ivybridge() +// CHECK: define linkonce i32 @foo_inline.arch_ivybridge() // CHECK: ret i32 1 -// CHECK: define available_externally i32 @foo_inline() +// CHECK: define linkonce i32 @foo_inline() // CHECK: ret i32 2 -// CHECK: define available_externally void @foo_decls() -// CHECK: define available_externally void @foo_decls.sse4.2() +// CHECK: define linkonce void @foo_decls() +// CHECK: define linkonce void @foo_decls.sse4.2() -// CHECK: define available_externally void @foo_multi.avx_sse4.2() -// CHECK: define available_externally void @foo_multi.fma4_sse4.2() -// CHECK: define available_externally void @foo_multi.arch_ivybridge_fma4_sse4.2() +// CHECK: define linkonce void @foo_multi.avx_sse4.2() +// CHECK: define linkonce void @foo_multi.fma4_sse4.2() +// CHECK: define linkonce void @foo_multi.arch_ivybridge_fma4_sse4.2()