@@ -3772,8 +3772,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
37723772 // Forward declarations are emitted lazily on first use.
37733773 if (!FD->doesThisDeclarationHaveABody ()) {
37743774 if (!FD->doesDeclarationForceExternallyVisibleDefinition () &&
3775- (!FD->isMultiVersion () ||
3776- !FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 ()))
3775+ (!FD->isMultiVersion () || !getTarget ().getTriple ().isAArch64 ()))
37773776 return ;
37783777
37793778 StringRef MangledName = getMangledName (GD);
@@ -4167,23 +4166,6 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
41674166 return llvm::GlobalValue::WeakODRLinkage;
41684167}
41694168
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-
41874169void CodeGenModule::emitMultiVersionFunctions () {
41884170 std::vector<GlobalDecl> MVFuncsToEmit;
41894171 MultiVersionFuncs.swap (MVFuncsToEmit);
@@ -4210,9 +4192,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
42104192 return cast<llvm::Function>(Func);
42114193 };
42124194
4213- bool HasDefaultDecl = !FD->isTargetVersionMultiVersion ();
4214- bool ShouldEmitResolver =
4215- !getContext ().getTargetInfo ().getTriple ().isAArch64 ();
4195+ bool ShouldEmitResolver = !getTarget ().getTriple ().isAArch64 ();
42164196 SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
42174197
42184198 getContext ().forEachMultiversionedFunctionVersion (
@@ -4224,10 +4204,8 @@ void CodeGenModule::emitMultiVersionFunctions() {
42244204 llvm::Function *Func = createFunction (CurFD);
42254205 Options.emplace_back (Func, TA->getArchitecture (), Feats);
42264206 } 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 ());
42314209 TVA->getFeatures (Feats);
42324210 llvm::Function *Func = createFunction (CurFD);
42334211 Options.emplace_back (Func, /* Architecture*/ " " , Feats);
@@ -4258,13 +4236,6 @@ void CodeGenModule::emitMultiVersionFunctions() {
42584236 if (!ShouldEmitResolver)
42594237 continue ;
42604238
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-
42684239 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
42694240 if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
42704241 ResolverConstant = IFunc->getResolver ();
@@ -4315,6 +4286,14 @@ void CodeGenModule::emitMultiVersionFunctions() {
43154286 emitMultiVersionFunctions ();
43164287}
43174288
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+
43184297void CodeGenModule::emitCPUDispatchDefinition (GlobalDecl GD) {
43194298 const auto *FD = cast<FunctionDecl>(GD.getDecl ());
43204299 assert (FD && " Not a FunctionDecl?" );
@@ -4419,12 +4398,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44194398 // Fix up function declarations that were created for cpu_specific before
44204399 // cpu_dispatch was known
44214400 if (!isa<llvm::GlobalIFunc>(IFunc)) {
4422- assert (cast<llvm::Function>(IFunc)->isDeclaration ());
44234401 auto *GI = llvm::GlobalIFunc::create (DeclTy, 0 , Linkage, " " , ResolverFunc,
44244402 &getModule ());
4425- GI->takeName (IFunc);
4426- IFunc->replaceAllUsesWith (GI);
4427- IFunc->eraseFromParent ();
4403+ replaceDeclarationWith (IFunc, GI);
44284404 IFunc = GI;
44294405 }
44304406
@@ -4454,7 +4430,8 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
44544430}
44554431
44564432// / 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.
44584435llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
44594436 const auto *FD = cast<FunctionDecl>(GD.getDecl ());
44604437 assert (FD && " Not a FunctionDecl?" );
@@ -4482,8 +4459,15 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
44824459 ResolverName += " .resolver" ;
44834460 }
44844461
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 ()))
44874471 return ResolverGV;
44884472
44894473 const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
@@ -4509,7 +4493,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45094493 " " , Resolver, &getModule ());
45104494 GIF->setName (ResolverName);
45114495 SetCommonAttributes (FD, GIF);
4512-
4496+ if (ResolverGV)
4497+ replaceDeclarationWith (ResolverGV, GIF);
45134498 return GIF;
45144499 }
45154500
@@ -4518,6 +4503,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45184503 assert (isa<llvm::GlobalValue>(Resolver) &&
45194504 " Resolver should be created for the first time" );
45204505 SetCommonAttributes (FD, cast<llvm::GlobalValue>(Resolver));
4506+ if (ResolverGV)
4507+ replaceDeclarationWith (ResolverGV, Resolver);
45214508 return Resolver;
45224509}
45234510
@@ -4547,6 +4534,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
45474534 ForDefinition_t IsForDefinition) {
45484535 const Decl *D = GD.getDecl ();
45494536
4537+ std::string NameWithoutMultiVersionMangling;
45504538 // Any attempts to use a MultiVersion function should result in retrieving
45514539 // the iFunc instead. Name Mangling will handle the rest of the changes.
45524540 if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
@@ -4568,14 +4556,24 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
45684556
45694557 if (FD->isMultiVersion ()) {
45704558 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+ }
45764571 }
45774572 }
45784573
4574+ if (!NameWithoutMultiVersionMangling.empty ())
4575+ MangledName = NameWithoutMultiVersionMangling;
4576+
45794577 // Lookup the entry, lazily creating it if necessary.
45804578 llvm::GlobalValue *Entry = GetGlobalValue (MangledName);
45814579 if (Entry) {
0 commit comments