[NFC][Clang][FMV] Make FMV priority data type future proof. (#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.
This commit is contained in:
parent
36c37b019b
commit
3ab64c5b29
@ -1551,8 +1551,8 @@ public:
|
||||
|
||||
// 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*)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -123,7 +123,7 @@ public:
|
||||
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);
|
||||
|
@ -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 {
|
||||
|
@ -388,7 +388,7 @@ public:
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -1930,7 +1930,7 @@ public:
|
||||
|
||||
/// 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;
|
||||
|
@ -1126,7 +1126,9 @@ public:
|
||||
|
||||
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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user