@@ -3772,8 +3772,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
3772
3772
// Forward declarations are emitted lazily on first use.
3773
3773
if (!FD->doesThisDeclarationHaveABody ()) {
3774
3774
if (!FD->doesDeclarationForceExternallyVisibleDefinition () &&
3775
- (!FD->isMultiVersion () ||
3776
- !FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 ()))
3775
+ (!FD->isMultiVersion () || !getTarget ().getTriple ().isAArch64 ()))
3777
3776
return ;
3778
3777
3779
3778
StringRef MangledName = getMangledName (GD);
@@ -4167,23 +4166,6 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
4167
4166
return llvm::GlobalValue::WeakODRLinkage;
4168
4167
}
4169
4168
4170
- static FunctionDecl *createDefaultTargetVersionFrom (const FunctionDecl *FD) {
4171
- auto *DeclCtx = const_cast <DeclContext *>(FD->getDeclContext ());
4172
- TypeSourceInfo *TInfo = FD->getTypeSourceInfo ();
4173
- StorageClass SC = FD->getStorageClass ();
4174
- DeclarationName Name = FD->getNameInfo ().getName ();
4175
-
4176
- FunctionDecl *NewDecl =
4177
- FunctionDecl::Create (FD->getASTContext (), DeclCtx, FD->getBeginLoc (),
4178
- FD->getEndLoc (), Name, TInfo->getType (), TInfo, SC);
4179
-
4180
- NewDecl->setIsMultiVersion ();
4181
- NewDecl->addAttr (TargetVersionAttr::CreateImplicit (
4182
- NewDecl->getASTContext (), " default" , NewDecl->getSourceRange ()));
4183
-
4184
- return NewDecl;
4185
- }
4186
-
4187
4169
void CodeGenModule::emitMultiVersionFunctions () {
4188
4170
std::vector<GlobalDecl> MVFuncsToEmit;
4189
4171
MultiVersionFuncs.swap (MVFuncsToEmit);
@@ -4210,9 +4192,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
4210
4192
return cast<llvm::Function>(Func);
4211
4193
};
4212
4194
4213
- bool HasDefaultDecl = !FD->isTargetVersionMultiVersion ();
4214
- bool ShouldEmitResolver =
4215
- !getContext ().getTargetInfo ().getTriple ().isAArch64 ();
4195
+ bool ShouldEmitResolver = !getTarget ().getTriple ().isAArch64 ();
4216
4196
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
4217
4197
4218
4198
getContext ().forEachMultiversionedFunctionVersion (
@@ -4224,10 +4204,8 @@ void CodeGenModule::emitMultiVersionFunctions() {
4224
4204
llvm::Function *Func = createFunction (CurFD);
4225
4205
Options.emplace_back (Func, TA->getArchitecture (), Feats);
4226
4206
} else if (const auto *TVA = CurFD->getAttr <TargetVersionAttr>()) {
4227
- bool HasDefaultDef = TVA->isDefaultVersion () &&
4228
- CurFD->doesThisDeclarationHaveABody ();
4229
- HasDefaultDecl |= TVA->isDefaultVersion ();
4230
- ShouldEmitResolver |= (CurFD->isUsed () || HasDefaultDef);
4207
+ ShouldEmitResolver |= (TVA->isDefaultVersion () &&
4208
+ CurFD->doesThisDeclarationHaveABody ());
4231
4209
TVA->getFeatures (Feats);
4232
4210
llvm::Function *Func = createFunction (CurFD);
4233
4211
Options.emplace_back (Func, /* Architecture*/ " " , Feats);
@@ -4258,13 +4236,6 @@ void CodeGenModule::emitMultiVersionFunctions() {
4258
4236
if (!ShouldEmitResolver)
4259
4237
continue ;
4260
4238
4261
- if (!HasDefaultDecl) {
4262
- FunctionDecl *NewFD = createDefaultTargetVersionFrom (FD);
4263
- llvm::Function *Func = createFunction (NewFD);
4264
- llvm::SmallVector<StringRef, 1 > Feats;
4265
- Options.emplace_back (Func, /* Architecture*/ " " , Feats);
4266
- }
4267
-
4268
4239
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
4269
4240
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
4270
4241
ResolverConstant = IFunc->getResolver ();
@@ -4315,6 +4286,14 @@ void CodeGenModule::emitMultiVersionFunctions() {
4315
4286
emitMultiVersionFunctions ();
4316
4287
}
4317
4288
4289
+ static void replaceDeclarationWith (llvm::GlobalValue *Old,
4290
+ llvm::Constant *New) {
4291
+ assert (cast<llvm::Function>(Old)->isDeclaration () && " Not a declaration" );
4292
+ New->takeName (Old);
4293
+ Old->replaceAllUsesWith (New);
4294
+ Old->eraseFromParent ();
4295
+ }
4296
+
4318
4297
void CodeGenModule::emitCPUDispatchDefinition (GlobalDecl GD) {
4319
4298
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4320
4299
assert (FD && " Not a FunctionDecl?" );
@@ -4419,12 +4398,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
4419
4398
// Fix up function declarations that were created for cpu_specific before
4420
4399
// cpu_dispatch was known
4421
4400
if (!isa<llvm::GlobalIFunc>(IFunc)) {
4422
- assert (cast<llvm::Function>(IFunc)->isDeclaration ());
4423
4401
auto *GI = llvm::GlobalIFunc::create (DeclTy, 0 , Linkage, " " , ResolverFunc,
4424
4402
&getModule ());
4425
- GI->takeName (IFunc);
4426
- IFunc->replaceAllUsesWith (GI);
4427
- IFunc->eraseFromParent ();
4403
+ replaceDeclarationWith (IFunc, GI);
4428
4404
IFunc = GI;
4429
4405
}
4430
4406
@@ -4454,7 +4430,8 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
4454
4430
}
4455
4431
4456
4432
// / If a dispatcher for the specified mangled name is not in the module, create
4457
- // / and return an llvm Function with the specified type.
4433
+ // / and return it. The dispatcher is either an llvm Function with the specified
4434
+ // / type, or a global ifunc.
4458
4435
llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
4459
4436
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4460
4437
assert (FD && " Not a FunctionDecl?" );
@@ -4482,8 +4459,15 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4482
4459
ResolverName += " .resolver" ;
4483
4460
}
4484
4461
4485
- // If the resolver has already been created, just return it.
4486
- if (llvm::GlobalValue *ResolverGV = GetGlobalValue (ResolverName))
4462
+ // If the resolver has already been created, just return it. This lookup may
4463
+ // yield a function declaration instead of a resolver on AArch64. That is
4464
+ // because we didn't know whether a resolver will be generated when we first
4465
+ // encountered a use of the symbol named after this resolver. Therefore,
4466
+ // targets which support ifuncs should not return here unless we actually
4467
+ // found an ifunc.
4468
+ llvm::GlobalValue *ResolverGV = GetGlobalValue (ResolverName);
4469
+ if (ResolverGV &&
4470
+ (isa<llvm::GlobalIFunc>(ResolverGV) || !getTarget ().supportsIFunc ()))
4487
4471
return ResolverGV;
4488
4472
4489
4473
const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
@@ -4509,7 +4493,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4509
4493
" " , Resolver, &getModule ());
4510
4494
GIF->setName (ResolverName);
4511
4495
SetCommonAttributes (FD, GIF);
4512
-
4496
+ if (ResolverGV)
4497
+ replaceDeclarationWith (ResolverGV, GIF);
4513
4498
return GIF;
4514
4499
}
4515
4500
@@ -4518,6 +4503,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4518
4503
assert (isa<llvm::GlobalValue>(Resolver) &&
4519
4504
" Resolver should be created for the first time" );
4520
4505
SetCommonAttributes (FD, cast<llvm::GlobalValue>(Resolver));
4506
+ if (ResolverGV)
4507
+ replaceDeclarationWith (ResolverGV, Resolver);
4521
4508
return Resolver;
4522
4509
}
4523
4510
@@ -4547,6 +4534,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
4547
4534
ForDefinition_t IsForDefinition) {
4548
4535
const Decl *D = GD.getDecl ();
4549
4536
4537
+ std::string NameWithoutMultiVersionMangling;
4550
4538
// Any attempts to use a MultiVersion function should result in retrieving
4551
4539
// the iFunc instead. Name Mangling will handle the rest of the changes.
4552
4540
if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
@@ -4568,14 +4556,24 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
4568
4556
4569
4557
if (FD->isMultiVersion ()) {
4570
4558
UpdateMultiVersionNames (GD, FD, MangledName);
4571
- if (FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 () &&
4572
- !FD->isUsed ())
4573
- AddDeferredMultiVersionResolverToEmit (GD);
4574
- else if (!IsForDefinition)
4575
- return GetOrCreateMultiVersionResolver (GD);
4559
+ if (!IsForDefinition) {
4560
+ // On AArch64 we do not immediatelly emit an ifunc resolver when a
4561
+ // function is used. Instead we defer the emission until we see a
4562
+ // default definition. In the meantime we just reference the symbol
4563
+ // without FMV mangling (it may or may not be replaced later).
4564
+ if (getTarget ().getTriple ().isAArch64 ()) {
4565
+ AddDeferredMultiVersionResolverToEmit (GD);
4566
+ NameWithoutMultiVersionMangling = getMangledNameImpl (
4567
+ *this , GD, FD, /* OmitMultiVersionMangling=*/ true );
4568
+ } else
4569
+ return GetOrCreateMultiVersionResolver (GD);
4570
+ }
4576
4571
}
4577
4572
}
4578
4573
4574
+ if (!NameWithoutMultiVersionMangling.empty ())
4575
+ MangledName = NameWithoutMultiVersionMangling;
4576
+
4579
4577
// Lookup the entry, lazily creating it if necessary.
4580
4578
llvm::GlobalValue *Entry = GetGlobalValue (MangledName);
4581
4579
if (Entry) {
0 commit comments