Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -4053,8 +4053,20 @@ } llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); - if (auto *IFunc = dyn_cast(ResolverConstant)) + if (auto *IFunc = dyn_cast(ResolverConstant)) { ResolverConstant = IFunc->getResolver(); + if (FD->isTargetClonesMultiVersion()) { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); + std::string MangledName = getMangledNameImpl( + *this, GD, FD, /*OmitMultiVersionMangling=*/true); + auto *Alias = + llvm::GlobalAlias::create(DeclTy, 0, llvm::Function::WeakODRLinkage, + MangledName, IFunc, &getModule()); + SetCommonAttributes(FD, Alias); + } + } + llvm::Function *ResolverFunc = cast(ResolverConstant); ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD)); Index: clang/test/CodeGen/attr-target-clones.c =================================================================== --- clang/test/CodeGen/attr-target-clones.c +++ clang/test/CodeGen/attr-target-clones.c @@ -13,6 +13,13 @@ // WINDOWS: $foo_inline = comdat any // WINDOWS: $foo_inline2 = comdat any +// LINUX: @foo = weak_odr alias i32 (), ptr @foo.ifunc +// LINUX: @foo_dupes = weak_odr alias void (), ptr @foo_dupes.ifunc +// LINUX: @unused = weak_odr alias void (), ptr @unused.ifunc +// LINUX: @foo_inline = weak_odr alias i32 (), ptr @foo_inline.ifunc +// LINUX: @foo_inline2 = weak_odr alias i32 (), ptr @foo_inline2.ifunc +// LINUX: @foo_used_no_defn = weak_odr alias i32 (), ptr @foo_used_no_defn.ifunc + // 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 Index: clang/test/CodeGenCXX/attr-target-clones.cpp =================================================================== --- clang/test/CodeGenCXX/attr-target-clones.cpp +++ clang/test/CodeGenCXX/attr-target-clones.cpp @@ -1,6 +1,13 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS +// Alias for ifunc +// LINUX: @_Z10overloadedi = weak_odr alias i32 (i32), ptr @_Z10overloadedi.ifunc +// LINUX: @_Z10overloadedPKc = weak_odr alias i32 (ptr), ptr @_Z10overloadedPKc.ifunc +// LINUX: @_ZN1CIssE3fooEv = weak_odr alias i32 (ptr), ptr @_ZN1CIssE3fooEv.ifunc +// LINUX: @_ZN1CIisE3fooEv = weak_odr alias i32 (ptr), ptr @_ZN1CIisE3fooEv.ifunc +// LINUX: @_ZN1CIdfE3fooEv = weak_odr alias i32 (ptr), ptr @_ZN1CIdfE3fooEv.ifunc + // Overloaded ifuncs // LINUX: @_Z10overloadedi.ifunc = weak_odr ifunc i32 (i32), ptr @_Z10overloadedi.resolver // LINUX: @_Z10overloadedPKc.ifunc = weak_odr ifunc i32 (ptr), ptr @_Z10overloadedPKc.resolver