diff --git a/include/llvm/MC/MCParser/MCTargetAsmParser.h b/include/llvm/MC/MCParser/MCTargetAsmParser.h index c5683b74c4c..24d064147d0 100644 --- a/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -16,6 +16,7 @@ #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/SMLoc.h" #include #include @@ -202,7 +203,7 @@ public: // The instruction encoding is not valid because it requires some target // features that are not currently enabled. MissingFeatures has a bit set for // each feature that the encoding needs but which is not enabled. - static NearMissInfo getMissedFeature(uint64_t MissingFeatures) { + static NearMissInfo getMissedFeature(const FeatureBitset &MissingFeatures) { NearMissInfo Result; Result.Kind = NearMissFeature; Result.Features = MissingFeatures; @@ -254,7 +255,7 @@ public: // Feature flags required by the instruction, that the current target does // not have. - uint64_t getFeatures() const { + const FeatureBitset& getFeatures() const { assert(Kind == NearMissFeature); return Features; } @@ -304,7 +305,7 @@ private: }; union { - uint64_t Features; + FeatureBitset Features; unsigned PredicateError; MissedOpInfo MissedOperand; TooFewOperandsInfo TooFewOperands; @@ -334,7 +335,7 @@ protected: // Can only create subclasses. MCSubtargetInfo ©STI(); /// AvailableFeatures - The current set of available features. - uint64_t AvailableFeatures = 0; + FeatureBitset AvailableFeatures; /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm = false; @@ -359,8 +360,12 @@ public: const MCSubtargetInfo &getSTI() const; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } + const FeatureBitset& getAvailableFeatures() const { + return AvailableFeatures; + } + void setAvailableFeatures(const FeatureBitset& Value) { + AvailableFeatures = Value; + } bool isParsingInlineAsm () { return ParsingInlineAsm; } void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 01e56778566..fc9565ceafa 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -46,6 +46,15 @@ public: for (auto I : Init) set(I); } + + bool operator < (const FeatureBitset &Other) const { + for (unsigned I = 0, E = size(); I != E; ++I) { + bool LHS = test(I), RHS = Other.test(I); + if (LHS != RHS) + return LHS < RHS; + } + return false; + } }; /// Class used to store the subtarget bits in the tables created by tablegen. diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 66cb9ae572e..7345ff38edb 100644 --- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -4166,7 +4166,8 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc, } } -static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string AArch64MnemonicSpellCheck(StringRef S, + const FeatureBitset &FBS, unsigned VariantID = 0); bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode, @@ -4776,10 +4777,12 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } MCInst Inst; + FeatureBitset MissingFeatures; // First try to match against the secondary set of tables containing the // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2"). unsigned MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1); + MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, + MatchingInlineAsm, 1); // If that fails, try against the alternate table containing long-form NEON: // "fadd v0.2s, v1.2s, v2.2s" @@ -4788,9 +4791,11 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // long-form match also fails. auto ShortFormNEONErrorInfo = ErrorInfo; auto ShortFormNEONMatchResult = MatchResult; + auto ShortFormNEONMissingFeatures = MissingFeatures; MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0); + MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, + MatchingInlineAsm, 0); // Now, both matches failed, and the long-form match failed on the mnemonic // suffix token operand. The short-form match failure is probably more @@ -4800,6 +4805,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ((AArch64Operand &)*Operands[1]).isTokenSuffix()) { MatchResult = ShortFormNEONMatchResult; ErrorInfo = ShortFormNEONErrorInfo; + MissingFeatures = ShortFormNEONMissingFeatures; } } @@ -4818,17 +4824,15 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return false; } case Match_MissingFeature: { - assert(ErrorInfo && "Unknown missing feature!"); + assert(MissingFeatures.any() && "Unknown missing feature!"); // Special case the error message for the very common case where only // a single subtarget feature is missing (neon, e.g.). std::string Msg = "instruction requires:"; - uint64_t Mask = 1; - for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { - if (ErrorInfo & Mask) { + for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { + if (MissingFeatures[i]) { Msg += " "; - Msg += getSubtargetFeatureName(ErrorInfo & Mask); + Msg += getSubtargetFeatureName(i); } - Mask <<= 1; } return Error(IDLoc, Msg); } @@ -5147,7 +5151,7 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) { FeatureBitset ToggleFeatures = EnableFeature ? (~Features & Extension.Features) : ( Features & Extension.Features); - uint64_t Features = + FeatureBitset Features = ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); setAvailableFeatures(Features); break; @@ -5191,7 +5195,7 @@ bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) { FeatureBitset ToggleFeatures = EnableFeature ? (~Features & Extension.Features) : (Features & Extension.Features); - uint64_t Features = + FeatureBitset Features = ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); setAvailableFeatures(Features); return false; @@ -5256,7 +5260,7 @@ bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) { FeatureBitset ToggleFeatures = EnableFeature ? (~Features & Extension.Features) : ( Features & Extension.Features); - uint64_t Features = + FeatureBitset Features = ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); setAvailableFeatures(Features); FoundExtension = true; diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp index fb852da93a9..8cb7a167298 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -187,9 +187,10 @@ public: const MCSubtargetInfo &STI) const; private: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // end anonymous namespace diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index f4068e6289a..60af90d8252 100644 --- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -2671,7 +2671,8 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, return true; } -static std::string AMDGPUMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string AMDGPUMnemonicSpellCheck(StringRef S, + const FeatureBitset &FBS, unsigned VariantID = 0); bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -2717,7 +2718,7 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(IDLoc, "instruction not supported on this GPU"); case Match_MnemonicFail: { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = AMDGPUMnemonicSpellCheck( ((AMDGPUOperand &)*Operands[0]).getToken(), FBS); return Error(IDLoc, "invalid instruction" + Suggestion, diff --git a/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h b/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h index e720289ff79..0201cc0670d 100644 --- a/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h +++ b/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h @@ -64,9 +64,10 @@ public: } protected: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // End namespace llvm diff --git a/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp b/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp index 57f5e4c2ade..2f1f4e7a039 100644 --- a/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp +++ b/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp @@ -64,9 +64,10 @@ private: uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index ef7f0be9887..76a0665239d 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -504,7 +504,7 @@ class ARMAsmParser : public MCTargetAsmParser { void SwitchMode() { MCSubtargetInfo &STI = copySTI(); - uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); + auto FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); } @@ -6009,7 +6009,8 @@ static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); } -static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, +static void applyMnemonicAliases(StringRef &Mnemonic, + const FeatureBitset &Features, unsigned VariantID); // The GNU assembler has aliases of ldrd and strd with the second register @@ -6067,7 +6068,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // The generic tblgen'erated code does this later, at the start of // MatchInstructionImpl(), but that's too late for aliases that include // any sort of suffix. - uint64_t AvailableFeatures = getAvailableFeatures(); + const FeatureBitset &AvailableFeatures = getAvailableFeatures(); unsigned AssemblerDialect = getParser().getAssemblerDialect(); applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); @@ -9279,7 +9280,7 @@ unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst, return PlainMatchResult; } -static std::string ARMMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string ARMMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID = 0); static const char *getSubtargetFeatureName(uint64_t Val); @@ -9352,7 +9353,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ReportNearMisses(NearMisses, IDLoc, Operands); return true; case Match_MnemonicFail: { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = ARMMnemonicSpellCheck( ((ARMOperand &)*Operands[0]).getToken(), FBS); return Error(IDLoc, "invalid instruction" + Suggestion, @@ -10427,7 +10428,7 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, // variants of an instruction that take 8- and 16-bit immediates, we want // to only report the widest one. std::multimap OperandMissesSeen; - SmallSet FeatureMissesSeen; + SmallSet FeatureMissesSeen; bool ReportedTooFewOperands = false; // Process the near-misses in reverse order, so that we see more general ones @@ -10478,7 +10479,7 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, break; } case NearMissInfo::NearMissFeature: { - uint64_t MissingFeatures = I.getFeatures(); + const FeatureBitset &MissingFeatures = I.getFeatures(); // Don't report the same set of features twice. if (FeatureMissesSeen.count(MissingFeatures)) break; @@ -10486,20 +10487,21 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, // Special case: don't report a feature set which includes arm-mode for // targets that don't have ARM mode. - if ((MissingFeatures & Feature_IsARM) && !hasARM()) + if (MissingFeatures.test(Feature_IsARMBit) && !hasARM()) break; // Don't report any near-misses that both require switching instruction // set, and adding other subtarget features. - if (isThumb() && (MissingFeatures & Feature_IsARM) && - (MissingFeatures & ~Feature_IsARM)) + if (isThumb() && MissingFeatures.test(Feature_IsARMBit) && + MissingFeatures.count() > 1) break; - if (!isThumb() && (MissingFeatures & Feature_IsThumb) && - (MissingFeatures & ~Feature_IsThumb)) + if (!isThumb() && MissingFeatures.test(Feature_IsThumbBit) && + MissingFeatures.count() > 1) break; - if (!isThumb() && (MissingFeatures & Feature_IsThumb2) && - (MissingFeatures & ~(Feature_IsThumb2 | Feature_IsThumb))) + if (!isThumb() && MissingFeatures.test(Feature_IsThumb2Bit) && + (MissingFeatures & ~FeatureBitset({Feature_IsThumb2Bit, + Feature_IsThumbBit})).any()) break; - if (isMClass() && (MissingFeatures & Feature_HasNEON)) + if (isMClass() && MissingFeatures.test(Feature_HasNEONBit)) break; NearMissMessage Message; @@ -10507,14 +10509,10 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, raw_svector_ostream OS(Message.Message); OS << "instruction requires:"; - uint64_t Mask = 1; - for (unsigned MaskPos = 0; MaskPos < (sizeof(MissingFeatures) * 8 - 1); - ++MaskPos) { - if (MissingFeatures & Mask) { - OS << " " << getSubtargetFeatureName(MissingFeatures & Mask); - } - Mask <<= 1; - } + for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) + if (MissingFeatures.test(i)) + OS << ' ' << getSubtargetFeatureName(i); + NearMissesOut.emplace_back(Message); break; @@ -10590,38 +10588,42 @@ void ARMAsmParser::ReportNearMisses(SmallVectorImpl &NearMisses, } } -// FIXME: This structure should be moved inside ARMTargetParser -// when we start to table-generate them, and we can use the ARM -// flags below, that were generated by table-gen. -static const struct { - const unsigned Kind; - const uint64_t ArchCheck; - const FeatureBitset Features; -} Extensions[] = { - { ARM::AEK_CRC, Feature_HasV8, {ARM::FeatureCRC} }, - { ARM::AEK_CRYPTO, Feature_HasV8, - {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, - { ARM::AEK_FP, Feature_HasV8, {ARM::FeatureFPARMv8} }, - { (ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), Feature_HasV7 | Feature_IsNotMClass, - {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM} }, - { ARM::AEK_MP, Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} }, - { ARM::AEK_SIMD, Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, - { ARM::AEK_SEC, Feature_HasV6K, {ARM::FeatureTrustZone} }, - // FIXME: Only available in A-class, isel not predicated - { ARM::AEK_VIRT, Feature_HasV7, {ARM::FeatureVirtualization} }, - { ARM::AEK_FP16, Feature_HasV8_2a, {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} }, - { ARM::AEK_RAS, Feature_HasV8, {ARM::FeatureRAS} }, - // FIXME: Unsupported extensions. - { ARM::AEK_OS, Feature_None, {} }, - { ARM::AEK_IWMMXT, Feature_None, {} }, - { ARM::AEK_IWMMXT2, Feature_None, {} }, - { ARM::AEK_MAVERICK, Feature_None, {} }, - { ARM::AEK_XSCALE, Feature_None, {} }, -}; - /// parseDirectiveArchExtension /// ::= .arch_extension [no]feature bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { + // FIXME: This structure should be moved inside ARMTargetParser + // when we start to table-generate them, and we can use the ARM + // flags below, that were generated by table-gen. + static const struct { + const unsigned Kind; + const FeatureBitset ArchCheck; + const FeatureBitset Features; + } Extensions[] = { + { ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC} }, + { ARM::AEK_CRYPTO, {Feature_HasV8Bit}, + {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, + { ARM::AEK_FP, {Feature_HasV8Bit}, {ARM::FeatureFPARMv8} }, + { (ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), + {Feature_HasV7Bit, Feature_IsNotMClassBit}, + {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM} }, + { ARM::AEK_MP, {Feature_HasV7Bit, Feature_IsNotMClassBit}, + {ARM::FeatureMP} }, + { ARM::AEK_SIMD, {Feature_HasV8Bit}, + {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, + { ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone} }, + // FIXME: Only available in A-class, isel not predicated + { ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization} }, + { ARM::AEK_FP16, {Feature_HasV8_2aBit}, + {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} }, + { ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS} }, + // FIXME: Unsupported extensions. + { ARM::AEK_OS, {}, {} }, + { ARM::AEK_IWMMXT, {}, {} }, + { ARM::AEK_IWMMXT2, {}, {} }, + { ARM::AEK_MAVERICK, {}, {} }, + { ARM::AEK_XSCALE, {}, {} }, + }; + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::Identifier)) @@ -10661,7 +10663,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { ? (~STI.getFeatureBits() & Extension.Features) : ( STI.getFeatureBits() & Extension.Features); - uint64_t Features = + FeatureBitset Features = ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); setAvailableFeatures(Features); return false; diff --git a/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp b/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp index 947095b8da7..f9abe76c976 100644 --- a/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp +++ b/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp @@ -63,9 +63,10 @@ public: const MCSubtargetInfo &STI) const override; private: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // end anonymous namespace diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp index 8c53027bd84..84b9a05b1db 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -377,7 +377,7 @@ void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, State.Bundle = &MI; State.Index = 0; size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1; - uint64_t Features = computeAvailableFeatures(STI.getFeatureBits()); + FeatureBitset Features = computeAvailableFeatures(STI.getFeatureBits()); for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) { MCInst &HMI = const_cast(*I.getInst()); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h index 9c60e963e1f..9e86dc8e498 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h @@ -82,9 +82,10 @@ private: // Return parse bits for instruction `MCI' inside bundle `MCB' uint32_t parseBits(size_t Last, MCInst const &MCB, MCInst const &MCI) const; - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // end namespace llvm diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 6de9e44a059..59df173eee9 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -6321,7 +6321,7 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, return false; } -static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID = 0); bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -6334,7 +6334,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); return Error(NameLoc, "unknown instruction" + Suggestion); } diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index cd589013dba..3bf5e1ed40d 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -1128,7 +1128,7 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, } } -static std::string PPCMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID = 0); bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -1147,7 +1147,7 @@ bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_MissingFeature: return Error(IDLoc, "instruction use requires an option to be enabled"); case Match_MnemonicFail: { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = PPCMnemonicSpellCheck( ((PPCOperand &)*Operands[0]).getToken(), FBS); return Error(IDLoc, "invalid instruction" + Suggestion, diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h index 64122a7e8d5..1324faa1255 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h @@ -98,9 +98,10 @@ public: unsigned getInstSizeInBytes(const MCInst &MI) const; private: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // namespace llvm diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index a1bff894aed..914efd6524c 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -645,7 +645,8 @@ bool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, return Error(StartLoc, "invalid register name"); } -static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, +static void applyMnemonicAliases(StringRef &Mnemonic, + const FeatureBitset &Features, unsigned VariantID); bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info, diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp index 8cb9108b49f..7e908011bd5 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -83,9 +83,10 @@ public: const MCSubtargetInfo &STI) const; private: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // end anonymous namespace diff --git a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index a9741bbda4d..ea6b28e8c68 100644 --- a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -1180,8 +1180,10 @@ bool SystemZAsmParser::parseOperand(OperandVector &Operands, // features to be available during the operand check, or else we will fail to // find the custom parser, and then we will later get an InvalidOperand error // instead of a MissingFeature errror. - uint64_t AvailableFeatures = getAvailableFeatures(); - setAvailableFeatures(~(uint64_t)0); + FeatureBitset AvailableFeatures = getAvailableFeatures(); + FeatureBitset All; + All.set(); + setAvailableFeatures(All); OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); setAvailableFeatures(AvailableFeatures); if (ResTy == MatchOperand_Success) @@ -1232,7 +1234,8 @@ bool SystemZAsmParser::parseOperand(OperandVector &Operands, return false; } -static std::string SystemZMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string SystemZMnemonicSpellCheck(StringRef S, + const FeatureBitset &FBS, unsigned VariantID = 0); bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -1243,8 +1246,9 @@ bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst Inst; unsigned MatchResult; + FeatureBitset MissingFeatures; MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); + MissingFeatures, MatchingInlineAsm); switch (MatchResult) { case Match_Success: Inst.setLoc(IDLoc); @@ -1252,17 +1256,15 @@ bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return false; case Match_MissingFeature: { - assert(ErrorInfo && "Unknown missing feature!"); + assert(MissingFeatures.any() && "Unknown missing feature!"); // Special case the error message for the very common case where only // a single subtarget feature is missing std::string Msg = "instruction requires:"; - uint64_t Mask = 1; - for (unsigned I = 0; I < sizeof(ErrorInfo) * 8 - 1; ++I) { - if (ErrorInfo & Mask) { + for (unsigned I = 0, E = MissingFeatures.size(); I != E; ++I) { + if (MissingFeatures[I]) { Msg += " "; - Msg += getSubtargetFeatureName(ErrorInfo & Mask); + Msg += getSubtargetFeatureName(I); } - Mask <<= 1; } return Error(IDLoc, Msg); } @@ -1281,7 +1283,7 @@ bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } case Match_MnemonicFail: { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = SystemZMnemonicSpellCheck( ((SystemZOperand &)*Operands[0]).getToken(), FBS); return Error(IDLoc, "invalid instruction" + Suggestion, diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp index 6503bb8be68..a5ccf4f68ff 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -143,9 +143,10 @@ private: } private: - uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; - void verifyInstructionPredicates(const MCInst &MI, - uint64_t AvailableFeatures) const; + FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; + void + verifyInstructionPredicates(const MCInst &MI, + const FeatureBitset &AvailableFeatures) const; }; } // end anonymous namespace diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index cb5712ccd86..46f32e6092c 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -89,13 +89,14 @@ private: } unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst, - uint64_t &ErrorInfo, bool matchingInlineAsm, - unsigned VariantID = 0) { + uint64_t &ErrorInfo, FeatureBitset &MissingFeatures, + bool matchingInlineAsm, unsigned VariantID = 0) { // In Code16GCC mode, match as 32-bit. if (Code16GCC) SwitchMode(X86::Mode32Bit); unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo, - matchingInlineAsm, VariantID); + MissingFeatures, matchingInlineAsm, + VariantID); if (Code16GCC) SwitchMode(X86::Mode16Bit); return rv; @@ -874,7 +875,7 @@ private: void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands, MCStreamer &Out, bool MatchingInlineAsm); - bool ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, + bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures, bool MatchingInlineAsm); bool MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -913,7 +914,7 @@ private: MCSubtargetInfo &STI = copySTI(); FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit}); FeatureBitset OldMode = STI.getFeatureBits() & AllModes; - uint64_t FB = ComputeAvailableFeatures( + FeatureBitset FB = ComputeAvailableFeatures( STI.ToggleFeature(OldMode.flip(mode))); setAvailableFeatures(FB); @@ -2906,17 +2907,16 @@ void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, } } -bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, +bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, + const FeatureBitset &MissingFeatures, bool MatchingInlineAsm) { - assert(ErrorInfo && "Unknown missing feature!"); + assert(MissingFeatures.any() && "Unknown missing feature!"); SmallString<126> Msg; raw_svector_ostream OS(Msg); OS << "instruction requires:"; - uint64_t Mask = 1; - for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { - if (ErrorInfo & Mask) - OS << ' ' << getSubtargetFeatureName(ErrorInfo & Mask); - Mask <<= 1; + for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { + if (MissingFeatures[i]) + OS << ' ' << getSubtargetFeatureName(i); } return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm); } @@ -2953,8 +2953,9 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, Inst.setFlags(Prefixes); // First, try a direct match. - switch (MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm, - isParsingIntelSyntax())) { + FeatureBitset MissingFeatures; + switch (MatchInstruction(Operands, Inst, ErrorInfo, MissingFeatures, + MatchingInlineAsm, isParsingIntelSyntax())) { default: llvm_unreachable("Unexpected match result!"); case Match_Success: if (!MatchingInlineAsm && validateInstruction(Inst, Operands)) @@ -2972,7 +2973,7 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, Opcode = Inst.getOpcode(); return false; case Match_MissingFeature: - return ErrorMissingFeature(IDLoc, ErrorInfo, MatchingInlineAsm); + return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm); case Match_InvalidOperand: WasOriginallyInvalidOperand = true; break; @@ -3002,16 +3003,17 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, // Check for the various suffix matches. uint64_t ErrorInfoIgnore; - uint64_t ErrorInfoMissingFeature = 0; // Init suppresses compiler warnings. + FeatureBitset ErrorInfoMissingFeatures; // Init suppresses compiler warnings. unsigned Match[4]; for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) { Tmp.back() = Suffixes[I]; Match[I] = MatchInstruction(Operands, Inst, ErrorInfoIgnore, - MatchingInlineAsm, isParsingIntelSyntax()); + MissingFeatures, MatchingInlineAsm, + isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match[I] == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfoIgnore; + ErrorInfoMissingFeatures = MissingFeatures; } // Restore the old token. @@ -3088,8 +3090,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, // missing feature. if (std::count(std::begin(Match), std::end(Match), Match_MissingFeature) == 1) { - ErrorInfo = ErrorInfoMissingFeature; - return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, + ErrorInfo = Match_MissingFeature; + return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures, MatchingInlineAsm); } @@ -3153,7 +3155,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, } SmallVector Match; - uint64_t ErrorInfoMissingFeature = 0; + FeatureBitset ErrorInfoMissingFeatures; + FeatureBitset MissingFeatures; // If unsized push has immediate operand we should default the default pointer // size for the size. @@ -3173,7 +3176,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, Op.setTokenValue(Tmp); // Do match in ATT mode to allow explicit suffix usage. Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo, - MatchingInlineAsm, + MissingFeatures, MatchingInlineAsm, false /*isParsingIntelSyntax()*/)); Op.setTokenValue(Base); } @@ -3190,13 +3193,14 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, uint64_t ErrorInfoIgnore; unsigned LastOpcode = Inst.getOpcode(); unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore, - MatchingInlineAsm, isParsingIntelSyntax()); + MissingFeatures, MatchingInlineAsm, + isParsingIntelSyntax()); if (Match.empty() || LastOpcode != Inst.getOpcode()) Match.push_back(M); // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfoIgnore; + ErrorInfoMissingFeatures = MissingFeatures; } // Restore the size of the unsized memory operand if we modified it. @@ -3208,10 +3212,11 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, // matching with the unsized operand. if (Match.empty()) { Match.push_back(MatchInstruction( - Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax())); + Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm, + isParsingIntelSyntax())); // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfo; + ErrorInfoMissingFeatures = MissingFeatures; } // Restore the size of the unsized memory operand if we modified it. @@ -3233,7 +3238,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, UnsizedMemOp->getMemFrontendSize()) { UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize(); unsigned M = MatchInstruction( - Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax()); + Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm, + isParsingIntelSyntax()); if (M == Match_Success) NumSuccessfulMatches = 1; @@ -3273,8 +3279,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, // missing feature. if (std::count(std::begin(Match), std::end(Match), Match_MissingFeature) == 1) { - ErrorInfo = ErrorInfoMissingFeature; - return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, + ErrorInfo = Match_MissingFeature; + return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures, MatchingInlineAsm); } diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index c1440169933..5a56d6494a6 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1473,7 +1473,6 @@ void AsmMatcherInfo::buildInfo() { for (const auto &Pair : SubtargetFeatures) LLVM_DEBUG(Pair.second.dump()); #endif // NDEBUG - assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); bool ReportMultipleNearMisses = @@ -2675,7 +2674,7 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; // FIXME: Totally just a placeholder name to get the algorithm working. - OS << " case " << SFI.getEnumName() << ": return \"" + OS << " case " << SFI.getEnumBitName() << ": return \"" << SFI.TheDef->getValueAsString("PredicateName") << "\";\n"; } OS << " default: return \"(unknown)\";\n"; @@ -2691,7 +2690,10 @@ static std::string GetAliasRequiredFeatures(Record *R, const AsmMatcherInfo &Info) { std::vector ReqFeatures = R->getValueAsListOfDefs("Predicates"); std::string Result; - unsigned NumFeatures = 0; + + if (ReqFeatures.empty()) + return Result; + for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); @@ -2699,15 +2701,12 @@ static std::string GetAliasRequiredFeatures(Record *R, PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + "' is not marked as an AssemblerPredicate!"); - if (NumFeatures) - Result += '|'; + if (i) + Result += " && "; - Result += F->getEnumName(); - ++NumFeatures; + Result += "Features.test(" + F->getEnumBitName() + ')'; } - if (NumFeatures > 1) - Result = '(' + Result + ')'; return Result; } @@ -2763,7 +2762,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, if (!MatchCode.empty()) MatchCode += "else "; - MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n"; + MatchCode += "if (" + FeatureMask + ")\n"; MatchCode += " Mnemonic = \""; MatchCode += R->getValueAsString("ToMnemonic"); MatchCode += "\";\n"; @@ -2798,7 +2797,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "uint64_t Features, unsigned VariantID) {\n"; + "const FeatureBitset &Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2823,7 +2822,9 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, const AsmMatcherInfo &Info, StringRef ClassName, StringToOffsetTable &StringTable, - unsigned MaxMnemonicIndex, bool HasMnemonicFirst) { + unsigned MaxMnemonicIndex, + unsigned MaxFeaturesIndex, + bool HasMnemonicFirst) { unsigned MaxMask = 0; for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) { MaxMask |= OMI.OperandMask; @@ -2832,14 +2833,14 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) - << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; + OS << " " << getMinimalTypeForRange(MaxMask) + << " OperandMask;\n"; OS << " " << getMinimalTypeForRange(std::distance( Info.Classes.begin(), Info.Classes.end())) << " Class;\n"; - OS << " " << getMinimalTypeForRange(MaxMask) - << " OperandMask;\n\n"; + OS << " " << getMinimalTypeForRange(MaxFeaturesIndex) + << " RequiredFeaturesIdx;\n\n"; OS << " StringRef getMnemonic() const {\n"; OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; OS << " MnemonicTable[Mnemonic]);\n"; @@ -2865,29 +2866,18 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, OS << "static const OperandMatchEntry OperandMatchTable[" << Info.OperandMatchInfo.size() << "] = {\n"; - OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n"; + OS << " /* Operand List Mnemonic, Mask, Operand Class, Features */\n"; for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) { const MatchableInfo &II = *OMI.MI; OS << " { "; - // Write the required features mask. - if (!II.RequiredFeatures.empty()) { - for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { - if (i) OS << "|"; - OS << II.RequiredFeatures[i]->getEnumName(); - } - } else - OS << "0"; - // Store a pascal-style length byte in the mnemonic. std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); - OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + OS << StringTable.GetOrAddStringOffset(LenMnemonic, false) << " /* " << II.Mnemonic << " */, "; - OS << OMI.CI->Name; - - OS << ", " << OMI.OperandMask; + OS << OMI.OperandMask; OS << " /* "; bool printComma = false; for (int i = 0, e = 31; i !=e; ++i) @@ -2897,7 +2887,17 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, OS << i; printComma = true; } - OS << " */"; + OS << " */, "; + + OS << OMI.CI->Name; + + // Write the required features mask. + OS << ", AMFBS"; + if (II.RequiredFeatures.empty()) + OS << "_None"; + else + for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) + OS << '_' << II.RequiredFeatures[i]->TheDef->getName(); OS << " },\n"; } @@ -2933,7 +2933,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " const FeatureBitset &AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()" @@ -2967,8 +2967,10 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit check that the required features are available. OS << " // check if the available features match\n"; + OS << " const FeatureBitset &RequiredFeatures = " + "FeatureBitsets[it->RequiredFeaturesIdx];\n"; OS << " if (!ParseForAllFeatures && (AvailableFeatures & " - "it->RequiredFeatures) != it->RequiredFeatures)\n"; + "RequiredFeatures) != RequiredFeatures)\n"; OS << " continue;\n\n"; // Emit check to ensure the operand number matches. @@ -3034,7 +3036,8 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target, static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target, unsigned VariantCount) { OS << "static std::string " << Target.getName() - << "MnemonicSpellCheck(StringRef S, uint64_t FBS, unsigned VariantID) {\n"; + << "MnemonicSpellCheck(StringRef S, const FeatureBitset &FBS," + << " unsigned VariantID) {\n"; if (!VariantCount) OS << " return \"\";"; else { @@ -3055,7 +3058,9 @@ static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target, OS << " }\n\n"; OS << " for (auto I = Start; I < End; I++) {\n"; OS << " // Ignore unsupported instructions.\n"; - OS << " if ((FBS & I->RequiredFeatures) != I->RequiredFeatures)\n"; + OS << " const FeatureBitset &RequiredFeatures = " + "FeatureBitsets[I->RequiredFeaturesIdx];\n"; + OS << " if ((FBS & RequiredFeatures) != RequiredFeatures)\n"; OS << " continue;\n"; OS << "\n"; OS << " StringRef T = I->getMnemonic();\n"; @@ -3103,6 +3108,14 @@ static void emitMatchClassKindNames(std::forward_list &Infos, OS << "#endif // NDEBUG\n"; } +static std::string +getNameForFeatureBitset(const std::vector &FeatureBitset) { + std::string Name = "AMFBS"; + for (const auto &Feature : FeatureBitset) + Name += ("_" + Feature->getName()).str(); + return Name; +} + void AsmMatcherEmitter::run(raw_ostream &OS) { CodeGenTarget Target(Records); Record *AsmParser = Target.getAsmParser(); @@ -3174,7 +3187,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; + OS << " FeatureBitset ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; if (HasOptionalOperands) { OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" @@ -3192,9 +3205,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (ReportMultipleNearMisses) OS << " SmallVectorImpl *NearMisses,\n"; else - OS << " uint64_t &ErrorInfo,\n"; + OS << " uint64_t &ErrorInfo,\n" + << " FeatureBitset &MissingFeatures,\n"; OS << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; + if (!ReportMultipleNearMisses) + OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" + << " MCInst &Inst,\n" + << " uint64_t &ErrorInfo,\n" + << " bool matchingInlineAsm,\n" + << " unsigned VariantID = 0) {\n" + << " FeatureBitset MissingFeatures;\n" + << " return MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,\n" + << " matchingInlineAsm, VariantID);\n" + << " }\n\n"; + if (!Info.OperandMatchInfo.empty()) { OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; @@ -3219,7 +3244,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_REGISTER_MATCHER\n\n"; // Emit the subtarget feature enumeration. - SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( Info.SubtargetFeatures, OS); // Emit the function to match a register name to number. @@ -3300,6 +3325,56 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { StringTable.EmitString(OS); OS << ";\n\n"; + std::vector> FeatureBitsets; + for (const auto &MI : Info.Matchables) { + if (MI->RequiredFeatures.empty()) + continue; + FeatureBitsets.emplace_back(); + for (unsigned I = 0, E = MI->RequiredFeatures.size(); I != E; ++I) + FeatureBitsets.back().push_back(MI->RequiredFeatures[I]->TheDef); + } + + llvm::sort(FeatureBitsets, [&](const std::vector &A, + const std::vector &B) { + if (A.size() < B.size()) + return true; + if (A.size() > B.size()) + return false; + for (const auto &Pair : zip(A, B)) { + if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName()) + return true; + if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName()) + return false; + } + return false; + }); + FeatureBitsets.erase( + std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), + FeatureBitsets.end()); + OS << "// Feature bitsets.\n" + << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" + << " AMFBS_None,\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; + } + OS << "};\n\n" + << "const static FeatureBitset FeatureBitsets[] {\n" + << " {}, // AMFBS_None\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + OS << " {"; + for (const auto &Feature : FeatureBitset) { + const auto &I = Info.SubtargetFeatures.find(Feature); + assert(I != Info.SubtargetFeatures.end() && "Didn't import predicate?"); + OS << I->second.getEnumBitName() << ", "; + } + OS << "},\n"; + } + OS << "};\n\n"; + // Emit the static match table; unused classes get initialized to 0 which is // guaranteed to be InvalidMatchClass. // @@ -3317,8 +3392,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) - << " RequiredFeatures;\n"; + OS << " " << getMinimalTypeForRange(FeatureBitsets.size()) + << " RequiredFeaturesIdx;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) << " Classes[" << MaxNumOperands << "];\n"; @@ -3363,13 +3438,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << MI->ConversionFnKind << ", "; // Write the required features mask. - if (!MI->RequiredFeatures.empty()) { - for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { - if (i) OS << "|"; - OS << MI->RequiredFeatures[i]->getEnumName(); - } - } else - OS << "0"; + OS << "AMFBS"; + if (MI->RequiredFeatures.empty()) + OS << "_None"; + else + for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) + OS << '_' << MI->RequiredFeatures[i]->TheDef->getName(); OS << ", { "; for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { @@ -3394,7 +3468,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (ReportMultipleNearMisses) OS << " SmallVectorImpl *NearMisses,\n"; else - OS << " uint64_t &ErrorInfo,\n"; + OS << " uint64_t &ErrorInfo,\n" + << " FeatureBitset &MissingFeatures,\n"; OS << " bool matchingInlineAsm, unsigned VariantID) {\n"; if (!ReportMultipleNearMisses) { @@ -3409,7 +3484,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " const FeatureBitset &AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; if (HasMnemonicFirst) { @@ -3433,7 +3508,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " uint64_t MissingFeatures = ~0ULL;\n"; + OS << " MissingFeatures.set();\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0ULL;\n"; @@ -3479,9 +3554,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " for (const MatchEntry *it = MnemonicRange.first, " << "*ie = MnemonicRange.second;\n"; OS << " it != ie; ++it) {\n"; + OS << " const FeatureBitset &RequiredFeatures = " + "FeatureBitsets[it->RequiredFeaturesIdx];\n"; OS << " bool HasRequiredFeatures =\n"; - OS << " (AvailableFeatures & it->RequiredFeatures) == " - "it->RequiredFeatures;\n"; + OS << " (AvailableFeatures & RequiredFeatures) == RequiredFeatures;\n"; OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Trying to match opcode \"\n"; OS << " << MII.getName(it->Opcode) << \"\\n\");\n"; @@ -3640,16 +3716,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (!HasRequiredFeatures) {\n"; if (!ReportMultipleNearMisses) OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " + OS << " FeatureBitset NewMissingFeatures = RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target features: \"\n"; - OS << " << format_hex(NewMissingFeatures, 18)\n"; - OS << " << \"\\n\");\n"; + OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target features:\";\n"; + OS << " for (unsigned I = 0, E = NewMissingFeatures.size(); I != E; ++I)\n"; + OS << " if (NewMissingFeatures[I])\n"; + OS << " dbgs() << ' ' << I;\n"; + OS << " dbgs() << \"\\n\");\n"; if (ReportMultipleNearMisses) { OS << " FeaturesNearMiss = NearMissInfo::getMissedFeature(NewMissingFeatures);\n"; } else { - OS << " if (countPopulation(NewMissingFeatures) <=\n" - " countPopulation(MissingFeatures))\n"; + OS << " if (NewMissingFeatures.count() <=\n" + " MissingFeatures.count())\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; } @@ -3804,15 +3882,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Okay, we had no match. Try to return a useful error code.\n"; OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n"; OS << " return RetCode;\n\n"; - OS << " // Missing feature matches return which features were missing\n"; - OS << " ErrorInfo = MissingFeatures;\n"; + OS << " ErrorInfo = 0;\n"; OS << " return Match_MissingFeature;\n"; } OS << "}\n\n"; if (!Info.OperandMatchInfo.empty()) emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable, - MaxMnemonicIndex, HasMnemonicFirst); + MaxMnemonicIndex, FeatureBitsets.size(), + HasMnemonicFirst); OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index ec16be14c6a..da65763905a 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -15,6 +15,7 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" @@ -228,6 +229,14 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, return Case; } +static std::string +getNameForFeatureBitset(const std::vector &FeatureBitset) { + std::string Name = "CEFBS"; + for (const auto &Feature : FeatureBitset) + Name += ("_" + Feature->getName()).str(); + return Name; +} + void CodeEmitterGen::run(raw_ostream &o) { CodeGenTarget Target(Records); std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); @@ -326,8 +335,8 @@ void CodeEmitterGen::run(raw_ostream &o) { << "#include \n\n"; // Emit the subtarget feature enumeration. - SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures, - o); + SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, + o); // Emit the name table for error messages. o << "#ifndef NDEBUG\n"; @@ -339,35 +348,97 @@ void CodeEmitterGen::run(raw_ostream &o) { Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", SubtargetFeatures, o); - // Emit the predicate verifier. - o << "void " << Target.getName() - << "MCCodeEmitter::verifyInstructionPredicates(\n" - << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n" - << "#ifndef NDEBUG\n" - << " static uint64_t RequiredFeatures[] = {\n"; - unsigned InstIdx = 0; + std::vector> FeatureBitsets; for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - o << " "; + FeatureBitsets.emplace_back(); for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { const auto &I = SubtargetFeatures.find(Predicate); if (I != SubtargetFeatures.end()) - o << I->second.getEnumName() << " | "; + FeatureBitsets.back().push_back(I->second.TheDef); } - o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; + } + + llvm::sort(FeatureBitsets, [&](const std::vector &A, + const std::vector &B) { + if (A.size() < B.size()) + return true; + if (A.size() > B.size()) + return false; + for (const auto &Pair : zip(A, B)) { + if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName()) + return true; + if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName()) + return false; + } + return false; + }); + FeatureBitsets.erase( + std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), + FeatureBitsets.end()); + o << "#ifndef NDEBUG\n" + << "// Feature bitsets.\n" + << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" + << " CEFBS_None,\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; + } + o << "};\n\n" + << "const static FeatureBitset FeatureBitsets[] {\n" + << " {}, // CEFBS_None\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + o << " {"; + for (const auto &Feature : FeatureBitset) { + const auto &I = SubtargetFeatures.find(Feature); + assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); + o << I->second.getEnumBitName() << ", "; + } + o << "},\n"; + } + o << "};\n" + << "#endif // NDEBUG\n\n"; + + + // Emit the predicate verifier. + o << "void " << Target.getName() + << "MCCodeEmitter::verifyInstructionPredicates(\n" + << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n" + << "#ifndef NDEBUG\n" + << " static " << getMinimalTypeForRange(FeatureBitsets.size()) + << " RequiredFeaturesRefs[] = {\n"; + unsigned InstIdx = 0; + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + o << " CEFBS"; + unsigned NumPredicates = 0; + for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) { + o << '_' << I->second.TheDef->getName(); + NumPredicates++; + } + } + if (!NumPredicates) + o << "_None"; + o << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; InstIdx++; } o << " };\n\n"; o << " assert(Inst.getOpcode() < " << InstIdx << ");\n"; - o << " uint64_t MissingFeatures =\n" - << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n" - << " RequiredFeatures[Inst.getOpcode()];\n" - << " if (MissingFeatures) {\n" + o << " const FeatureBitset &RequiredFeatures = " + "FeatureBitsets[RequiredFeaturesRefs[Inst.getOpcode()]];\n"; + o << " FeatureBitset MissingFeatures =\n" + << " (AvailableFeatures & RequiredFeatures) ^\n" + << " RequiredFeatures;\n" + << " if (MissingFeatures.any()) {\n" << " std::ostringstream Msg;\n" << " Msg << \"Attempting to emit \" << " "MCII.getName(Inst.getOpcode()).str()\n" << " << \" instruction but the \";\n" - << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n" - << " if (MissingFeatures & (1ULL << i))\n" + << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n" + << " if (MissingFeatures.test(i))\n" << " Msg << SubtargetFeatureNames[i] << \" \";\n" << " Msg << \"predicate(s) are not met\";\n" << " report_fatal_error(Msg.str());\n" diff --git a/utils/TableGen/SubtargetFeatureInfo.cpp b/utils/TableGen/SubtargetFeatureInfo.cpp index b7ed23fff87..edf0b4a01c6 100644 --- a/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/utils/TableGen/SubtargetFeatureInfo.cpp @@ -44,20 +44,6 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { return SubtargetFeatures; } -void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( - SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { - OS << "// Flags for subtarget features that participate in " - << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag : " - << getMinimalTypeForEnumBitfield(SubtargetFeatures.size()) << " {\n"; - for (const auto &SF : SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; - } - OS << " Feature_None = 0\n"; - OS << "};\n\n"; -} - void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "// Bits for subtarget features that participate in " @@ -120,9 +106,9 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures( void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { - OS << "uint64_t " << TargetName << ClassName << "::\n" + OS << "FeatureBitset " << TargetName << ClassName << "::\n" << FuncName << "(const FeatureBitset& FB) const {\n"; - OS << " uint64_t Features = 0;\n"; + OS << " FeatureBitset Features;\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -156,7 +142,7 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( } while (true); OS << ")\n"; - OS << " Features |= " << SFI.getEnumName() << ";\n"; + OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n"; } OS << " return Features;\n"; OS << "}\n\n"; diff --git a/utils/TableGen/SubtargetFeatureInfo.h b/utils/TableGen/SubtargetFeatureInfo.h index 7113fc67b78..d72f8b93461 100644 --- a/utils/TableGen/SubtargetFeatureInfo.h +++ b/utils/TableGen/SubtargetFeatureInfo.h @@ -53,13 +53,6 @@ struct SubtargetFeatureInfo { static std::vector> getAll(const RecordKeeper &Records); - /// Emit the subtarget feature flag definitions. - /// - /// This version emits the bit value for the feature and is therefore limited - /// to 64 feature bits. - static void emitSubtargetFeatureFlagEnumeration( - SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); - /// Emit the subtarget feature flag definitions. /// /// This version emits the bit index for the feature and can therefore support