diff --git a/llvm/include/llvm/TargetParser/SubtargetFeature.h b/llvm/include/llvm/TargetParser/SubtargetFeature.h index a48b18745352a..a5bf1ef72fa68 100644 --- a/llvm/include/llvm/TargetParser/SubtargetFeature.h +++ b/llvm/include/llvm/TargetParser/SubtargetFeature.h @@ -20,6 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/bit.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" #include @@ -151,6 +152,18 @@ class FeatureBitset { } return false; } + + template + constexpr void forEachBit(Func func) const { + for (unsigned I = 0; I < MAX_SUBTARGET_WORDS; ++I) { + uint64_t Word = Bits[I]; + while (Word) { + unsigned Bit = llvm::countr_zero(Word); + Word &= Word - 1; + func(I * 64 + Bit); + } + } + } }; /// Class used to store the subtarget bits in the tables created by tablegen. diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp index 89a08327dd259..77ea1bc5aa040 100644 --- a/llvm/lib/MC/MCSubtargetInfo.cpp +++ b/llvm/lib/MC/MCSubtargetInfo.cpp @@ -34,15 +34,32 @@ static const T *Find(StringRef S, ArrayRef A) { } /// For each feature that is (transitively) implied by this feature, set it. -static -void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies, - ArrayRef FeatureTable) { - // OR the Implies bits in outside the loop. This allows the Implies for CPUs - // which might imply features not in FeatureTable to use this. - Bits |= Implies; - for (const SubtargetFeatureKV &FE : FeatureTable) - if (Implies.test(FE.Value)) - SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable); +static void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies, + ArrayRef FeatureTable) { + std::array featureMap; + FeatureBitset Mask; + uint16_t idx = 0; + for (const auto &FE : FeatureTable) { + Mask.set(FE.Value); + featureMap[FE.Value] = idx++; + } + + FeatureBitset impl(Implies); + while (true) { + Bits |= impl; + auto newImplies = Mask & impl; + if (newImplies.none()) { + break; + } + + Mask ^= newImplies; + impl = FeatureBitset(); + + newImplies.forEachBit([&](unsigned Bit) { + unsigned idx = featureMap[Bit]; + impl |= FeatureTable[idx].Implies.getAsBitset(); + }); + } } /// For each feature that (transitively) implies this feature, clear it.