@@ -3447,6 +3447,9 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
3447
3447
// Implicit template instantiations may change linkage if they are later
3448
3448
// explicitly instantiated, so they should not be emitted eagerly.
3449
3449
return false ;
3450
+ // Defer until all versions have been semantically checked.
3451
+ if (FD->hasAttr <TargetVersionAttr>() && !FD->isMultiVersion ())
3452
+ return false ;
3450
3453
}
3451
3454
if (const auto *VD = dyn_cast<VarDecl>(Global)) {
3452
3455
if (Context.getInlineVariableDefinitionKind (VD) ==
@@ -3995,10 +3998,13 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
3995
3998
EmitGlobalFunctionDefinition (GD.getWithMultiVersionIndex (I), nullptr );
3996
3999
// Ensure that the resolver function is also emitted.
3997
4000
GetOrCreateMultiVersionResolver (GD);
3998
- } else if (FD->hasAttr <TargetVersionAttr>()) {
3999
- GetOrCreateMultiVersionResolver (GD);
4000
4001
} else
4001
4002
EmitGlobalFunctionDefinition (GD, GV);
4003
+
4004
+ // Defer the resolver emission until we can reason whether the TU
4005
+ // contains a default target version implementation.
4006
+ if (FD->isTargetVersionMultiVersion ())
4007
+ AddDeferredMultiVersionResolverToEmit (GD);
4002
4008
}
4003
4009
4004
4010
void CodeGenModule::EmitGlobalDefinition (GlobalDecl GD, llvm::GlobalValue *GV) {
@@ -4091,10 +4097,11 @@ void CodeGenModule::emitMultiVersionFunctions() {
4091
4097
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4092
4098
assert (FD && " Expected a FunctionDecl" );
4093
4099
4100
+ bool EmitResolver = !FD->isTargetVersionMultiVersion ();
4094
4101
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
4095
4102
if (FD->isTargetMultiVersion ()) {
4096
4103
getContext ().forEachMultiversionedFunctionVersion (
4097
- FD, [this , &GD, &Options](const FunctionDecl *CurFD) {
4104
+ FD, [this , &GD, &Options, &EmitResolver ](const FunctionDecl *CurFD) {
4098
4105
GlobalDecl CurGD{
4099
4106
(CurFD->isDefined () ? CurFD->getDefinition () : CurFD)};
4100
4107
StringRef MangledName = getMangledName (CurGD);
@@ -4120,6 +4127,9 @@ void CodeGenModule::emitMultiVersionFunctions() {
4120
4127
TA->getArchitecture (), Feats);
4121
4128
} else {
4122
4129
const auto *TVA = CurFD->getAttr <TargetVersionAttr>();
4130
+ if (TVA->isDefaultVersion () &&
4131
+ CurFD->doesThisDeclarationHaveABody ())
4132
+ EmitResolver = true ;
4123
4133
llvm::SmallVector<StringRef, 8 > Feats;
4124
4134
TVA->getFeatures (Feats);
4125
4135
Options.emplace_back (cast<llvm::Function>(Func),
@@ -4175,22 +4185,27 @@ void CodeGenModule::emitMultiVersionFunctions() {
4175
4185
continue ;
4176
4186
}
4177
4187
4188
+ if (!EmitResolver)
4189
+ continue ;
4190
+
4178
4191
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
4179
4192
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
4180
4193
ResolverConstant = IFunc->getResolver ();
4181
4194
if (FD->isTargetClonesMultiVersion () ||
4182
4195
FD->isTargetVersionMultiVersion ()) {
4183
- const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
4184
- llvm::FunctionType *DeclTy = getTypes ().GetFunctionType (FI);
4185
4196
std::string MangledName = getMangledNameImpl (
4186
4197
*this , GD, FD, /* OmitMultiVersionMangling=*/ true );
4187
- // In prior versions of Clang, the mangling for ifuncs incorrectly
4188
- // included an .ifunc suffix. This alias is generated for backward
4189
- // compatibility. It is deprecated, and may be removed in the future.
4190
- auto *Alias = llvm::GlobalAlias::create (
4191
- DeclTy, 0 , getMultiversionLinkage (*this , GD),
4192
- MangledName + " .ifunc" , IFunc, &getModule ());
4193
- SetCommonAttributes (FD, Alias);
4198
+ if (!GetGlobalValue (MangledName + " .ifunc" )) {
4199
+ const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
4200
+ llvm::FunctionType *DeclTy = getTypes ().GetFunctionType (FI);
4201
+ // In prior versions of Clang, the mangling for ifuncs incorrectly
4202
+ // included an .ifunc suffix. This alias is generated for backward
4203
+ // compatibility. It is deprecated, and may be removed in the future.
4204
+ auto *Alias = llvm::GlobalAlias::create (
4205
+ DeclTy, 0 , getMultiversionLinkage (*this , GD),
4206
+ MangledName + " .ifunc" , IFunc, &getModule ());
4207
+ SetCommonAttributes (FD, Alias);
4208
+ }
4194
4209
}
4195
4210
}
4196
4211
llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant);
@@ -4347,6 +4362,19 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
4347
4362
}
4348
4363
}
4349
4364
4365
+ // / Adds a declaration to the list of multi version functions if not present.
4366
+ void CodeGenModule::AddDeferredMultiVersionResolverToEmit (GlobalDecl GD) {
4367
+ const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4368
+ assert (FD && " Not a FunctionDecl?" );
4369
+
4370
+ if (FD->isTargetVersionMultiVersion ()) {
4371
+ StringRef NamePrefix = getMangledName (GD).split (' .' ).first ;
4372
+ if (!DeferredResolversToEmit.insert (NamePrefix).second )
4373
+ return ;
4374
+ }
4375
+ MultiVersionFuncs.push_back (GD);
4376
+ }
4377
+
4350
4378
// / If a dispatcher for the specified mangled name is not in the module, create
4351
4379
// / and return an llvm Function with the specified type.
4352
4380
llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
@@ -4386,7 +4414,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4386
4414
// The resolver needs to be created. For target and target_clones, defer
4387
4415
// creation until the end of the TU.
4388
4416
if (FD->isTargetMultiVersion () || FD->isTargetClonesMultiVersion ())
4389
- MultiVersionFuncs. push_back (GD);
4417
+ AddDeferredMultiVersionResolverToEmit (GD);
4390
4418
4391
4419
// For cpu_specific, don't create an ifunc yet because we don't know if the
4392
4420
// cpu_dispatch will be emitted in this translation unit.
0 commit comments