@@ -3796,8 +3796,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
37963796 // Forward declarations are emitted lazily on first use.
37973797 if (!FD->doesThisDeclarationHaveABody ()) {
37983798 if (!FD->doesDeclarationForceExternallyVisibleDefinition () &&
3799- (!FD->isMultiVersion () ||
3800- !FD->getASTContext ().getTargetInfo ().getTriple ().isAArch64 ()))
3799+ (!FD->isMultiVersion () || !getTarget ().getTriple ().isAArch64 ()))
38013800 return ;
38023801
38033802 StringRef MangledName = getMangledName (GD);
@@ -4191,23 +4190,6 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
41914190 return llvm::GlobalValue::WeakODRLinkage;
41924191}
41934192
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-
42114193void CodeGenModule::emitMultiVersionFunctions () {
42124194 std::vector<GlobalDecl> MVFuncsToEmit;
42134195 MultiVersionFuncs.swap (MVFuncsToEmit);
@@ -4234,29 +4216,30 @@ void CodeGenModule::emitMultiVersionFunctions() {
42344216 return cast<llvm::Function>(Func);
42354217 };
42364218
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 ();
42404223 SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
42414224
42424225 getContext ().forEachMultiversionedFunctionVersion (
42434226 FD, [&](const FunctionDecl *CurFD) {
42444227 llvm::SmallVector<StringRef, 8 > Feats;
4228+ bool IsDefined = CurFD->doesThisDeclarationHaveABody ();
42454229
42464230 if (const auto *TA = CurFD->getAttr <TargetAttr>()) {
42474231 TA->getAddedFeatures (Feats);
42484232 llvm::Function *Func = createFunction (CurFD);
42494233 Options.emplace_back (Func, TA->getArchitecture (), Feats);
42504234 } 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 ;
42554237 TVA->getFeatures (Feats);
42564238 llvm::Function *Func = createFunction (CurFD);
42574239 Options.emplace_back (Func, /* Architecture*/ " " , Feats);
42584240 } else if (const auto *TC = CurFD->getAttr <TargetClonesAttr>()) {
4259- ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody ();
4241+ if (IsDefined)
4242+ ShouldEmitResolver = true ;
42604243 for (unsigned I = 0 ; I < TC->featuresStrs_size (); ++I) {
42614244 if (!TC->isFirstOfVersion (I))
42624245 continue ;
@@ -4282,13 +4265,6 @@ void CodeGenModule::emitMultiVersionFunctions() {
42824265 if (!ShouldEmitResolver)
42834266 continue ;
42844267
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-
42924268 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
42934269 if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
42944270 ResolverConstant = IFunc->getResolver ();
@@ -4339,6 +4315,14 @@ void CodeGenModule::emitMultiVersionFunctions() {
43394315 emitMultiVersionFunctions ();
43404316}
43414317
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+
43424326void CodeGenModule::emitCPUDispatchDefinition (GlobalDecl GD) {
43434327 const auto *FD = cast<FunctionDecl>(GD.getDecl ());
43444328 assert (FD && " Not a FunctionDecl?" );
@@ -4443,12 +4427,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44434427 // Fix up function declarations that were created for cpu_specific before
44444428 // cpu_dispatch was known
44454429 if (!isa<llvm::GlobalIFunc>(IFunc)) {
4446- assert (cast<llvm::Function>(IFunc)->isDeclaration ());
44474430 auto *GI = llvm::GlobalIFunc::create (DeclTy, 0 , Linkage, " " , ResolverFunc,
44484431 &getModule ());
4449- GI->takeName (IFunc);
4450- IFunc->replaceAllUsesWith (GI);
4451- IFunc->eraseFromParent ();
4432+ replaceDeclarationWith (IFunc, GI);
44524433 IFunc = GI;
44534434 }
44544435
@@ -4478,7 +4459,8 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
44784459}
44794460
44804461// / 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.
44824464llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver (GlobalDecl GD) {
44834465 const auto *FD = cast<FunctionDecl>(GD.getDecl ());
44844466 assert (FD && " Not a FunctionDecl?" );
@@ -4506,8 +4488,15 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45064488 ResolverName += " .resolver" ;
45074489 }
45084490
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 ()))
45114500 return ResolverGV;
45124501
45134502 const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (GD);
@@ -4533,7 +4522,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45334522 " " , Resolver, &getModule ());
45344523 GIF->setName (ResolverName);
45354524 SetCommonAttributes (FD, GIF);
4536-
4525+ if (ResolverGV)
4526+ replaceDeclarationWith (ResolverGV, GIF);
45374527 return GIF;
45384528 }
45394529
@@ -4542,6 +4532,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45424532 assert (isa<llvm::GlobalValue>(Resolver) &&
45434533 " Resolver should be created for the first time" );
45444534 SetCommonAttributes (FD, cast<llvm::GlobalValue>(Resolver));
4535+ if (ResolverGV)
4536+ replaceDeclarationWith (ResolverGV, Resolver);
45454537 return Resolver;
45464538}
45474539
@@ -4571,6 +4563,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
45714563 ForDefinition_t IsForDefinition) {
45724564 const Decl *D = GD.getDecl ();
45734565
4566+ std::string NameWithoutMultiVersionMangling;
45744567 // Any attempts to use a MultiVersion function should result in retrieving
45754568 // the iFunc instead. Name Mangling will handle the rest of the changes.
45764569 if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
@@ -4592,14 +4585,24 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
45924585
45934586 if (FD->isMultiVersion ()) {
45944587 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+ }
46004600 }
46014601 }
46024602
4603+ if (!NameWithoutMultiVersionMangling.empty ())
4604+ MangledName = NameWithoutMultiVersionMangling;
4605+
46034606 // Lookup the entry, lazily creating it if necessary.
46044607 llvm::GlobalValue *Entry = GetGlobalValue (MangledName);
46054608 if (Entry) {
0 commit comments