@@ -3449,6 +3449,9 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
34493449 // Implicit template instantiations may change linkage if they are later
34503450 // explicitly instantiated, so they should not be emitted eagerly.
34513451 return false ;
3452+ // Defer until all versions have been semantically checked.
3453+ if (FD->hasAttr <TargetVersionAttr>() && !FD->isMultiVersion ())
3454+ return false ;
34523455 }
34533456 if (const auto *VD = dyn_cast<VarDecl>(Global)) {
34543457 if (Context.getInlineVariableDefinitionKind (VD) ==
@@ -3997,10 +4000,13 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
39974000 EmitGlobalFunctionDefinition (GD.getWithMultiVersionIndex (I), nullptr );
39984001 // Ensure that the resolver function is also emitted.
39994002 GetOrCreateMultiVersionResolver (GD);
4000- } else if (FD->hasAttr <TargetVersionAttr>()) {
4001- GetOrCreateMultiVersionResolver (GD);
40024003 } else
40034004 EmitGlobalFunctionDefinition (GD, GV);
4005+
4006+ // Defer the resolver emission until we can reason whether the TU
4007+ // contains a default target version implementation.
4008+ if (FD->isTargetVersionMultiVersion ())
4009+ AddDeferredMultiVersionResolverToEmit (GD);
40044010}
40054011
40064012void CodeGenModule::EmitGlobalDefinition (GlobalDecl GD, llvm::GlobalValue *GV) {
@@ -4093,10 +4099,11 @@ void CodeGenModule::emitMultiVersionFunctions() {
40934099 const auto *FD = cast<FunctionDecl>(GD.getDecl ());
40944100 assert (FD && " Expected a FunctionDecl" );
40954101
4102+ bool EmitResolver = !FD->isTargetVersionMultiVersion ();
40964103 SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
40974104 if (FD->isTargetMultiVersion ()) {
40984105 getContext ().forEachMultiversionedFunctionVersion (
4099- FD, [this , &GD, &Options](const FunctionDecl *CurFD) {
4106+ FD, [this , &GD, &Options, &EmitResolver ](const FunctionDecl *CurFD) {
41004107 GlobalDecl CurGD{
41014108 (CurFD->isDefined () ? CurFD->getDefinition () : CurFD)};
41024109 StringRef MangledName = getMangledName (CurGD);
@@ -4122,6 +4129,9 @@ void CodeGenModule::emitMultiVersionFunctions() {
41224129 TA->getArchitecture (), Feats);
41234130 } else {
41244131 const auto *TVA = CurFD->getAttr <TargetVersionAttr>();
4132+ if (CurFD->isUsed () || (TVA->isDefaultVersion () &&
4133+ CurFD->doesThisDeclarationHaveABody ()))
4134+ EmitResolver = true ;
41254135 llvm::SmallVector<StringRef, 8 > Feats;
41264136 TVA->getFeatures (Feats);
41274137 Options.emplace_back (cast<llvm::Function>(Func),
@@ -4177,22 +4187,27 @@ void CodeGenModule::emitMultiVersionFunctions() {
41774187 continue ;
41784188 }
41794189
4190+ if (!EmitResolver)
4191+ continue ;
4192+
41804193 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
41814194 if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
41824195 ResolverConstant = IFunc->getResolver ();
41834196 if (FD->isTargetClonesMultiVersion () ||
41844197 FD->isTargetVersionMultiVersion ()) {
4185- const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
4186- llvm::FunctionType *DeclTy = getTypes ().GetFunctionType (FI);
41874198 std::string MangledName = getMangledNameImpl (
41884199 *this , GD, FD, /* OmitMultiVersionMangling=*/ true );
4189- // In prior versions of Clang, the mangling for ifuncs incorrectly
4190- // included an .ifunc suffix. This alias is generated for backward
4191- // compatibility. It is deprecated, and may be removed in the future.
4192- auto *Alias = llvm::GlobalAlias::create (
4193- DeclTy, 0 , getMultiversionLinkage (*this , GD),
4194- MangledName + " .ifunc" , IFunc, &getModule ());
4195- SetCommonAttributes (FD, Alias);
4200+ if (!GetGlobalValue (MangledName + " .ifunc" )) {
4201+ const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
4202+ llvm::FunctionType *DeclTy = getTypes ().GetFunctionType (FI);
4203+ // In prior versions of Clang, the mangling for ifuncs incorrectly
4204+ // included an .ifunc suffix. This alias is generated for backward
4205+ // compatibility. It is deprecated, and may be removed in the future.
4206+ auto *Alias = llvm::GlobalAlias::create (
4207+ DeclTy, 0 , getMultiversionLinkage (*this , GD),
4208+ MangledName + " .ifunc" , IFunc, &getModule ());
4209+ SetCommonAttributes (FD, Alias);
4210+ }
41964211 }
41974212 }
41984213 llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant);
@@ -4349,6 +4364,20 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
43494364 }
43504365}
43514366
4367+ // / Adds a declaration to the list of multi version functions if not present.
4368+ void CodeGenModule::AddDeferredMultiVersionResolverToEmit (GlobalDecl GD) {
4369+ const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4370+ assert (FD && " Not a FunctionDecl?" );
4371+
4372+ if (FD->isTargetVersionMultiVersion ()) {
4373+ std::string MangledName =
4374+ getMangledNameImpl (*this , GD, FD, /* OmitMultiVersionMangling=*/ true );
4375+ if (!DeferredResolversToEmit.insert (MangledName).second )
4376+ return ;
4377+ }
4378+ MultiVersionFuncs.push_back (GD);
4379+ }
4380+
43524381// / If a dispatcher for the specified mangled name is not in the module, create
43534382// / and return an llvm Function with the specified type.
43544383llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
@@ -4388,7 +4417,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
43884417 // The resolver needs to be created. For target and target_clones, defer
43894418 // creation until the end of the TU.
43904419 if (FD->isTargetMultiVersion () || FD->isTargetClonesMultiVersion ())
4391- MultiVersionFuncs. push_back (GD);
4420+ AddDeferredMultiVersionResolverToEmit (GD);
43924421
43934422 // For cpu_specific, don't create an ifunc yet because we don't know if the
43944423 // cpu_dispatch will be emitted in this translation unit.
0 commit comments