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/CodeGenFunction.cpp | 109 ++++++++++++---------------------- 1 file changed, 38 insertions(+), 71 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp') diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index ef6bb4f..f8138e9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2828,23 +2828,17 @@ void CodeGenFunction::EmitKCFIOperandBundle( Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar())); } -llvm::Value *CodeGenFunction::FormAArch64ResolverCondition( - const MultiVersionResolverOption &RO) { - llvm::SmallVector CondFeatures; - for (const StringRef &Feature : RO.Conditions.Features) - CondFeatures.push_back(Feature); - if (!CondFeatures.empty()) { - return EmitAArch64CpuSupports(CondFeatures); - } - return nullptr; +llvm::Value * +CodeGenFunction::FormAArch64ResolverCondition(const FMVResolverOption &RO) { + return RO.Features.empty() ? nullptr : EmitAArch64CpuSupports(RO.Features); } -llvm::Value *CodeGenFunction::FormX86ResolverCondition( - const MultiVersionResolverOption &RO) { +llvm::Value * +CodeGenFunction::FormX86ResolverCondition(const FMVResolverOption &RO) { llvm::Value *Condition = nullptr; - if (!RO.Conditions.Architecture.empty()) { - StringRef Arch = RO.Conditions.Architecture; + if (RO.Architecture) { + StringRef Arch = *RO.Architecture; // If arch= specifies an x86-64 micro-architecture level, test the feature // with __builtin_cpu_supports, otherwise use __builtin_cpu_is. if (Arch.starts_with("x86-64")) @@ -2853,8 +2847,8 @@ llvm::Value *CodeGenFunction::FormX86ResolverCondition( Condition = EmitX86CpuIs(Arch); } - if (!RO.Conditions.Features.empty()) { - llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features); + if (!RO.Features.empty()) { + llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Features); Condition = Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond; } @@ -2884,7 +2878,7 @@ static void CreateMultiVersionResolverReturn(CodeGenModule &CGM, } void CodeGenFunction::EmitMultiVersionResolver( - llvm::Function *Resolver, ArrayRef Options) { + llvm::Function *Resolver, ArrayRef Options) { llvm::Triple::ArchType ArchType = getContext().getTargetInfo().getTriple().getArch(); @@ -2907,26 +2901,8 @@ void CodeGenFunction::EmitMultiVersionResolver( } } -static unsigned getPriorityFromAttrString(StringRef AttrStr) { - SmallVector Attrs; - - AttrStr.split(Attrs, ';'); - - // Default Priority is zero. - unsigned Priority = 0; - for (auto Attr : Attrs) { - if (Attr.consume_front("priority=")) { - unsigned Result; - if (!Attr.getAsInteger(0, Result)) - Priority = Result; - } - } - - return Priority; -} - void CodeGenFunction::EmitRISCVMultiVersionResolver( - llvm::Function *Resolver, ArrayRef Options) { + llvm::Function *Resolver, ArrayRef Options) { if (getContext().getTargetInfo().getTriple().getOS() != llvm::Triple::OSType::Linux) { @@ -2942,20 +2918,10 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( bool HasDefault = false; unsigned DefaultIndex = 0; - SmallVector CurrOptions( - Options); - - llvm::stable_sort( - CurrOptions, [](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return getPriorityFromAttrString(LHS.Conditions.Features[0]) > - getPriorityFromAttrString(RHS.Conditions.Features[0]); - }); - // Check the each candidate function. - for (unsigned Index = 0; Index < CurrOptions.size(); Index++) { + for (unsigned Index = 0; Index < Options.size(); Index++) { - if (CurrOptions[Index].Conditions.Features[0].starts_with("default")) { + if (Options[Index].Features.empty()) { HasDefault = true; DefaultIndex = Index; continue; @@ -2963,15 +2929,6 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( Builder.SetInsertPoint(CurBlock); - std::vector TargetAttrFeats = - getContext() - .getTargetInfo() - .parseTargetAttr(CurrOptions[Index].Conditions.Features[0]) - .Features; - - if (TargetAttrFeats.empty()) - continue; - // FeaturesCondition: The bitmask of the required extension has been // enabled by the runtime object. // (__riscv_feature_bits.features[i] & REQUIRED_BITMASK) == @@ -2994,20 +2951,32 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( // Without checking the length first, we may access an incorrect memory // address when using different versions. llvm::SmallVector CurrTargetAttrFeats; + llvm::SmallVector TargetAttrFeats; - for (auto &Feat : TargetAttrFeats) { - StringRef CurrFeat = Feat; - if (CurrFeat.starts_with('+')) - CurrTargetAttrFeats.push_back(CurrFeat.substr(1)); + for (StringRef Feat : Options[Index].Features) { + std::vector FeatStr = + getContext().getTargetInfo().parseTargetAttr(Feat).Features; + + assert(FeatStr.size() == 1 && "Feature string not delimited"); + + std::string &CurrFeat = FeatStr.front(); + if (CurrFeat[0] == '+') + TargetAttrFeats.push_back(CurrFeat.substr(1)); } + if (TargetAttrFeats.empty()) + continue; + + for (std::string &Feat : TargetAttrFeats) + CurrTargetAttrFeats.push_back(Feat); + Builder.SetInsertPoint(CurBlock); llvm::Value *FeatsCondition = EmitRISCVCpuSupports(CurrTargetAttrFeats); llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver); CGBuilderTy RetBuilder(*this, RetBlock); - CreateMultiVersionResolverReturn( - CGM, Resolver, RetBuilder, CurrOptions[Index].Function, SupportsIFunc); + CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, + Options[Index].Function, SupportsIFunc); llvm::BasicBlock *ElseBlock = createBasicBlock("resolver_else", Resolver); Builder.SetInsertPoint(CurBlock); @@ -3019,9 +2988,8 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( // Finally, emit the default one. if (HasDefault) { Builder.SetInsertPoint(CurBlock); - CreateMultiVersionResolverReturn(CGM, Resolver, Builder, - CurrOptions[DefaultIndex].Function, - SupportsIFunc); + CreateMultiVersionResolverReturn( + CGM, Resolver, Builder, Options[DefaultIndex].Function, SupportsIFunc); return; } @@ -3035,17 +3003,16 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( } void CodeGenFunction::EmitAArch64MultiVersionResolver( - llvm::Function *Resolver, ArrayRef Options) { + llvm::Function *Resolver, ArrayRef Options) { assert(!Options.empty() && "No multiversion resolver options found"); - assert(Options.back().Conditions.Features.size() == 0 && - "Default case must be last"); + assert(Options.back().Features.size() == 0 && "Default case must be last"); bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc(); assert(SupportsIFunc && "Multiversion resolver requires target IFUNC support"); bool AArch64CpuInitialized = false; llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); - for (const MultiVersionResolverOption &RO : Options) { + for (const FMVResolverOption &RO : Options) { Builder.SetInsertPoint(CurBlock); llvm::Value *Condition = FormAArch64ResolverCondition(RO); @@ -3081,7 +3048,7 @@ void CodeGenFunction::EmitAArch64MultiVersionResolver( } void CodeGenFunction::EmitX86MultiVersionResolver( - llvm::Function *Resolver, ArrayRef Options) { + llvm::Function *Resolver, ArrayRef Options) { bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc(); @@ -3090,7 +3057,7 @@ void CodeGenFunction::EmitX86MultiVersionResolver( Builder.SetInsertPoint(CurBlock); EmitX86CpuInit(); - for (const MultiVersionResolverOption &RO : Options) { + for (const FMVResolverOption &RO : Options) { Builder.SetInsertPoint(CurBlock); llvm::Value *Condition = FormX86ResolverCondition(RO); -- cgit v1.1