@@ -3796,8 +3796,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
3796
3796
// Forward declarations are emitted lazily on first use.
3797
3797
if (!FD->doesThisDeclarationHaveABody ()) {
3798
3798
if (!FD->doesDeclarationForceExternallyVisibleDefinition () &&
3799
- (!FD->isMultiVersion () ||
3800
- !FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 ()))
3799
+ (!FD->isMultiVersion () || !getTarget ().getTriple ().isAArch64 ()))
3801
3800
return ;
3802
3801
3803
3802
StringRef MangledName = getMangledName (GD);
@@ -4191,23 +4190,6 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
4191
4190
return llvm::GlobalValue::WeakODRLinkage;
4192
4191
}
4193
4192
4194
- static FunctionDecl *createDefaultTargetVersionFrom (const FunctionDecl *FD) {
4195
- auto *DeclCtx = const_cast <DeclContext *>(FD->getDeclContext ());
4196
- TypeSourceInfo *TInfo = FD->getTypeSourceInfo ();
4197
- StorageClass SC = FD->getStorageClass ();
4198
- DeclarationName Name = FD->getNameInfo ().getName ();
4199
-
4200
- FunctionDecl *NewDecl =
4201
- FunctionDecl::Create (FD->getASTContext (), DeclCtx, FD->getBeginLoc (),
4202
- FD->getEndLoc (), Name, TInfo->getType (), TInfo, SC);
4203
-
4204
- NewDecl->setIsMultiVersion ();
4205
- NewDecl->addAttr (TargetVersionAttr::CreateImplicit (
4206
- NewDecl->getASTContext (), " default" , NewDecl->getSourceRange ()));
4207
-
4208
- return NewDecl;
4209
- }
4210
-
4211
4193
void CodeGenModule::emitMultiVersionFunctions () {
4212
4194
std::vector<GlobalDecl> MVFuncsToEmit;
4213
4195
MultiVersionFuncs.swap (MVFuncsToEmit);
@@ -4234,29 +4216,30 @@ void CodeGenModule::emitMultiVersionFunctions() {
4234
4216
return cast<llvm::Function>(Func);
4235
4217
};
4236
4218
4237
- bool HasDefaultDecl = !FD->isTargetVersionMultiVersion ();
4238
- bool ShouldEmitResolver =
4239
- !getContext ().getTargetInfo ().getTriple ().isAArch64 ();
4219
+ // For AArch64, a resolver is only emitted if a function marked with
4220
+ // target_version("default")) or target_clones() is present and defined
4221
+ // in this TU. For other architectures it is always emitted.
4222
+ bool ShouldEmitResolver = !getTarget ().getTriple ().isAArch64 ();
4240
4223
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
4241
4224
4242
4225
getContext ().forEachMultiversionedFunctionVersion (
4243
4226
FD, [&](const FunctionDecl *CurFD) {
4244
4227
llvm::SmallVector<StringRef, 8 > Feats;
4228
+ bool IsDefined = CurFD->doesThisDeclarationHaveABody ();
4245
4229
4246
4230
if (const auto *TA = CurFD->getAttr <TargetAttr>()) {
4247
4231
TA->getAddedFeatures (Feats);
4248
4232
llvm::Function *Func = createFunction (CurFD);
4249
4233
Options.emplace_back (Func, TA->getArchitecture (), Feats);
4250
4234
} else if (const auto *TVA = CurFD->getAttr <TargetVersionAttr>()) {
4251
- bool HasDefaultDef = TVA->isDefaultVersion () &&
4252
- CurFD->doesThisDeclarationHaveABody ();
4253
- HasDefaultDecl |= TVA->isDefaultVersion ();
4254
- ShouldEmitResolver |= (CurFD->isUsed () || HasDefaultDef);
4235
+ if (TVA->isDefaultVersion () && IsDefined)
4236
+ ShouldEmitResolver = true ;
4255
4237
TVA->getFeatures (Feats);
4256
4238
llvm::Function *Func = createFunction (CurFD);
4257
4239
Options.emplace_back (Func, /* Architecture*/ " " , Feats);
4258
4240
} else if (const auto *TC = CurFD->getAttr <TargetClonesAttr>()) {
4259
- ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody ();
4241
+ if (IsDefined)
4242
+ ShouldEmitResolver = true ;
4260
4243
for (unsigned I = 0 ; I < TC->featuresStrs_size (); ++I) {
4261
4244
if (!TC->isFirstOfVersion (I))
4262
4245
continue ;
@@ -4282,13 +4265,6 @@ void CodeGenModule::emitMultiVersionFunctions() {
4282
4265
if (!ShouldEmitResolver)
4283
4266
continue ;
4284
4267
4285
- if (!HasDefaultDecl) {
4286
- FunctionDecl *NewFD = createDefaultTargetVersionFrom (FD);
4287
- llvm::Function *Func = createFunction (NewFD);
4288
- llvm::SmallVector<StringRef, 1 > Feats;
4289
- Options.emplace_back (Func, /* Architecture*/ " " , Feats);
4290
- }
4291
-
4292
4268
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
4293
4269
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
4294
4270
ResolverConstant = IFunc->getResolver ();
@@ -4339,6 +4315,14 @@ void CodeGenModule::emitMultiVersionFunctions() {
4339
4315
emitMultiVersionFunctions ();
4340
4316
}
4341
4317
4318
+ static void replaceDeclarationWith (llvm::GlobalValue *Old,
4319
+ llvm::Constant *New) {
4320
+ assert (cast<llvm::Function>(Old)->isDeclaration () && " Not a declaration" );
4321
+ New->takeName (Old);
4322
+ Old->replaceAllUsesWith (New);
4323
+ Old->eraseFromParent ();
4324
+ }
4325
+
4342
4326
void CodeGenModule::emitCPUDispatchDefinition (GlobalDecl GD) {
4343
4327
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4344
4328
assert (FD && " Not a FunctionDecl?" );
@@ -4443,12 +4427,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
4443
4427
// Fix up function declarations that were created for cpu_specific before
4444
4428
// cpu_dispatch was known
4445
4429
if (!isa<llvm::GlobalIFunc>(IFunc)) {
4446
- assert (cast<llvm::Function>(IFunc)->isDeclaration ());
4447
4430
auto *GI = llvm::GlobalIFunc::create (DeclTy, 0 , Linkage, " " , ResolverFunc,
4448
4431
&getModule ());
4449
- GI->takeName (IFunc);
4450
- IFunc->replaceAllUsesWith (GI);
4451
- IFunc->eraseFromParent ();
4432
+ replaceDeclarationWith (IFunc, GI);
4452
4433
IFunc = GI;
4453
4434
}
4454
4435
@@ -4478,7 +4459,8 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
4478
4459
}
4479
4460
4480
4461
// / If a dispatcher for the specified mangled name is not in the module, create
4481
- // / and return an llvm Function with the specified type.
4462
+ // / and return it. The dispatcher is either an llvm Function with the specified
4463
+ // / type, or a global ifunc.
4482
4464
llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
4483
4465
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4484
4466
assert (FD && " Not a FunctionDecl?" );
@@ -4506,8 +4488,15 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4506
4488
ResolverName += " .resolver" ;
4507
4489
}
4508
4490
4509
- // If the resolver has already been created, just return it.
4510
- if (llvm::GlobalValue *ResolverGV = GetGlobalValue (ResolverName))
4491
+ // If the resolver has already been created, just return it. This lookup may
4492
+ // yield a function declaration instead of a resolver on AArch64. That is
4493
+ // because we didn't know whether a resolver will be generated when we first
4494
+ // encountered a use of the symbol named after this resolver. Therefore,
4495
+ // targets which support ifuncs should not return here unless we actually
4496
+ // found an ifunc.
4497
+ llvm::GlobalValue *ResolverGV = GetGlobalValue (ResolverName);
4498
+ if (ResolverGV &&
4499
+ (isa<llvm::GlobalIFunc>(ResolverGV) || !getTarget ().supportsIFunc ()))
4511
4500
return ResolverGV;
4512
4501
4513
4502
const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
@@ -4533,7 +4522,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4533
4522
" " , Resolver, &getModule ());
4534
4523
GIF->setName (ResolverName);
4535
4524
SetCommonAttributes (FD, GIF);
4536
-
4525
+ if (ResolverGV)
4526
+ replaceDeclarationWith (ResolverGV, GIF);
4537
4527
return GIF;
4538
4528
}
4539
4529
@@ -4542,6 +4532,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
4542
4532
assert (isa<llvm::GlobalValue>(Resolver) &&
4543
4533
" Resolver should be created for the first time" );
4544
4534
SetCommonAttributes (FD, cast<llvm::GlobalValue>(Resolver));
4535
+ if (ResolverGV)
4536
+ replaceDeclarationWith (ResolverGV, Resolver);
4545
4537
return Resolver;
4546
4538
}
4547
4539
@@ -4571,6 +4563,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
4571
4563
ForDefinition_t IsForDefinition) {
4572
4564
const Decl *D = GD.getDecl ();
4573
4565
4566
+ std::string NameWithoutMultiVersionMangling;
4574
4567
// Any attempts to use a MultiVersion function should result in retrieving
4575
4568
// the iFunc instead. Name Mangling will handle the rest of the changes.
4576
4569
if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
@@ -4592,14 +4585,24 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
4592
4585
4593
4586
if (FD->isMultiVersion ()) {
4594
4587
UpdateMultiVersionNames (GD, FD, MangledName);
4595
- if (FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 () &&
4596
- !FD->isUsed ())
4597
- AddDeferredMultiVersionResolverToEmit (GD);
4598
- else if (!IsForDefinition)
4599
- return GetOrCreateMultiVersionResolver (GD);
4588
+ if (!IsForDefinition) {
4589
+ // On AArch64 we do not immediatelly emit an ifunc resolver when a
4590
+ // function is used. Instead we defer the emission until we see a
4591
+ // default definition. In the meantime we just reference the symbol
4592
+ // without FMV mangling (it may or may not be replaced later).
4593
+ if (getTarget ().getTriple ().isAArch64 ()) {
4594
+ AddDeferredMultiVersionResolverToEmit (GD);
4595
+ NameWithoutMultiVersionMangling = getMangledNameImpl (
4596
+ *this , GD, FD, /* OmitMultiVersionMangling=*/ true );
4597
+ } else
4598
+ return GetOrCreateMultiVersionResolver (GD);
4599
+ }
4600
4600
}
4601
4601
}
4602
4602
4603
+ if (!NameWithoutMultiVersionMangling.empty ())
4604
+ MangledName = NameWithoutMultiVersionMangling;
4605
+
4603
4606
// Lookup the entry, lazily creating it if necessary.
4604
4607
llvm::GlobalValue *Entry = GetGlobalValue (MangledName);
4605
4608
if (Entry) {
0 commit comments