@@ -3711,7 +3711,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
3711
3711
3712
3712
// Forward declarations are emitted lazily on first use.
3713
3713
if (!FD->doesThisDeclarationHaveABody ()) {
3714
- if (!FD->doesDeclarationForceExternallyVisibleDefinition ())
3714
+ if (!FD->doesDeclarationForceExternallyVisibleDefinition () &&
3715
+ !FD->isTargetVersionMultiVersion ())
3715
3716
return ;
3716
3717
3717
3718
StringRef MangledName = getMangledName (GD);
@@ -4092,77 +4093,78 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
4092
4093
return llvm::GlobalValue::WeakODRLinkage;
4093
4094
}
4094
4095
4096
+ static FunctionDecl *createDefaultTargetVersionFrom (const FunctionDecl *FD) {
4097
+ DeclContext *DeclCtx = FD->getASTContext ().getTranslationUnitDecl ();
4098
+ TypeSourceInfo *TInfo = FD->getTypeSourceInfo ();
4099
+ StorageClass SC = FD->getStorageClass ();
4100
+ DeclarationName Name = FD->getNameInfo ().getName ();
4101
+
4102
+ FunctionDecl *NewDecl =
4103
+ FunctionDecl::Create (FD->getASTContext (), DeclCtx, FD->getBeginLoc (),
4104
+ FD->getEndLoc (), Name, TInfo->getType (), TInfo, SC);
4105
+
4106
+ NewDecl->setIsMultiVersion ();
4107
+ NewDecl->addAttr (TargetVersionAttr::CreateImplicit (
4108
+ NewDecl->getASTContext (), " default" , NewDecl->getSourceRange ()));
4109
+
4110
+ return NewDecl;
4111
+ }
4112
+
4095
4113
void CodeGenModule::emitMultiVersionFunctions () {
4096
4114
std::vector<GlobalDecl> MVFuncsToEmit;
4097
4115
MultiVersionFuncs.swap (MVFuncsToEmit);
4098
4116
for (GlobalDecl GD : MVFuncsToEmit) {
4099
4117
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4100
4118
assert (FD && " Expected a FunctionDecl" );
4101
4119
4102
- bool EmitResolver = !FD->isTargetVersionMultiVersion ();
4120
+ auto createFunction = [&](const FunctionDecl *Decl, unsigned MVIdx = 0 ) {
4121
+ GlobalDecl CurGD{Decl->isDefined () ? Decl->getDefinition () : Decl, MVIdx};
4122
+ StringRef MangledName = getMangledName (CurGD);
4123
+ llvm::Constant *Func = GetGlobalValue (MangledName);
4124
+ if (!Func) {
4125
+ if (Decl->isDefined ()) {
4126
+ EmitGlobalFunctionDefinition (CurGD, nullptr );
4127
+ Func = GetGlobalValue (MangledName);
4128
+ } else {
4129
+ const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (CurGD);
4130
+ llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4131
+ Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4132
+ /* DontDefer=*/ false , ForDefinition);
4133
+ }
4134
+ assert (Func && " This should have just been created" );
4135
+ }
4136
+ return cast<llvm::Function>(Func);
4137
+ };
4138
+
4139
+ bool HasDefaultDecl = !FD->isTargetVersionMultiVersion ();
4140
+ bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion ();
4103
4141
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
4104
4142
if (FD->isTargetMultiVersion ()) {
4105
4143
getContext ().forEachMultiversionedFunctionVersion (
4106
- FD, [this , &GD, &Options, &EmitResolver](const FunctionDecl *CurFD) {
4107
- GlobalDecl CurGD{
4108
- (CurFD->isDefined () ? CurFD->getDefinition () : CurFD)};
4109
- StringRef MangledName = getMangledName (CurGD);
4110
- llvm::Constant *Func = GetGlobalValue (MangledName);
4111
- if (!Func) {
4112
- if (CurFD->isDefined ()) {
4113
- EmitGlobalFunctionDefinition (CurGD, nullptr );
4114
- Func = GetGlobalValue (MangledName);
4115
- } else {
4116
- const CGFunctionInfo &FI =
4117
- getTypes ().arrangeGlobalDeclaration (GD);
4118
- llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4119
- Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4120
- /* DontDefer=*/ false , ForDefinition);
4121
- }
4122
- assert (Func && " This should have just been created" );
4123
- }
4124
- if (CurFD->getMultiVersionKind () == MultiVersionKind::Target) {
4125
- const auto *TA = CurFD->getAttr <TargetAttr>();
4126
- llvm::SmallVector<StringRef, 8 > Feats;
4144
+ FD, [&](const FunctionDecl *CurFD) {
4145
+ llvm::SmallVector<StringRef, 8 > Feats;
4146
+ llvm::Function *Func = createFunction (CurFD);
4147
+
4148
+ if (const auto *TA = CurFD->getAttr <TargetAttr>()) {
4127
4149
TA->getAddedFeatures (Feats);
4128
- Options.emplace_back (cast<llvm::Function>(Func),
4129
- TA->getArchitecture (), Feats);
4130
- } else {
4131
- const auto *TVA = CurFD->getAttr <TargetVersionAttr>();
4132
- if (CurFD->isUsed () || (TVA->isDefaultVersion () &&
4133
- CurFD->doesThisDeclarationHaveABody ()))
4134
- EmitResolver = true ;
4135
- llvm::SmallVector<StringRef, 8 > Feats;
4150
+ Options.emplace_back (Func, TA->getArchitecture (), Feats);
4151
+ } else if (const auto *TVA = CurFD->getAttr <TargetVersionAttr>()) {
4152
+ bool HasDefaultDef = TVA->isDefaultVersion () &&
4153
+ CurFD->doesThisDeclarationHaveABody ();
4154
+ HasDefaultDecl |= TVA->isDefaultVersion ();
4155
+ ShouldEmitResolver |= (CurFD->isUsed () || HasDefaultDef);
4136
4156
TVA->getFeatures (Feats);
4137
- Options.emplace_back (cast<llvm::Function>( Func),
4138
- /* Architecture */ " " , Feats);
4139
- }
4157
+ Options.emplace_back (Func, /* Architecture */ " " , Feats);
4158
+ } else
4159
+ llvm_unreachable ( " unexpected MultiVersionKind " );
4140
4160
});
4141
- } else if (FD->isTargetClonesMultiVersion ()) {
4142
- const auto *TC = FD->getAttr <TargetClonesAttr>();
4143
- for (unsigned VersionIndex = 0 ; VersionIndex < TC->featuresStrs_size ();
4144
- ++VersionIndex) {
4145
- if (!TC->isFirstOfVersion (VersionIndex))
4161
+ } else if (const auto *TC = FD->getAttr <TargetClonesAttr>()) {
4162
+ for (unsigned I = 0 ; I < TC->featuresStrs_size (); ++I) {
4163
+ if (!TC->isFirstOfVersion (I))
4146
4164
continue ;
4147
- GlobalDecl CurGD{(FD->isDefined () ? FD->getDefinition () : FD),
4148
- VersionIndex};
4149
- StringRef Version = TC->getFeatureStr (VersionIndex);
4150
- StringRef MangledName = getMangledName (CurGD);
4151
- llvm::Constant *Func = GetGlobalValue (MangledName);
4152
- if (!Func) {
4153
- if (FD->isDefined ()) {
4154
- EmitGlobalFunctionDefinition (CurGD, nullptr );
4155
- Func = GetGlobalValue (MangledName);
4156
- } else {
4157
- const CGFunctionInfo &FI =
4158
- getTypes ().arrangeGlobalDeclaration (CurGD);
4159
- llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4160
- Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4161
- /* DontDefer=*/ false , ForDefinition);
4162
- }
4163
- assert (Func && " This should have just been created" );
4164
- }
4165
4165
4166
+ llvm::Function *Func = createFunction (FD, I);
4167
+ StringRef Version = TC->getFeatureStr (I);
4166
4168
StringRef Architecture;
4167
4169
llvm::SmallVector<StringRef, 1 > Feature;
4168
4170
@@ -4180,16 +4182,23 @@ void CodeGenModule::emitMultiVersionFunctions() {
4180
4182
Feature.push_back (Version);
4181
4183
}
4182
4184
4183
- Options.emplace_back (cast<llvm::Function>( Func) , Architecture, Feature);
4185
+ Options.emplace_back (Func, Architecture, Feature);
4184
4186
}
4185
4187
} else {
4186
4188
assert (0 && " Expected a target or target_clones multiversion function" );
4187
4189
continue ;
4188
4190
}
4189
4191
4190
- if (!EmitResolver )
4192
+ if (!ShouldEmitResolver )
4191
4193
continue ;
4192
4194
4195
+ if (!HasDefaultDecl) {
4196
+ FunctionDecl *NewFD = createDefaultTargetVersionFrom (FD);
4197
+ llvm::Function *Func = createFunction (NewFD);
4198
+ llvm::SmallVector<StringRef, 1 > Feats;
4199
+ Options.emplace_back (Func, /* Architecture*/ " " , Feats);
4200
+ }
4201
+
4193
4202
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
4194
4203
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
4195
4204
ResolverConstant = IFunc->getResolver ();
@@ -4480,7 +4489,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
4480
4489
4481
4490
if (FD->isMultiVersion ()) {
4482
4491
UpdateMultiVersionNames (GD, FD, MangledName);
4483
- if (!IsForDefinition)
4492
+ if (FD->isTargetVersionMultiVersion () && !FD->isUsed ())
4493
+ AddDeferredMultiVersionResolverToEmit (GD);
4494
+ else if (!IsForDefinition)
4484
4495
return GetOrCreateMultiVersionResolver (GD);
4485
4496
}
4486
4497
}
0 commit comments