From 88c2af80fac423fc338027c007e1499333f05ddb Mon Sep 17 00:00:00 2001 From: Alexandros Lamprineas Date: Thu, 28 Nov 2024 09:22:05 +0000 Subject: [NFC][clang][FMV][TargetInfo] Refactor API for FMV feature priority. (#116257) Currently we have code with target hooks in CodeGenModule shared between X86 and AArch64 for sorting MultiVersionResolverOptions. Those are used when generating IFunc resolvers for FMV. The RISCV target has different criteria for sorting, therefore it repeats sorting after calling CodeGenFunction::EmitMultiVersionResolver. I am moving the FMV priority logic in TargetInfo, so that it can be implemented by the TargetParser which then makes it possible to query it from llvm. Here is an example why this is handy: https://github.com/llvm/llvm-project/pull/87939 --- clang/lib/CodeGen/CodeGenModule.cpp | 86 ++++++++++++++----------------------- 1 file changed, 32 insertions(+), 54 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 716c43431667..7189a4689e81 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4223,23 +4223,12 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, llvm::Function *NewFn); -static unsigned -TargetMVPriority(const TargetInfo &TI, - const CodeGenFunction::MultiVersionResolverOption &RO) { - unsigned Priority = 0; - unsigned NumFeatures = 0; - for (StringRef Feat : RO.Conditions.Features) { - Priority = std::max(Priority, TI.multiVersionSortPriority(Feat)); - NumFeatures++; - } - - if (!RO.Conditions.Architecture.empty()) - Priority = std::max( - Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture)); - - Priority += TI.multiVersionFeatureCost() * NumFeatures; - - return Priority; +static unsigned getFMVPriority(const TargetInfo &TI, + const CodeGenFunction::FMVResolverOption &RO) { + llvm::SmallVector Features{RO.Features}; + if (RO.Architecture) + Features.push_back(*RO.Architecture); + return TI.getFMVPriority(Features); } // Multiversion functions should be at most 'WeakODRLinkage' so that a different @@ -4285,7 +4274,7 @@ void CodeGenModule::emitMultiVersionFunctions() { // target_version("default")) or target_clones() is present and defined // in this TU. For other architectures it is always emitted. bool ShouldEmitResolver = !getTarget().getTriple().isAArch64(); - SmallVector Options; + SmallVector Options; getContext().forEachMultiversionedFunctionVersion( FD, [&](const FunctionDecl *CurFD) { @@ -4293,20 +4282,17 @@ void CodeGenModule::emitMultiVersionFunctions() { bool IsDefined = CurFD->doesThisDeclarationHaveABody(); if (const auto *TA = CurFD->getAttr()) { - TA->getAddedFeatures(Feats); + assert(getTarget().getTriple().isX86() && "Unsupported target"); + TA->getX86AddedFeatures(Feats); llvm::Function *Func = createFunction(CurFD); - Options.emplace_back(Func, TA->getArchitecture(), Feats); + Options.emplace_back(Func, Feats, TA->getX86Architecture()); } else if (const auto *TVA = CurFD->getAttr()) { if (TVA->isDefaultVersion() && IsDefined) ShouldEmitResolver = true; llvm::Function *Func = createFunction(CurFD); - if (getTarget().getTriple().isRISCV()) { - Feats.push_back(TVA->getName()); - } else { - assert(getTarget().getTriple().isAArch64()); - TVA->getFeatures(Feats); - } - Options.emplace_back(Func, /*Architecture*/ "", Feats); + char Delim = getTarget().getTriple().isAArch64() ? '+' : ','; + TVA->getFeatures(Feats, Delim); + Options.emplace_back(Func, Feats); } else if (const auto *TC = CurFD->getAttr()) { if (IsDefined) ShouldEmitResolver = true; @@ -4315,21 +4301,15 @@ void CodeGenModule::emitMultiVersionFunctions() { continue; llvm::Function *Func = createFunction(CurFD, I); - StringRef Architecture; Feats.clear(); - if (getTarget().getTriple().isAArch64()) - TC->getFeatures(Feats, I); - else if (getTarget().getTriple().isRISCV()) { - StringRef Version = TC->getFeatureStr(I); - Feats.push_back(Version); + if (getTarget().getTriple().isX86()) { + TC->getX86Feature(Feats, I); + Options.emplace_back(Func, Feats, TC->getX86Architecture(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); + char Delim = getTarget().getTriple().isAArch64() ? '+' : ','; + TC->getFeatures(Feats, I, Delim); + Options.emplace_back(Func, Feats); } - Options.emplace_back(Func, Architecture, Feats); } } else llvm_unreachable("unexpected MultiVersionKind"); @@ -4368,9 +4348,9 @@ void CodeGenModule::emitMultiVersionFunctions() { const TargetInfo &TI = getTarget(); llvm::stable_sort( - Options, [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS); + Options, [&TI](const CodeGenFunction::FMVResolverOption &LHS, + const CodeGenFunction::FMVResolverOption &RHS) { + return getFMVPriority(TI, LHS) > getFMVPriority(TI, RHS); }); CodeGenFunction CGF(*this); CGF.EmitMultiVersionResolver(ResolverFunc, Options); @@ -4429,7 +4409,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { ResolverFunc->setComdat( getModule().getOrInsertComdat(ResolverFunc->getName())); - SmallVector Options; + SmallVector Options; const TargetInfo &Target = getTarget(); unsigned Index = 0; for (const IdentifierInfo *II : DD->cpus()) { @@ -4463,25 +4443,23 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { llvm::erase_if(Features, [&Target](StringRef Feat) { return !Target.validateCpuSupports(Feat); }); - Options.emplace_back(cast(Func), StringRef{}, Features); + Options.emplace_back(cast(Func), Features); ++Index; } - llvm::stable_sort( - Options, [](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return llvm::X86::getCpuSupportsMask(LHS.Conditions.Features) > - llvm::X86::getCpuSupportsMask(RHS.Conditions.Features); - }); + llvm::stable_sort(Options, [](const CodeGenFunction::FMVResolverOption &LHS, + const CodeGenFunction::FMVResolverOption &RHS) { + return llvm::X86::getCpuSupportsMask(LHS.Features) > + llvm::X86::getCpuSupportsMask(RHS.Features); + }); // If the list contains multiple 'default' versions, such as when it contains // 'pentium' and 'generic', don't emit the call to the generic one (since we // always run on at least a 'pentium'). We do this by deleting the 'least // advanced' (read, lowest mangling letter). - while (Options.size() > 1 && - llvm::all_of(llvm::X86::getCpuSupportsMask( - (Options.end() - 2)->Conditions.Features), - [](auto X) { return X == 0; })) { + while (Options.size() > 1 && llvm::all_of(llvm::X86::getCpuSupportsMask( + (Options.end() - 2)->Features), + [](auto X) { return X == 0; })) { StringRef LHSName = (Options.end() - 2)->Function->getName(); StringRef RHSName = (Options.end() - 1)->Function->getName(); if (LHSName.compare(RHSName) < 0) -- cgit v1.2.3