https://github.com/labrinea created https://github.com/llvm/llvm-project/pull/150079
FMV priority is the returned value of a polymorphic function. On RISC-V and X86 targets a 32-bit value is enough. On AArch64 we currently need 64 bits and we will soon exceed that. APInt seems to be a suitable replacement for uint64_t, presumably with minimal compile time overhead. It allows bit manipulation, comparison and variable bit width. >From b62c8913fc17b7f85f7e81e02e6bb99eee1ec2a9 Mon Sep 17 00:00:00 2001 From: Alexandros Lamprineas <alexandros.lamprin...@arm.com> Date: Tue, 22 Jul 2025 17:49:46 +0100 Subject: [PATCH] [NFC][Clang][FMV] Make FMV priority data type future proof. FMV priority is the returned value of a polymorphic function. On RISC-V and X86 targets a 32-bit value is enough. On AArch64 we currently need 64 bits and we will soon exceed that. APInt seems to be a suitable replacement for uint64_t, presumably with minimal compile time overhead. It allows bit manipulation, comparison and variable bit width. --- clang/include/clang/Basic/TargetInfo.h | 4 ++-- clang/lib/Basic/Targets/AArch64.cpp | 3 ++- clang/lib/Basic/Targets/AArch64.h | 2 +- clang/lib/Basic/Targets/RISCV.cpp | 9 +++++---- clang/lib/Basic/Targets/RISCV.h | 2 +- clang/lib/Basic/Targets/X86.cpp | 8 ++++---- clang/lib/Basic/Targets/X86.h | 2 +- clang/lib/CodeGen/ABIInfo.cpp | 4 ++-- clang/lib/CodeGen/CodeGenModule.cpp | 7 ++++--- clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 4 ++-- llvm/include/llvm/Analysis/TargetTransformInfo.h | 2 +- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h | 4 +++- llvm/include/llvm/TargetParser/AArch64TargetParser.h | 4 ++-- llvm/lib/Analysis/TargetTransformInfo.cpp | 2 +- .../Target/AArch64/AArch64TargetTransformInfo.cpp | 2 +- llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h | 2 +- llvm/lib/TargetParser/AArch64TargetParser.cpp | 12 ++++++------ llvm/lib/Transforms/IPO/GlobalOpt.cpp | 12 ++++++------ 18 files changed, 45 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 8b66c73474704..abfbdfaa9c0d5 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1551,8 +1551,8 @@ class TargetInfo : public TransferrableTargetInfo, // Return the target-specific priority for features/cpus/vendors so // that they can be properly sorted for checking. - virtual uint64_t getFMVPriority(ArrayRef<StringRef> Features) const { - return 0; + virtual llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const { + return llvm::APInt::getZero(32); } // Validate the contents of the __builtin_cpu_is(const char*) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 72d2e5fcf4619..2b023e5fdb7d8 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -786,7 +786,8 @@ AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts, return std::nullopt; } -uint64_t AArch64TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { +llvm::APInt +AArch64TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { return llvm::AArch64::getFMVPriority(Features); } diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index f4277e95b19be..dfd89beeee2f3 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -152,7 +152,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; bool setCPU(const std::string &Name) override; - uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override; + llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override; bool useFP16ConversionIntrinsics() const override { return false; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 8a28c0788aad7..a6a5ec4b325bc 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -568,7 +568,8 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { return Ret; } -uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { +llvm::APInt +RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { // Priority is explicitly specified on RISC-V unlike on other targets, where // it is derived by all the features of a specific version. Therefore if a // feature contains the priority string, then return it immediately. @@ -580,12 +581,12 @@ uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { Feature = RHS; else continue; - uint64_t Priority; + unsigned Priority; if (!Feature.getAsInteger(0, Priority)) - return Priority; + return llvm::APInt(32, Priority); } // Default Priority is zero. - return 0; + return llvm::APInt::getZero(32); } TargetInfo::CallingConvCheckResult diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index 8d629abab7bec..58bfad128ce2c 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -123,7 +123,7 @@ class RISCVTargetInfo : public TargetInfo { void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; bool supportsTargetAttributeTune() const override { return true; } ParsedTargetAttr parseTargetAttr(StringRef Str) const override; - uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override; + llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override; std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { return std::make_pair(32, 32); diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index a1f5aa26ab2ec..24ecec24d2a4a 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -1390,8 +1390,8 @@ static llvm::X86::ProcessorFeatures getFeature(StringRef Name) { // correct, so it asserts if the value is out of range. } -uint64_t X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { - auto getPriority = [](StringRef Feature) -> uint64_t { +llvm::APInt X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { + auto getPriority = [](StringRef Feature) -> unsigned { // Valid CPUs have a 'key feature' that compares just better than its key // feature. using namespace llvm::X86; @@ -1405,11 +1405,11 @@ uint64_t X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { return getFeaturePriority(getFeature(Feature)) << 1; }; - uint64_t Priority = 0; + unsigned Priority = 0; for (StringRef Feature : Features) if (!Feature.empty()) Priority = std::max(Priority, getPriority(Feature)); - return Priority; + return llvm::APInt(32, Priority); } bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const { diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index ebc59c92f4c24..eb151034dec85 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -388,7 +388,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { return CPU != llvm::X86::CK_None; } - uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override; + llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override; bool setFPMath(StringRef Name) override; diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index d981d69913632..3ef430e19ebd3 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -218,8 +218,8 @@ void ABIInfo::appendAttributeMangling(StringRef AttrStr, // only have "+" prefixes here. assert(LHS.starts_with("+") && RHS.starts_with("+") && "Features should always have a prefix."); - return TI.getFMVPriority({LHS.substr(1)}) > - TI.getFMVPriority({RHS.substr(1)}); + return TI.getFMVPriority({LHS.substr(1)}) + .ugt(TI.getFMVPriority({RHS.substr(1)})); }); bool IsFirst = true; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 236cc3d9e8907..834b1c067d84c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4418,8 +4418,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, llvm::Function *NewFn); -static uint64_t getFMVPriority(const TargetInfo &TI, - const CodeGenFunction::FMVResolverOption &RO) { +static llvm::APInt +getFMVPriority(const TargetInfo &TI, + const CodeGenFunction::FMVResolverOption &RO) { llvm::SmallVector<StringRef, 8> Features{RO.Features}; if (RO.Architecture) Features.push_back(*RO.Architecture); @@ -4544,7 +4545,7 @@ void CodeGenModule::emitMultiVersionFunctions() { llvm::stable_sort( Options, [&TI](const CodeGenFunction::FMVResolverOption &LHS, const CodeGenFunction::FMVResolverOption &RHS) { - return getFMVPriority(TI, LHS) > getFMVPriority(TI, RHS); + return getFMVPriority(TI, LHS).ugt(getFMVPriority(TI, RHS)); }); CodeGenFunction CGF(*this); CGF.EmitMultiVersionResolver(ResolverFunc, Options); diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index 7e6a47fd7c103..2e6b4b3eb10f1 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -8112,7 +8112,7 @@ Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) { llvm::Value * CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { - uint64_t FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs); + llvm::APInt FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs); Value *Result = Builder.getTrue(); if (FeaturesMask != 0) { // Get features from structure in runtime library @@ -8128,7 +8128,7 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 0)}); Value *Features = Builder.CreateAlignedLoad(Int64Ty, CpuFeatures, CharUnits::fromQuantity(8)); - Value *Mask = Builder.getInt64(FeaturesMask); + Value *Mask = Builder.getInt(FeaturesMask.trunc(64)); Value *Bitset = Builder.CreateAnd(Features, Mask); Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask); Result = Builder.CreateAnd(Result, Cmp); diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index 98b793aace7a3..7928835f7f84d 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1930,7 +1930,7 @@ class TargetTransformInfo { /// Returns a bitmask constructed from the target-features or fmv-features /// metadata of a function. - LLVM_ABI uint64_t getFeatureMask(const Function &F) const; + LLVM_ABI APInt getFeatureMask(const Function &F) const; /// Returns true if this is an instance of a function with multiple versions. LLVM_ABI bool isMultiversionedFunction(const Function &F) const; diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index ddc8a5eaffa94..2ea87b3c62895 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1126,7 +1126,9 @@ class TargetTransformInfoImplBase { virtual bool hasArmWideBranch(bool) const { return false; } - virtual uint64_t getFeatureMask(const Function &F) const { return 0; } + virtual APInt getFeatureMask(const Function &F) const { + return APInt::getZero(32); + } virtual bool isMultiversionedFunction(const Function &F) const { return false; diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index 59e8117ccb730..8e83b04681f58 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -276,14 +276,14 @@ LLVM_ABI bool isX18ReservedByDefault(const Triple &TT); // For a given set of feature names, which can be either target-features, or // fmv-features metadata, expand their dependencies and then return a bitmask // corresponding to the entries of AArch64::FeatPriorities. -LLVM_ABI uint64_t getFMVPriority(ArrayRef<StringRef> Features); +LLVM_ABI APInt getFMVPriority(ArrayRef<StringRef> Features); // For a given set of FMV feature names, expand their dependencies and then // return a bitmask corresponding to the entries of AArch64::CPUFeatures. // The values in CPUFeatures are not bitmasks themselves, they are sequential // (0, 1, 2, 3, ...). The resulting bitmask is used at runtime to test whether // a certain FMV feature is available on the host. -LLVM_ABI uint64_t getCpuSupportsMask(ArrayRef<StringRef> Features); +LLVM_ABI APInt getCpuSupportsMask(ArrayRef<StringRef> Features); LLVM_ABI void PrintSupportedExtensions(); diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 8a470ebf85a16..55ba52a1079ce 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -1423,7 +1423,7 @@ bool TargetTransformInfo::hasArmWideBranch(bool Thumb) const { return TTIImpl->hasArmWideBranch(Thumb); } -uint64_t TargetTransformInfo::getFeatureMask(const Function &F) const { +APInt TargetTransformInfo::getFeatureMask(const Function &F) const { return TTIImpl->getFeatureMask(F); } diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index 90d3d92d6bbf5..40f49dade6131 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -249,7 +249,7 @@ static bool hasPossibleIncompatibleOps(const Function *F) { return false; } -uint64_t AArch64TTIImpl::getFeatureMask(const Function &F) const { +APInt AArch64TTIImpl::getFeatureMask(const Function &F) const { StringRef AttributeStr = isMultiversionedFunction(F) ? "fmv-features" : "target-features"; StringRef FeatureStr = F.getFnAttribute(AttributeStr).getValueAsString(); diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h index b27eb2ef7a39d..7f45177437237 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -89,7 +89,7 @@ class AArch64TTIImpl final : public BasicTTIImplBase<AArch64TTIImpl> { unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override; - uint64_t getFeatureMask(const Function &F) const override; + APInt getFeatureMask(const Function &F) const override; bool isMultiversionedFunction(const Function &F) const override; diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp index 9432fc2c4ac8d..7e3583275a734 100644 --- a/llvm/lib/TargetParser/AArch64TargetParser.cpp +++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp @@ -55,7 +55,7 @@ std::optional<AArch64::FMVInfo> lookupFMVByID(AArch64::ArchExtKind ExtID) { return {}; } -uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) { +APInt AArch64::getFMVPriority(ArrayRef<StringRef> Features) { // Transitively enable the Arch Extensions which correspond to each feature. ExtensionSet FeatureBits; for (const StringRef Feature : Features) { @@ -69,15 +69,15 @@ uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) { } // Construct a bitmask for all the transitively enabled Arch Extensions. - uint64_t PriorityMask = 0; + APInt PriorityMask = APInt::getZero(128); for (const FMVInfo &Info : getFMVInfo()) if (Info.ID && FeatureBits.Enabled.test(*Info.ID)) - PriorityMask |= (1ULL << Info.PriorityBit); + PriorityMask.setBit(Info.PriorityBit); return PriorityMask; } -uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> Features) { +APInt AArch64::getCpuSupportsMask(ArrayRef<StringRef> Features) { // Transitively enable the Arch Extensions which correspond to each feature. ExtensionSet FeatureBits; for (const StringRef Feature : Features) @@ -86,10 +86,10 @@ uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> Features) { FeatureBits.enable(*Info->ID); // Construct a bitmask for all the transitively enabled Arch Extensions. - uint64_t FeaturesMask = 0; + APInt FeaturesMask = APInt::getZero(128); for (const FMVInfo &Info : getFMVInfo()) if (Info.ID && FeatureBits.Enabled.test(*Info.ID)) - FeaturesMask |= (1ULL << Info.FeatureBit); + FeaturesMask.setBit(Info.FeatureBit); return FeaturesMask; } diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 2623be3e88fc0..bdda4980c1005 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2529,7 +2529,7 @@ static bool OptimizeNonTrivialIFuncs( bool Changed = false; // Cache containing the mask constructed from a function's target features. - DenseMap<Function *, uint64_t> FeatureMask; + DenseMap<Function *, APInt> FeatureMask; for (GlobalIFunc &IF : M.ifuncs()) { if (IF.isInterposable()) @@ -2568,7 +2568,7 @@ static bool OptimizeNonTrivialIFuncs( // Sort the callee versions in decreasing priority order. sort(Callees, [&](auto *LHS, auto *RHS) { - return FeatureMask[LHS] > FeatureMask[RHS]; + return FeatureMask[LHS].ugt(FeatureMask[RHS]); }); // Find the callsites and cache the feature mask for each caller. @@ -2591,10 +2591,10 @@ static bool OptimizeNonTrivialIFuncs( // Sort the caller versions in decreasing priority order. sort(Callers, [&](auto *LHS, auto *RHS) { - return FeatureMask[LHS] > FeatureMask[RHS]; + return FeatureMask[LHS].ugt(FeatureMask[RHS]); }); - auto implies = [](uint64_t A, uint64_t B) { return (A & B) == B; }; + auto implies = [](APInt A, APInt B) { return B.isSubsetOf(A); }; // Index to the highest priority candidate. unsigned I = 0; @@ -2603,8 +2603,8 @@ static bool OptimizeNonTrivialIFuncs( assert(I < Callees.size() && "Found callers of equal priority"); Function *Callee = Callees[I]; - uint64_t CallerBits = FeatureMask[Caller]; - uint64_t CalleeBits = FeatureMask[Callee]; + APInt CallerBits = FeatureMask[Caller]; + APInt CalleeBits = FeatureMask[Callee]; // In the case of FMV callers, we know that all higher priority callers // than the current one did not get selected at runtime, which helps _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits