diff options
author | Alexandros Lamprineas <alexandros.lamprineas@arm.com> | 2024-03-26 11:36:34 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-26 11:36:34 +0000 |
commit | da9ac43433ace54b262cd8552a9fafac21186381 (patch) | |
tree | 7a95b8ed1ccf50df79f6366b9a04b4ae3b9a5371 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | fe97a6148ebce0091c03abd12abd814cb55afe24 (diff) | |
download | llvm-da9ac43433ace54b262cd8552a9fafac21186381.zip llvm-da9ac43433ace54b262cd8552a9fafac21186381.tar.gz llvm-da9ac43433ace54b262cd8552a9fafac21186381.tar.bz2 |
[FMV] Allow mixing target_version with target_clones. (#86493)
The latest ACLE allows it and further clarifies the following
in regards to the combination of the two attributes:
"If the `default` matches with another explicitly provided
version in the same translation unit, then the compiler can
emit only one function instead of the two. The explicitly
provided version shall be preferred."
("default" refers to the default clone here)
https://github.com/ARM-software/acle/pull/310
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 105 |
1 files changed, 50 insertions, 55 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index da411a9..3997da1 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3712,7 +3712,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { if (!FD->doesDeclarationForceExternallyVisibleDefinition() && - !FD->isTargetVersionMultiVersion()) + (!FD->isMultiVersion() || + !FD->getASTContext().getTargetInfo().getTriple().isAArch64())) return; StringRef MangledName = getMangledName(GD); @@ -3994,10 +3995,11 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, auto *Spec = FD->getAttr<CPUSpecificAttr>(); for (unsigned I = 0; I < Spec->cpus_size(); ++I) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - } else if (FD->isTargetClonesMultiVersion()) { - auto *Clone = FD->getAttr<TargetClonesAttr>(); - for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I) - if (Clone->isFirstOfVersion(I)) + } else if (auto *TC = FD->getAttr<TargetClonesAttr>()) { + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) + // AArch64 favors the default target version over the clone if any. + if ((!TC->isDefaultVersion(I) || !getTarget().getTriple().isAArch64()) && + TC->isFirstOfVersion(I)) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); // Ensure that the resolver function is also emitted. GetOrCreateMultiVersionResolver(GD); @@ -4137,57 +4139,49 @@ void CodeGenModule::emitMultiVersionFunctions() { }; bool HasDefaultDecl = !FD->isTargetVersionMultiVersion(); - bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion(); + bool ShouldEmitResolver = + !getContext().getTargetInfo().getTriple().isAArch64(); SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - if (FD->isTargetMultiVersion()) { - getContext().forEachMultiversionedFunctionVersion( - FD, [&](const FunctionDecl *CurFD) { - llvm::SmallVector<StringRef, 8> Feats; - llvm::Function *Func = createFunction(CurFD); - if (const auto *TA = CurFD->getAttr<TargetAttr>()) { - TA->getAddedFeatures(Feats); - Options.emplace_back(Func, TA->getArchitecture(), Feats); - } else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) { - bool HasDefaultDef = TVA->isDefaultVersion() && - CurFD->doesThisDeclarationHaveABody(); - HasDefaultDecl |= TVA->isDefaultVersion(); - ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef); - TVA->getFeatures(Feats); - Options.emplace_back(Func, /*Architecture*/ "", Feats); - } else - llvm_unreachable("unexpected MultiVersionKind"); - }); - } else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) { - for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { - if (!TC->isFirstOfVersion(I)) - continue; + getContext().forEachMultiversionedFunctionVersion( + FD, [&](const FunctionDecl *CurFD) { + llvm::SmallVector<StringRef, 8> Feats; - llvm::Function *Func = createFunction(FD, I); - StringRef Version = TC->getFeatureStr(I); - StringRef Architecture; - llvm::SmallVector<StringRef, 1> Feature; - - if (getTarget().getTriple().isAArch64()) { - if (Version != "default") { - llvm::SmallVector<StringRef, 8> VerFeats; - Version.split(VerFeats, "+"); - for (auto &CurFeat : VerFeats) - Feature.push_back(CurFeat.trim()); - } - } else { - if (Version.starts_with("arch=")) - Architecture = Version.drop_front(sizeof("arch=") - 1); - else if (Version != "default") - Feature.push_back(Version); - } - - Options.emplace_back(Func, Architecture, Feature); - } - } else { - assert(0 && "Expected a target or target_clones multiversion function"); - continue; - } + if (const auto *TA = CurFD->getAttr<TargetAttr>()) { + TA->getAddedFeatures(Feats); + llvm::Function *Func = createFunction(CurFD); + Options.emplace_back(Func, TA->getArchitecture(), Feats); + } else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) { + bool HasDefaultDef = TVA->isDefaultVersion() && + CurFD->doesThisDeclarationHaveABody(); + HasDefaultDecl |= TVA->isDefaultVersion(); + ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef); + TVA->getFeatures(Feats); + llvm::Function *Func = createFunction(CurFD); + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) { + ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody(); + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { + if (!TC->isFirstOfVersion(I)) + continue; + + llvm::Function *Func = createFunction(CurFD, I); + StringRef Architecture; + Feats.clear(); + if (getTarget().getTriple().isAArch64()) + TC->getFeatures(Feats, I); + else { + StringRef Version = TC->getFeatureStr(I); + if (Version.starts_with("arch=")) + Architecture = Version.drop_front(sizeof("arch=") - 1); + else if (Version != "default") + Feats.push_back(Version); + } + Options.emplace_back(Func, Architecture, Feats); + } + } else + llvm_unreachable("unexpected MultiVersionKind"); + }); if (!ShouldEmitResolver) continue; @@ -4378,7 +4372,7 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) { const auto *FD = cast<FunctionDecl>(GD.getDecl()); assert(FD && "Not a FunctionDecl?"); - if (FD->isTargetVersionMultiVersion()) { + if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) { std::string MangledName = getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); if (!DeferredResolversToEmit.insert(MangledName).second) @@ -4489,7 +4483,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( if (FD->isMultiVersion()) { UpdateMultiVersionNames(GD, FD, MangledName); - if (FD->isTargetVersionMultiVersion() && !FD->isUsed()) + if (FD->getASTContext().getTargetInfo().getTriple().isAArch64() && + !FD->isUsed()) AddDeferredMultiVersionResolverToEmit(GD); else if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD); |