diff options
Diffstat (limited to 'utils')
68 files changed, 1663 insertions, 885 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 5b4229e64682..146d10835b8d 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1,9 +1,8 @@ //===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -1073,8 +1072,9 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const { // handle, the target should be refactored to use operands instead of // modifiers. // - // Also, check for instructions which reference the operand multiple times; - // this implies a constraint we would not honor. + // Also, check for instructions which reference the operand multiple times, + // if they don't define a custom AsmMatcher: this implies a constraint that + // the built-in matching code would not honor. std::set<std::string> OperandNames; for (const AsmOperand &Op : AsmOperands) { StringRef Tok = Op.Token; @@ -1084,7 +1084,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const { "' not supported by asm matcher. Mark isCodeGenOnly!"); // Verify that any operand is only mentioned once. // We reject aliases and ignore instructions for now. - if (!IsAlias && Tok[0] == '$' && !OperandNames.insert(Tok).second) { + if (!IsAlias && TheDef->getValueAsString("AsmMatchConverter").empty() && + Tok[0] == '$' && !OperandNames.insert(Tok).second) { LLVM_DEBUG({ errs() << "warning: '" << TheDef->getName() << "': " << "ignoring instruction with tied operand '" @@ -1160,8 +1161,9 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { // use it, else just fall back to the underlying register class. const RecordVal *R = Rec->getValue("ParserMatchClass"); if (!R || !R->getValue()) - PrintFatalError("Record `" + Rec->getName() + - "' does not have a ParserMatchClass!\n"); + PrintFatalError(Rec->getLoc(), + "Record `" + Rec->getName() + + "' does not have a ParserMatchClass!\n"); if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) { Record *MatchClass = DI->getDef(); @@ -1473,7 +1475,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 = @@ -1928,10 +1929,11 @@ getConverterOperandID(const std::string &Name, return ID; } -static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::vector<std::unique_ptr<MatchableInfo>> &Infos, - bool HasMnemonicFirst, bool HasOptionalOperands, - raw_ostream &OS) { +static unsigned +emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, + std::vector<std::unique_ptr<MatchableInfo>> &Infos, + bool HasMnemonicFirst, bool HasOptionalOperands, + raw_ostream &OS) { SmallSetVector<CachedHashString, 16> OperandConversionKinds; SmallSetVector<CachedHashString, 16> InstructionConversionKinds; std::vector<std::vector<uint8_t> > ConversionTable; @@ -2337,6 +2339,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Spit out the operand number lookup function. OS << OpOS.str(); + + return ConversionTable.size(); } /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. @@ -2675,7 +2679,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 +2695,10 @@ static std::string GetAliasRequiredFeatures(Record *R, const AsmMatcherInfo &Info) { std::vector<Record*> 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 +2706,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 +2767,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 +2802,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 +2827,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 +2838,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 +2871,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 +2892,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 +2938,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 +2972,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 +3041,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 +3063,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 +3113,14 @@ static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos, OS << "#endif // NDEBUG\n"; } +static std::string +getNameForFeatureBitset(const std::vector<Record *> &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(); @@ -3115,10 +3133,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Sort the instruction table using the partial order on classes. We use // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. - std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), - [](const std::unique_ptr<MatchableInfo> &a, - const std::unique_ptr<MatchableInfo> &b){ - return *a < *b;}); + llvm::stable_sort( + Info.Matchables, + [](const std::unique_ptr<MatchableInfo> &a, + const std::unique_ptr<MatchableInfo> &b) { return *a < *b; }); #ifdef EXPENSIVE_CHECKS // Verify that the table is sorted and operator < works transitively. @@ -3174,7 +3192,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 +3210,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (ReportMultipleNearMisses) OS << " SmallVectorImpl<NearMissInfo> *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 +3249,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. @@ -3249,8 +3279,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Generate the convertToMCInst function to convert operands into an MCInst. // Also, generate the convertToMapAndConstraints function for MS-style inline // assembly. The latter doesn't actually generate a MCInst. - emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst, - HasOptionalOperands, OS); + unsigned NumConverters = emitConvertFuncs(Target, ClassName, Info.Matchables, + HasMnemonicFirst, + HasOptionalOperands, OS); // Emit the enumeration for classes which participate in matching. emitMatchClassEnumeration(Target, Info.Classes, OS); @@ -3300,6 +3331,56 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { StringTable.EmitString(OS); OS << ";\n\n"; + std::vector<std::vector<Record *>> 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<Record *> &A, + const std::vector<Record *> &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. // @@ -3315,10 +3396,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; OS << " uint16_t Opcode;\n"; - OS << " " << getMinimalTypeForRange(Info.Matchables.size()) + OS << " " << getMinimalTypeForRange(NumConverters) << " 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 +3444,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 +3474,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (ReportMultipleNearMisses) OS << " SmallVectorImpl<NearMissInfo> *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 +3490,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 +3514,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 +3560,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 +3722,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 +3888,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/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index a8f191181766..05d81f133505 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -1,9 +1,8 @@ //===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -586,11 +585,20 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { O << " case "; if (!Namespace.empty()) O << Namespace << "::"; - O << AltName << ":\n" - << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName - << "[RegNo-1]) &&\n" - << " \"Invalid alt name index for register!\");\n" - << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName + O << AltName << ":\n"; + if (R->isValueUnset("FallbackRegAltNameIndex")) + O << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName + << "[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n"; + else { + O << " if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName + << "[RegNo-1]))\n" + << " return getRegisterName(RegNo, "; + if (!Namespace.empty()) + O << Namespace << "::"; + O << R->getValueAsDef("FallbackRegAltNameIndex")->getName() << ");\n"; + } + O << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName << "[RegNo-1];\n"; } O << " }\n"; diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 2c19e5d663d6..c26e0e421183 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -1,9 +1,8 @@ //===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -94,8 +93,10 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex, != std::string::npos) { AddLiteralString(std::string(1, AsmString[DollarPos+1])); } else { - PrintFatalError("Non-supported escaped character found in instruction '" + - CGI.TheDef->getName() + "'!"); + PrintFatalError( + CGI.TheDef->getLoc(), + "Non-supported escaped character found in instruction '" + + CGI.TheDef->getName() + "'!"); } LastEmitted = DollarPos+2; continue; @@ -132,15 +133,19 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex, // brace. if (hasCurlyBraces) { if (VarEnd >= AsmString.size()) - PrintFatalError("Reached end of string before terminating curly brace in '" - + CGI.TheDef->getName() + "'"); + PrintFatalError( + CGI.TheDef->getLoc(), + "Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"); // Look for a modifier string. if (AsmString[VarEnd] == ':') { ++VarEnd; if (VarEnd >= AsmString.size()) - PrintFatalError("Reached end of string before terminating curly brace in '" - + CGI.TheDef->getName() + "'"); + PrintFatalError( + CGI.TheDef->getLoc(), + "Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"); std::string::size_type ModifierStart = VarEnd; while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) @@ -148,17 +153,22 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex, Modifier = std::string(AsmString.begin()+ModifierStart, AsmString.begin()+VarEnd); if (Modifier.empty()) - PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"); + PrintFatalError(CGI.TheDef->getLoc(), + "Bad operand modifier name in '" + + CGI.TheDef->getName() + "'"); } if (AsmString[VarEnd] != '}') - PrintFatalError("Variable name beginning with '{' did not end with '}' in '" - + CGI.TheDef->getName() + "'"); + PrintFatalError( + CGI.TheDef->getLoc(), + "Variable name beginning with '{' did not end with '}' in '" + + CGI.TheDef->getName() + "'"); ++VarEnd; } if (VarName.empty() && Modifier.empty()) - PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() + - "' asm string, maybe you want $$?"); + PrintFatalError(CGI.TheDef->getLoc(), + "Stray '$' in '" + CGI.TheDef->getName() + + "' asm string, maybe you want $$?"); if (VarName.empty()) { // Just a modifier, pass this into PrintSpecial. diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 708f23cb5b0e..7d88e5a9d037 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -1,9 +1,8 @@ //===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/Attributes.cpp b/utils/TableGen/Attributes.cpp index 6bfc0ab896f9..6fbc595d7300 100644 --- a/utils/TableGen/Attributes.cpp +++ b/utils/TableGen/Attributes.cpp @@ -1,9 +1,8 @@ //===- Attributes.cpp - Generate attributes -------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index bd596bcb47a8..ccb7f3300dde 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -1,9 +1,8 @@ //===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index d452031f8850..de5044e24d49 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -1,9 +1,8 @@ //===- CallingConvEmitter.cpp - Generate calling conventions --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -41,11 +40,17 @@ void CallingConvEmitter::run(raw_ostream &O) { // each other. for (Record *CC : CCs) { if (!CC->getValueAsBit("Custom")) { - O << "static bool " << CC->getName() - << "(unsigned ValNo, MVT ValVT,\n" - << std::string(CC->getName().size() + 13, ' ') - << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" - << std::string(CC->getName().size() + 13, ' ') + unsigned Pad = CC->getName().size(); + if (CC->getValueAsBit("Entry")) { + O << "bool llvm::"; + Pad += 12; + } else { + O << "static bool "; + Pad += 13; + } + O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" + << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; } } @@ -62,12 +67,18 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { ListInit *CCActions = CC->getValueAsListInit("Actions"); Counter = 0; - O << "\n\nstatic bool " << CC->getName() - << "(unsigned ValNo, MVT ValVT,\n" - << std::string(CC->getName().size()+13, ' ') - << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" - << std::string(CC->getName().size()+13, ' ') - << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; + O << "\n\n"; + unsigned Pad = CC->getName().size(); + if (CC->getValueAsBit("Entry")) { + O << "bool llvm::"; + Pad += 12; + } else { + O << "static bool "; + Pad += 13; + } + O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" + << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; // Emit all of the actions, in order. for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { O << "\n"; @@ -97,7 +108,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Action->getValueAsString("Predicate"); } else { errs() << *Action; - PrintFatalError("Unknown CCPredicateAction!"); + PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); } O << ") {\n"; @@ -134,7 +145,8 @@ void CallingConvEmitter::EmitAction(Record *Action, ListInit *RegList = Action->getValueAsListInit("RegList"); ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) - PrintFatalError("Invalid length of list of shadowed registers"); + PrintFatalError(Action->getLoc(), + "Invalid length of list of shadowed registers"); if (RegList->size() == 1) { O << IndentStr << "if (unsigned Reg = State.AllocateReg("; @@ -237,7 +249,8 @@ void CallingConvEmitter::EmitAction(Record *Action, MVT::SimpleValueType DestVT = getValueType(DestTy); O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; if (MVT(DestVT).isFloatingPoint()) { - PrintFatalError("CCPromoteToUpperBitsInType does not handle floating " + PrintFatalError(Action->getLoc(), + "CCPromoteToUpperBitsInType does not handle floating " "point"); } else { O << IndentStr << "if (ArgFlags.isSExt())\n" @@ -269,7 +282,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << IndentStr << "return false;\n"; } else { errs() << *Action; - PrintFatalError("Unknown CCAction!"); + PrintFatalError(Action->getLoc(), "Unknown CCAction!"); } } } diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 23751a2cbfba..da65763905a8 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -1,9 +1,8 @@ //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -16,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" @@ -229,6 +229,14 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, return Case; } +static std::string +getNameForFeatureBitset(const std::vector<Record *> &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<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); @@ -327,8 +335,8 @@ void CodeEmitterGen::run(raw_ostream &o) { << "#include <sstream>\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"; @@ -340,35 +348,97 @@ void CodeEmitterGen::run(raw_ostream &o) { Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", SubtargetFeatures, o); + std::vector<std::vector<Record *>> FeatureBitsets; + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + FeatureBitsets.emplace_back(); + for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) + FeatureBitsets.back().push_back(I->second.TheDef); + } + } + + llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A, + const std::vector<Record *> &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, uint64_t AvailableFeatures) const {\n" + << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n" << "#ifndef NDEBUG\n" - << " static uint64_t RequiredFeatures[] = {\n"; + << " static " << getMinimalTypeForRange(FeatureBitsets.size()) + << " RequiredFeaturesRefs[] = {\n"; unsigned InstIdx = 0; for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - o << " "; + 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.getEnumName() << " | "; + if (I != SubtargetFeatures.end()) { + o << '_' << I->second.TheDef->getName(); + NumPredicates++; + } } - o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; + 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/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 96c90c9cf6bd..c8f710d66a03 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1,9 +1,8 @@ //===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -68,8 +67,10 @@ static bool berase_if(MachineValueTypeSet &S, Predicate P) { // inference will apply to each mode separately. TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) { - for (const ValueTypeByHwMode &VVT : VTList) + for (const ValueTypeByHwMode &VVT : VTList) { insert(VVT); + AddrSpaces.push_back(VVT.PtrAddrSpace); + } } bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { @@ -86,9 +87,13 @@ ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { assert(isValueTypeByHwMode(true) && "The type set has multiple types for at least one HW mode"); ValueTypeByHwMode VVT; + auto ASI = AddrSpaces.begin(); + for (const auto &I : *this) { MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); VVT.getOrCreateTypeForMode(I.first, T); + if (ASI != AddrSpaces.end()) + VVT.PtrAddrSpace = *ASI++; } return VVT; } @@ -502,22 +507,14 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, (A.getScalarSizeInBits() == B.getScalarSizeInBits() && A.getSizeInBits() < B.getSizeInBits()); }; - auto LE = [](MVT A, MVT B) -> bool { + auto LE = [<](MVT A, MVT B) -> bool { // This function is used when removing elements: when a vector is compared // to a non-vector, it should return false (to avoid removal). if (A.isVector() != B.isVector()) return false; - // Note on the < comparison below: - // X86 has patterns like - // (set VR128X:$dst, (v16i8 (X86vtrunc (v4i32 VR128X:$src1)))), - // where the truncated vector is given a type v16i8, while the source - // vector has type v4i32. They both have the same size in bits. - // The minimal type in the result is obviously v16i8, and when we remove - // all types from the source that are smaller-or-equal than v8i16, the - // only source type would also be removed (since it's equal in size). - return A.getScalarSizeInBits() <= B.getScalarSizeInBits() || - A.getSizeInBits() < B.getSizeInBits(); + return LT(A, B) || (A.getScalarSizeInBits() == B.getScalarSizeInBits() && + A.getSizeInBits() == B.getSizeInBits()); }; for (unsigned M : Modes) { @@ -957,13 +954,33 @@ std::string TreePredicateFn::getPredCode() const { } if (isLoad() || isStore() || isAtomic()) { - StringRef SDNodeName = - isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode"; + if (ListInit *AddressSpaces = getAddressSpaces()) { + Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n" + " if ("; + + bool First = true; + for (Init *Val : AddressSpaces->getValues()) { + if (First) + First = false; + else + Code += " && "; + + IntInit *IntVal = dyn_cast<IntInit>(Val); + if (!IntVal) { + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "AddressSpaces element must be integer"); + } + + Code += "AddrSpace != " + utostr(IntVal->getValue()); + } + + Code += ")\nreturn false;\n"; + } Record *MemoryVT = getMemoryVT(); if (MemoryVT) - Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" + + Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" + MemoryVT->getName() + ") return false;\n") .str(); } @@ -1152,6 +1169,14 @@ Record *TreePredicateFn::getMemoryVT() const { return nullptr; return R->getValueAsDef("MemoryVT"); } + +ListInit *TreePredicateFn::getAddressSpaces() const { + Record *R = getOrigPatFragRecord()->getRecord(); + if (R->isValueUnset("AddressSpaces")) + return nullptr; + return R->getValueAsListInit("AddressSpaces"); +} + Record *TreePredicateFn::getScalarMemoryVT() const { Record *R = getOrigPatFragRecord()->getRecord(); if (R->isValueUnset("ScalarMemoryVT")) @@ -1276,6 +1301,17 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { // PatternToMatch implementation // +static bool isImmAllOnesAllZerosMatch(const TreePatternNode *P) { + if (!P->isLeaf()) + return false; + DefInit *DI = dyn_cast<DefInit>(P->getLeafValue()); + if (!DI) + return false; + + Record *R = DI->getDef(); + return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV"; +} + /// getPatternSize - Return the 'size' of this pattern. We want to match large /// patterns before small ones. This is used to determine the size of a /// pattern. @@ -1315,6 +1351,8 @@ static unsigned getPatternSize(const TreePatternNode *P, Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); + else if (isImmAllOnesAllZerosMatch(Child)) + Size += 4; // Matches a build_vector(+3) and a predicate (+1). else if (!Child->getPredicateCalls().empty()) ++Size; } @@ -1408,7 +1446,8 @@ SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) { x.SDTCisSameSizeAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); } else { - PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); + PrintFatalError(R->getLoc(), + "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } } @@ -2120,7 +2159,8 @@ static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, } if (R->getName() == "node" || R->getName() == "srcvalue" || - R->getName() == "zero_reg") { + R->getName() == "zero_reg" || R->getName() == "immAllOnesV" || + R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") { // Placeholder. return TypeSetByHwMode(); // Unknown. } @@ -2425,18 +2465,32 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { } } + // If one or more operands with a default value appear at the end of the + // formal operand list for an instruction, we allow them to be overridden + // by optional operands provided in the pattern. + // + // But if an operand B without a default appears at any point after an + // operand A with a default, then we don't allow A to be overridden, + // because there would be no way to specify whether the next operand in + // the pattern was intended to override A or skip it. + unsigned NonOverridableOperands = Inst.getNumOperands(); + while (NonOverridableOperands > 0 && + CDP.operandHasDefault(Inst.getOperand(NonOverridableOperands-1))) + --NonOverridableOperands; + unsigned ChildNo = 0; for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { Record *OperandNode = Inst.getOperand(i); - // If the instruction expects a predicate or optional def operand, we - // codegen this by setting the operand to it's default value if it has a - // non-empty DefaultOps field. - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + // If the operand has a default value, do we use it? We must use the + // default if we've run out of children of the pattern DAG to consume, + // or if the operand is followed by a non-defaulted one. + if (CDP.operandHasDefault(OperandNode) && + (i < NonOverridableOperands || ChildNo >= getNumChildren())) continue; - // Verify that we didn't run out of provided operands. + // If we have run out of child nodes and there _isn't_ a default + // value we can use for the next operand, give an error. if (ChildNo >= getNumChildren()) { emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); return false; @@ -2753,7 +2807,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, // chain. if (Int.IS.RetVTs.empty()) Operator = getDAGPatterns().get_intrinsic_void_sdnode(); - else if (Int.ModRef != CodeGenIntrinsic::NoMem) + else if (Int.ModRef != CodeGenIntrinsic::NoMem || Int.hasSideEffects) // Has side-effects, requires chain. Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); else // Otherwise, no chain. diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 4be9afdcacd2..2b49a64c3f1d 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -1,9 +1,8 @@ //===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -191,6 +190,7 @@ private: struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> { using SetType = MachineValueTypeSet; + std::vector<unsigned> AddrSpaces; TypeSetByHwMode() = default; TypeSetByHwMode(const TypeSetByHwMode &VTS) = default; @@ -227,6 +227,15 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> { return Map.size() == 1 && Map.begin()->first == DefaultMode; } + bool isPointer() const { + return getValueTypeByHwMode().isPointer(); + } + + unsigned getPtrAddrSpace() const { + assert(isPointer()); + return getValueTypeByHwMode().PtrAddrSpace; + } + bool insert(const ValueTypeByHwMode &VVT); bool constrain(const TypeSetByHwMode &VTS); template <typename Predicate> bool constrain(Predicate P); @@ -243,6 +252,7 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> { bool validate() const; private: + unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max(); /// Intersect two sets. Return true if anything has changed. bool intersect(SetType &Out, const SetType &In); }; @@ -583,6 +593,8 @@ public: /// ValueType record for the memory VT. Record *getScalarMemoryVT() const; + ListInit *getAddressSpaces() const; + // If true, indicates that GlobalISel-based C++ code was supplied. bool hasGISelPredicateCode() const; std::string getGISelPredicateCode() const; @@ -1272,6 +1284,11 @@ public: unsigned allocateScope() { return ++NumScopes; } + bool operandHasDefault(Record *Op) const { + return Op->isSubClassOf("OperandWithDefaultOps") && + !getDefaultOperand(Op).DefaultOps.empty(); + } + private: void ParseNodeInfo(); void ParseNodeTransforms(); diff --git a/utils/TableGen/CodeGenHwModes.cpp b/utils/TableGen/CodeGenHwModes.cpp index 9f88d95275b4..9052cdd2bd3e 100644 --- a/utils/TableGen/CodeGenHwModes.cpp +++ b/utils/TableGen/CodeGenHwModes.cpp @@ -1,9 +1,8 @@ //===--- CodeGenHwModes.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Classes to parse and store HW mode information for instruction selection diff --git a/utils/TableGen/CodeGenHwModes.h b/utils/TableGen/CodeGenHwModes.h index 36df835d1933..1ff2faaa0e52 100644 --- a/utils/TableGen/CodeGenHwModes.h +++ b/utils/TableGen/CodeGenHwModes.h @@ -1,9 +1,8 @@ //===--- CodeGenHwModes.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Classes to parse and store HW mode information for instruction selection. diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 6d06ba2c8b67..2463824469ab 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -1,9 +1,8 @@ //===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -34,18 +33,24 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) { if (Init->getDef()->getName() != "outs") - PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'"); + PrintFatalError(R->getLoc(), + R->getName() + + ": invalid def name for output list: use 'outs'"); } else - PrintFatalError(R->getName() + ": invalid output list: use 'outs'"); + PrintFatalError(R->getLoc(), + R->getName() + ": invalid output list: use 'outs'"); NumDefs = OutDI->getNumArgs(); DagInit *InDI = R->getValueAsDag("InOperandList"); if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) { if (Init->getDef()->getName() != "ins") - PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'"); + PrintFatalError(R->getLoc(), + R->getName() + + ": invalid def name for input list: use 'ins'"); } else - PrintFatalError(R->getName() + ": invalid input list: use 'ins'"); + PrintFatalError(R->getLoc(), + R->getName() + ": invalid input list: use 'ins'"); unsigned MIOperandNo = 0; std::set<std::string> OperandNames; @@ -64,7 +69,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { DefInit *Arg = dyn_cast<DefInit>(ArgInit); if (!Arg) - PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!"); + PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() + + "' instruction!"); Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; @@ -89,8 +95,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { // Verify that MIOpInfo has an 'ops' root value. if (!isa<DefInit>(MIOpInfo->getOperator()) || cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops") - PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() + - "'\n"); + PrintFatalError(R->getLoc(), + "Bad value for MIOperandInfo in operand '" + + Rec->getName() + "'\n"); // If we have MIOpInfo, then we have #operands equal to number of entries // in MIOperandInfo. @@ -108,16 +115,20 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { OperandType = "OPERAND_REGISTER"; } else if (!Rec->isSubClassOf("PointerLikeRegClass") && !Rec->isSubClassOf("unknown_class")) - PrintFatalError("Unknown operand class '" + Rec->getName() + - "' in '" + R->getName() + "' instruction!"); + PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() + + "' in '" + R->getName() + + "' instruction!"); // Check that the operand has a name and that it's unique. if (ArgName.empty()) - PrintFatalError("In instruction '" + R->getName() + "', operand #" + - Twine(i) + " has no name!"); + PrintFatalError(R->getLoc(), "In instruction '" + R->getName() + + "', operand #" + Twine(i) + + " has no name!"); if (!OperandNames.insert(ArgName).second) - PrintFatalError("In instruction '" + R->getName() + "', operand #" + - Twine(i) + " has the same name as a previous operand!"); + PrintFatalError(R->getLoc(), + "In instruction '" + R->getName() + "', operand #" + + Twine(i) + + " has the same name as a previous operand!"); OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod, OperandNamespace + "::" + OperandType, MIOperandNo, @@ -139,9 +150,11 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { /// unsigned CGIOperandList::getOperandNamed(StringRef Name) const { unsigned OpIdx; - if (hasOperandNamed(Name, OpIdx)) return OpIdx; - PrintFatalError("'" + TheDef->getName() + - "' does not have an operand named '$" + Name + "'!"); + if (hasOperandNamed(Name, OpIdx)) + return OpIdx; + PrintFatalError(TheDef->getLoc(), "'" + TheDef->getName() + + "' does not have an operand named '$" + + Name + "'!"); } /// hasOperandNamed - Query whether the instruction has an operand of the @@ -160,7 +173,8 @@ bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { std::pair<unsigned,unsigned> CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (Op.empty() || Op[0] != '$') - PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'"); + PrintFatalError(TheDef->getLoc(), + TheDef->getName() + ": Illegal operand name: '" + Op + "'"); std::string OpName = Op.substr(1); std::string SubOpName; @@ -170,7 +184,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (DotIdx != std::string::npos) { SubOpName = OpName.substr(DotIdx+1); if (SubOpName.empty()) - PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"); + PrintFatalError(TheDef->getLoc(), + TheDef->getName() + + ": illegal empty suboperand name in '" + Op + "'"); OpName = OpName.substr(0, DotIdx); } @@ -180,8 +196,11 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // If one was needed, throw. if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && SubOpName.empty()) - PrintFatalError(TheDef->getName() + ": Illegal to refer to" - " whole operand part of complex operand '" + Op + "'"); + PrintFatalError(TheDef->getLoc(), + TheDef->getName() + + ": Illegal to refer to" + " whole operand part of complex operand '" + + Op + "'"); // Otherwise, return the operand. return std::make_pair(OpIdx, 0U); @@ -190,7 +209,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; if (!MIOpInfo) - PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); + PrintFatalError(TheDef->getLoc(), TheDef->getName() + + ": unknown suboperand name in '" + + Op + "'"); // Find the operand with the right name. for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) @@ -198,7 +219,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { return std::make_pair(OpIdx, i); // Otherwise, didn't find it! - PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); + PrintFatalError(TheDef->getLoc(), TheDef->getName() + + ": unknown suboperand name in '" + Op + + "'"); return std::make_pair(0U, 0U); } @@ -354,7 +377,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R) isAdd = R->getValueAsBit("isAdd"); isTrap = R->getValueAsBit("isTrap"); canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); - isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); + isPredicable = !R->getValueAsBit("isUnpredicable") && ( + Operands.isPredicable || R->getValueAsBit("isPredicable")); isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); isCommutable = R->getValueAsBit("isCommutable"); isTerminator = R->getValueAsBit("isTerminator"); @@ -377,6 +401,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) mayLoad_Unset = Unset; mayStore = R->getValueAsBitOrUnset("mayStore", Unset); mayStore_Unset = Unset; + mayRaiseFPException = R->getValueAsBit("mayRaiseFPException"); hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset); hasSideEffects_Unset = Unset; diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 2e3d2f48a928..bb5b1369649f 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -1,9 +1,8 @@ //===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -250,6 +249,7 @@ template <typename T> class ArrayRef; bool mayLoad_Unset : 1; bool mayStore : 1; bool mayStore_Unset : 1; + bool mayRaiseFPException : 1; bool isPredicable : 1; bool isConvertibleToThreeAddress : 1; bool isCommutable : 1; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 9487a79c1432..7b74bb07d6e0 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -1,9 +1,8 @@ //===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -124,6 +123,9 @@ struct CodeGenIntrinsic { /// True if the intrinsic is no-return. bool isNoReturn; + /// True if the intrinsic is will-return. + bool isWillReturn; + /// True if the intrinsic is cold. bool isCold; @@ -137,7 +139,15 @@ struct CodeGenIntrinsic { // True if the intrinsic is marked as speculatable. bool isSpeculatable; - enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone }; + enum ArgAttribute { + NoCapture, + Returned, + ReadOnly, + WriteOnly, + ReadNone, + ImmArg + }; + std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes; bool hasProperty(enum SDNP Prop) const { diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index e5b0426cdcc3..b1774b01ba8c 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -1,9 +1,8 @@ //===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // CodeGenMapTable provides functionality for the TabelGen to create diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 74a2b078dfb3..f87c6d6c945a 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -1,9 +1,8 @@ //===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -740,8 +739,9 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { Record *Type = TypeList[i]; if (!Type->isSubClassOf("ValueType")) - PrintFatalError("RegTypes list member '" + Type->getName() + - "' does not derive from the ValueType class!"); + PrintFatalError(R->getLoc(), + "RegTypes list member '" + Type->getName() + + "' does not derive from the ValueType class!"); VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes())); } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); @@ -2101,8 +2101,7 @@ void CodeGenRegBank::computeDerivedInfo() { for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) RegUnitSetOrder.push_back(Idx); - std::stable_sort(RegUnitSetOrder.begin(), RegUnitSetOrder.end(), - [this](unsigned ID1, unsigned ID2) { + llvm::stable_sort(RegUnitSetOrder, [this](unsigned ID1, unsigned ID2) { return getRegPressureSet(ID1).Units.size() < getRegPressureSet(ID2).Units.size(); }); diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 0f7a025ded10..f04a90f8fde5 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -1,9 +1,8 @@ //===- CodeGenRegisters.h - Register and RegisterClass Info -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 6d259cbb33ee..fd007044a16e 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -1,9 +1,8 @@ //===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -369,24 +368,22 @@ processSTIPredicate(STIPredicateFunction &Fn, [&](const OpcodeMapPair &Lhs, const OpcodeMapPair &Rhs) { unsigned LhsIdx = Opcode2Index[Lhs.first]; unsigned RhsIdx = Opcode2Index[Rhs.first]; - std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx]; - std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx]; - - if (LhsMasks.first != RhsMasks.first) { - if (LhsMasks.first.countPopulation() < - RhsMasks.first.countPopulation()) - return true; - return LhsMasks.first.countLeadingZeros() > - RhsMasks.first.countLeadingZeros(); - } - - if (LhsMasks.second != RhsMasks.second) { - if (LhsMasks.second.countPopulation() < - RhsMasks.second.countPopulation()) - return true; - return LhsMasks.second.countLeadingZeros() > - RhsMasks.second.countLeadingZeros(); - } + const std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx]; + const std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx]; + + auto LessThan = [](const APInt &Lhs, const APInt &Rhs) { + unsigned LhsCountPopulation = Lhs.countPopulation(); + unsigned RhsCountPopulation = Rhs.countPopulation(); + return ((LhsCountPopulation < RhsCountPopulation) || + ((LhsCountPopulation == RhsCountPopulation) && + (Lhs.countLeadingZeros() > Rhs.countLeadingZeros()))); + }; + + if (LhsMasks.first != RhsMasks.first) + return LessThan(LhsMasks.first, RhsMasks.first); + + if (LhsMasks.second != RhsMasks.second) + return LessThan(LhsMasks.second, RhsMasks.second); return LhsIdx < RhsIdx; }); @@ -1936,8 +1933,10 @@ void CodeGenSchedModels::checkCompleteness() { unsigned SCIdx = getSchedClassIdx(*Inst); if (!SCIdx) { if (Inst->TheDef->isValueUnset("SchedRW") && !HadCompleteModel) { - PrintError("No schedule information for instruction '" - + Inst->TheDef->getName() + "'"); + PrintError(Inst->TheDef->getLoc(), + "No schedule information for instruction '" + + Inst->TheDef->getName() + "' in SchedMachineModel '" + + ProcModel.ModelDef->getName() + "'"); Complete = false; } continue; @@ -1955,8 +1954,9 @@ void CodeGenSchedModels::checkCompleteness() { return R->getValueAsDef("SchedModel") == ProcModel.ModelDef; }); if (I == InstRWs.end()) { - PrintError("'" + ProcModel.ModelName + "' lacks information for '" + - Inst->TheDef->getName() + "'"); + PrintError(Inst->TheDef->getLoc(), "'" + ProcModel.ModelName + + "' lacks information for '" + + Inst->TheDef->getName() + "'"); Complete = false; } } diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 87a051b0c05e..c26fb1f97807 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -1,9 +1,8 @@ //===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index bcb653135551..b65e1b6af791 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -1,9 +1,8 @@ //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -21,8 +20,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Timer.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> using namespace llvm; @@ -105,11 +106,18 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v128i16: return "MVT::v128i16"; case MVT::v1i32: return "MVT::v1i32"; case MVT::v2i32: return "MVT::v2i32"; + case MVT::v3i32: return "MVT::v3i32"; case MVT::v4i32: return "MVT::v4i32"; + case MVT::v5i32: return "MVT::v5i32"; case MVT::v8i32: return "MVT::v8i32"; case MVT::v16i32: return "MVT::v16i32"; case MVT::v32i32: return "MVT::v32i32"; case MVT::v64i32: return "MVT::v64i32"; + case MVT::v128i32: return "MVT::v128i32"; + case MVT::v256i32: return "MVT::v256i32"; + case MVT::v512i32: return "MVT::v512i32"; + case MVT::v1024i32: return "MVT::v1024i32"; + case MVT::v2048i32: return "MVT::v2048i32"; case MVT::v1i64: return "MVT::v1i64"; case MVT::v2i64: return "MVT::v2i64"; case MVT::v4i64: return "MVT::v4i64"; @@ -122,9 +130,18 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v8f16: return "MVT::v8f16"; case MVT::v1f32: return "MVT::v1f32"; case MVT::v2f32: return "MVT::v2f32"; + case MVT::v3f32: return "MVT::v3f32"; case MVT::v4f32: return "MVT::v4f32"; + case MVT::v5f32: return "MVT::v5f32"; case MVT::v8f32: return "MVT::v8f32"; case MVT::v16f32: return "MVT::v16f32"; + case MVT::v32f32: return "MVT::v32f32"; + case MVT::v64f32: return "MVT::v64f32"; + case MVT::v128f32: return "MVT::v128f32"; + case MVT::v256f32: return "MVT::v256f32"; + case MVT::v512f32: return "MVT::v512f32"; + case MVT::v1024f32: return "MVT::v1024f32"; + case MVT::v2048f32: return "MVT::v2048f32"; case MVT::v1f64: return "MVT::v1f64"; case MVT::v2f64: return "MVT::v2f64"; case MVT::v4f64: return "MVT::v4f64"; @@ -174,7 +191,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) { case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; case MVT::Untyped: return "MVT::Untyped"; - case MVT::ExceptRef: return "MVT::ExceptRef"; + case MVT::exnref: return "MVT::exnref"; default: llvm_unreachable("ILLEGAL VALUE TYPE!"); } } @@ -327,6 +344,8 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const { } void CodeGenTarget::ReadInstructions() const { + NamedRegionTimer T("Read Instructions", "Time spent reading instructions", + "CodeGenTarget", "CodeGenTarget", TimeRegions); std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); if (Insts.size() <= 2) PrintFatalError("No 'Instruction' subclasses defined!"); @@ -492,9 +511,10 @@ ComplexPattern::ComplexPattern(Record *R) { } else if (PropList[i]->getName() == "SDNPWantParent") { Properties |= 1 << SDNPWantParent; } else { - PrintFatalError("Unsupported SD Node property '" + - PropList[i]->getName() + "' on ComplexPattern '" + - R->getName() + "'!"); + PrintFatalError(R->getLoc(), "Unsupported SD Node property '" + + PropList[i]->getName() + + "' on ComplexPattern '" + R->getName() + + "'!"); } } @@ -530,12 +550,14 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC, CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { TheDef = R; std::string DefName = R->getName(); + ArrayRef<SMLoc> DefLoc = R->getLoc(); ModRef = ReadWriteMem; Properties = 0; isOverloaded = false; isCommutative = false; canThrow = false; isNoReturn = false; + isWillReturn = false; isCold = false; isNoDuplicate = false; isConvergent = false; @@ -544,7 +566,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") - PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!"); + PrintFatalError(DefLoc, + "Intrinsic '" + DefName + "' does not start with 'int_'!"); EnumName = std::string(DefName.begin()+4, DefName.end()); @@ -566,7 +589,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // Verify it starts with "llvm.". if (Name.size() <= 5 || std::string(Name.begin(), Name.begin() + 5) != "llvm.") - PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"); + PrintFatalError(DefLoc, "Intrinsic '" + DefName + + "'s name does not start with 'llvm.'!"); } // If TargetPrefix is specified, make sure that Name starts with @@ -575,13 +599,34 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { if (Name.size() < 6+TargetPrefix.size() || std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) != (TargetPrefix + ".")) - PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." + - TargetPrefix + ".'!"); + PrintFatalError(DefLoc, "Intrinsic '" + DefName + + "' does not start with 'llvm." + + TargetPrefix + ".'!"); } - // Parse the list of return types. + ListInit *RetTypes = R->getValueAsListInit("RetTypes"); + ListInit *ParamTypes = R->getValueAsListInit("ParamTypes"); + + // First collate a list of overloaded types. std::vector<MVT::SimpleValueType> OverloadedVTs; - ListInit *TypeList = R->getValueAsListInit("RetTypes"); + for (ListInit *TypeList : {RetTypes, ParamTypes}) { + for (unsigned i = 0, e = TypeList->size(); i != e; ++i) { + Record *TyEl = TypeList->getElementAsRecord(i); + assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); + + if (TyEl->isSubClassOf("LLVMMatchType")) + continue; + + MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); + if (MVT(VT).isOverloaded()) { + OverloadedVTs.push_back(VT); + isOverloaded = true; + } + } + } + + // Parse the list of return types. + ListInit *TypeList = RetTypes; for (unsigned i = 0, e = TypeList->size(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); @@ -601,21 +646,18 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { } else { VT = getValueType(TyEl->getValueAsDef("VT")); } - if (MVT(VT).isOverloaded()) { - OverloadedVTs.push_back(VT); - isOverloaded = true; - } // Reject invalid types. if (VT == MVT::isVoid) - PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); + PrintFatalError(DefLoc, "Intrinsic '" + DefName + + " has void in result type list!"); IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); } // Parse the list of parameter types. - TypeList = R->getValueAsListInit("ParamTypes"); + TypeList = ParamTypes; for (unsigned i = 0, e = TypeList->size(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); @@ -626,7 +668,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { PrintError(R->getLoc(), "Parameter #" + Twine(i) + " has out of bounds matching " "number " + Twine(MatchTy)); - PrintFatalError(Twine("ParamTypes is ") + TypeList->getAsString()); + PrintFatalError(DefLoc, + Twine("ParamTypes is ") + TypeList->getAsString()); } VT = OverloadedVTs[MatchTy]; // It only makes sense to use the extended and truncated vector element @@ -634,20 +677,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && !TyEl->isSubClassOf("LLVMTruncatedType") && - !TyEl->isSubClassOf("LLVMVectorSameWidth")) || + !TyEl->isSubClassOf("LLVMScalarOrSameVectorWidth")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); - if (MVT(VT).isOverloaded()) { - OverloadedVTs.push_back(VT); - isOverloaded = true; - } - // Reject invalid types. if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) - PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); + PrintFatalError(DefLoc, "Intrinsic '" + DefName + + " has void in result type list!"); IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); @@ -683,6 +722,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isConvergent = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; + else if (Property->getName() == "IntrWillReturn") + isWillReturn = true; else if (Property->getName() == "IntrCold") isCold = true; else if (Property->getName() == "IntrSpeculatable") @@ -704,6 +745,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { } else if (Property->isSubClassOf("ReadNone")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone)); + } else if (Property->isSubClassOf("ImmArg")) { + unsigned ArgNo = Property->getValueAsInt("ArgNo"); + ArgumentAttributes.push_back(std::make_pair(ArgNo, ImmArg)); } else llvm_unreachable("Unknown property!"); } diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index d2833d5b6a92..1ab2de269c76 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -1,9 +1,8 @@ //===- CodeGenTarget.h - Target Class Wrapper -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 62a0ff700725..fb0c6faa5295 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -1,9 +1,8 @@ //===- DAGISelEmitter.cpp - Generate an instruction selector --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index c8e005739460..bebd205ad58f 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -1,9 +1,8 @@ //===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -212,6 +211,11 @@ void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n'; } +void CheckChild2CondCodeMatcher::printImpl(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckChild2CondCode ISD::" << CondCodeName << '\n'; +} + void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n'; } @@ -233,6 +237,16 @@ void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS, OS.indent(indent) << "CheckFoldableChainNode\n"; } +void CheckImmAllOnesVMatcher::printImpl(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckAllOnesV\n"; +} + +void CheckImmAllZerosVMatcher::printImpl(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckAllZerosV\n"; +} + void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitInteger " << Val << " VT=" << getEnumName(VT) << '\n'; @@ -398,3 +412,12 @@ bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const { return false; } +bool CheckImmAllOnesVMatcher::isContradictoryImpl(const Matcher *M) const { + // AllZeros is contradictory. + return isa<CheckImmAllZerosVMatcher>(M); +} + +bool CheckImmAllZerosVMatcher::isContradictoryImpl(const Matcher *M) const { + // AllOnes is contradictory. + return isa<CheckImmAllOnesVMatcher>(M); +} diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 9be7295c67d4..0a782e84a372 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -1,9 +1,8 @@ //===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -67,10 +66,13 @@ public: CheckInteger, // Fail if wrong val. CheckChildInteger, // Fail if child is wrong val. CheckCondCode, // Fail if not condcode. + CheckChild2CondCode, // Fail if child is wrong condcode. CheckValueType, CheckComplexPat, CheckAndImm, CheckOrImm, + CheckImmAllOnesV, + CheckImmAllZerosV, CheckFoldableChainNode, // Node creation/emisssion. @@ -122,9 +124,12 @@ public: case CheckInteger: case CheckChildInteger: case CheckCondCode: + case CheckChild2CondCode: case CheckValueType: case CheckAndImm: case CheckOrImm: + case CheckImmAllOnesV: + case CheckImmAllZerosV: case CheckFoldableChainNode: return true; } @@ -626,6 +631,27 @@ private: } }; +/// CheckChild2CondCodeMatcher - This checks to see if child 2 node is a +/// CondCodeSDNode with the specified condition, if not it fails to match. +class CheckChild2CondCodeMatcher : public Matcher { + StringRef CondCodeName; +public: + CheckChild2CondCodeMatcher(StringRef condcodename) + : Matcher(CheckChild2CondCode), CondCodeName(condcodename) {} + + StringRef getCondCodeName() const { return CondCodeName; } + + static bool classof(const Matcher *N) { + return N->getKind() == CheckChild2CondCode; + } + +private: + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { + return cast<CheckChild2CondCodeMatcher>(M)->CondCodeName == CondCodeName; + } +}; + /// CheckValueTypeMatcher - This checks to see if the current node is a /// VTSDNode with the specified type, if not it fails to match. class CheckValueTypeMatcher : public Matcher { @@ -731,6 +757,38 @@ private: } }; +/// CheckImmAllOnesVMatcher - This check if the current node is an build vector +/// of all ones. +class CheckImmAllOnesVMatcher : public Matcher { +public: + CheckImmAllOnesVMatcher() : Matcher(CheckImmAllOnesV) {} + + static bool classof(const Matcher *N) { + return N->getKind() == CheckImmAllOnesV; + } + +private: + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + bool isContradictoryImpl(const Matcher *M) const override; +}; + +/// CheckImmAllZerosVMatcher - This check if the current node is an build vector +/// of all zeros. +class CheckImmAllZerosVMatcher : public Matcher { +public: + CheckImmAllZerosVMatcher() : Matcher(CheckImmAllZerosV) {} + + static bool classof(const Matcher *N) { + return N->getKind() == CheckImmAllZerosV; + } + +private: + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + bool isContradictoryImpl(const Matcher *M) const override; +}; + /// CheckFoldableChainNodeMatcher - This checks to see if the current node /// (which defines a chain operand) is safe to fold into a larger pattern. class CheckFoldableChainNodeMatcher : public Matcher { diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 90ca1bff5344..cecbc6cccdff 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -1,9 +1,8 @@ //===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -259,7 +258,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) { OS << "\n};"; OS << "\nreturn StringRef(PATTERN_MATCH_TABLE[Index]);"; - OS << "\n}"; + OS << "\n}\n"; EndEmitFunction(OS); BeginEmitFunction(OS, "StringRef", "getIncludePathForIndex(unsigned Index)", @@ -273,7 +272,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) { OS << "\n};"; OS << "\nreturn StringRef(INCLUDE_PATH_TABLE[Index]);"; - OS << "\n}"; + OS << "\n}\n"; EndEmitFunction(OS); } @@ -555,6 +554,11 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n"; return 2; + case Matcher::CheckChild2CondCode: + OS << "OPC_CheckChild2CondCode, ISD::" + << cast<CheckChild2CondCodeMatcher>(N)->getCondCodeName() << ",\n"; + return 2; + case Matcher::CheckValueType: OS << "OPC_CheckValueType, MVT::" << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n"; @@ -597,6 +601,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << "OPC_CheckFoldableChainNode,\n"; return 1; + case Matcher::CheckImmAllOnesV: + OS << "OPC_CheckImmAllOnesV,\n"; + return 1; + + case Matcher::CheckImmAllZerosV: + OS << "OPC_CheckImmAllZerosV,\n"; + return 1; + case Matcher::EmitInteger: { int64_t Val = cast<EmitIntegerMatcher>(N)->getValue(); OS << "OPC_EmitInteger, " @@ -996,12 +1008,15 @@ static StringRef getOpcodeString(Matcher::KindTy Kind) { case Matcher::CheckInteger: return "OPC_CheckInteger"; break; case Matcher::CheckChildInteger: return "OPC_CheckChildInteger"; break; case Matcher::CheckCondCode: return "OPC_CheckCondCode"; break; + case Matcher::CheckChild2CondCode: return "OPC_CheckChild2CondCode"; break; case Matcher::CheckValueType: return "OPC_CheckValueType"; break; case Matcher::CheckComplexPat: return "OPC_CheckComplexPat"; break; case Matcher::CheckAndImm: return "OPC_CheckAndImm"; break; case Matcher::CheckOrImm: return "OPC_CheckOrImm"; break; case Matcher::CheckFoldableChainNode: return "OPC_CheckFoldableChainNode"; break; + case Matcher::CheckImmAllOnesV: return "OPC_CheckImmAllOnesV"; break; + case Matcher::CheckImmAllZerosV: return "OPC_CheckImmAllZerosV"; break; case Matcher::EmitInteger: return "OPC_EmitInteger"; break; case Matcher::EmitStringInteger: return "OPC_EmitStringInteger"; break; case Matcher::EmitRegister: return "OPC_EmitRegister"; break; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 612342ddcddf..8f54beeba65b 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -1,9 +1,8 @@ //===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -278,6 +277,27 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { return; } + if (LeafRec->getName() == "immAllOnesV") { + // If this is the root of the dag we're matching, we emit a redundant opcode + // check to ensure that this gets folded into the normal top-level + // OpcodeSwitch. + if (N == Pattern.getSrcPattern()) { + const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("build_vector")); + AddMatcher(new CheckOpcodeMatcher(NI)); + } + return AddMatcher(new CheckImmAllOnesVMatcher()); + } + if (LeafRec->getName() == "immAllZerosV") { + // If this is the root of the dag we're matching, we emit a redundant opcode + // check to ensure that this gets folded into the normal top-level + // OpcodeSwitch. + if (N == Pattern.getSrcPattern()) { + const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("build_vector")); + AddMatcher(new CheckOpcodeMatcher(NI)); + } + return AddMatcher(new CheckImmAllZerosVMatcher()); + } + errs() << "Unknown leaf kind: " << *N << "\n"; abort(); } @@ -671,6 +691,17 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, return; } + if (Def->getName() == "undef_tied_input") { + std::array<MVT::SimpleValueType, 1> ResultVTs = {{ N->getSimpleType(0) }}; + std::array<unsigned, 0> InstOps; + auto IDOperandNo = NextRecordedOperandNo++; + AddMatcher(new EmitNodeMatcher("TargetOpcode::IMPLICIT_DEF", + ResultVTs, InstOps, false, false, false, + false, -1, IDOperandNo)); + ResultOps.push_back(IDOperandNo); + return; + } + // Handle a reference to a register class. This is used // in COPY_TO_SUBREG instructions. if (Def->isSubClassOf("RegisterOperand")) @@ -763,14 +794,27 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // 'execute always' values. Match up the node operands to the instruction // operands to do this. unsigned ChildNo = 0; + + // Similarly to the code in TreePatternNode::ApplyTypeConstraints, count the + // number of operands at the end of the list which have default values. + // Those can come from the pattern if it provides enough arguments, or be + // filled in with the default if the pattern hasn't provided them. But any + // operand with a default value _before_ the last mandatory one will be + // filled in with their defaults unconditionally. + unsigned NonOverridableOperands = NumFixedOperands; + while (NonOverridableOperands > NumResults && + CGP.operandHasDefault(II.Operands[NonOverridableOperands-1].Rec)) + --NonOverridableOperands; + for (unsigned InstOpNo = NumResults, e = NumFixedOperands; InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { - // This is a predicate or optional def operand; emit the - // 'default ops' operands. + if (CGP.operandHasDefault(OperandNode) && + (InstOpNo < NonOverridableOperands || ChildNo >= N->getNumChildren())) { + // This is a predicate or optional def operand which the pattern has not + // overridden, or which we aren't letting it override; emit the 'default + // ops' operands. const DAGDefaultOperand &DefaultOp = CGP.getDefaultOperand(OperandNode); for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 554c7438ce3d..7d51b0769372 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -1,9 +1,8 @@ //===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -56,9 +55,13 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, if (MC->getChildNo() < 4) // Only have CheckChildSame0...3 New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber()); - if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext())) + if (CheckIntegerMatcher *CI = dyn_cast<CheckIntegerMatcher>(MC->getNext())) if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4 - New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue()); + New = new CheckChildIntegerMatcher(MC->getChildNo(), CI->getValue()); + + if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MC->getNext())) + if (MC->getChildNo() == 2) // Only have CheckChild2CondCode + New = new CheckChild2CondCodeMatcher(CCC->getCondCodeName()); if (New) { // Insert the new node. diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index 0db0f55f5ed6..dabcc8f8ed55 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -1,9 +1,8 @@ //===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index b99a0a973a2c..9e75c7fba77b 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -1,9 +1,8 @@ //===- DisassemblerEmitter.cpp - Generate a disassembler ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/ExegesisEmitter.cpp b/utils/TableGen/ExegesisEmitter.cpp index 208237aca20c..976d5f51776f 100644 --- a/utils/TableGen/ExegesisEmitter.cpp +++ b/utils/TableGen/ExegesisEmitter.cpp @@ -1,9 +1,8 @@ //===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 5134b684c6f9..b39956859fe8 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -1,9 +1,8 @@ ///===- FastISelEmitter.cpp - Generate an instruction selector -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 5e621fc0efdd..f5e975d2e5ae 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1,9 +1,8 @@ //===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -17,9 +16,10 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCFixedLenDisassembler.h" @@ -48,6 +48,12 @@ using namespace llvm; namespace { +STATISTIC(NumEncodings, "Number of encodings considered"); +STATISTIC(NumEncodingsLackingDisasm, "Number of encodings without disassembler info"); +STATISTIC(NumInstructions, "Number of instructions considered"); +STATISTIC(NumEncodingsSupported, "Number of encodings supported"); +STATISTIC(NumEncodingsOmitted, "Number of encodings omitted"); + struct EncodingField { unsigned Base, Width, Offset; EncodingField(unsigned B, unsigned W, unsigned O) @@ -95,6 +101,15 @@ struct EncodingAndInst { : EncodingDef(EncodingDef), Inst(Inst) {} }; +struct EncodingIDAndOpcode { + unsigned EncodingID; + unsigned Opcode; + + EncodingIDAndOpcode() : EncodingID(0), Opcode(0) {} + EncodingIDAndOpcode(unsigned EncodingID, unsigned Opcode) + : EncodingID(EncodingID), Opcode(Opcode) {} +}; + raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) { if (Value.EncodingDef != Value.Inst->TheDef) OS << Value.EncodingDef->getName() << ":"; @@ -103,6 +118,7 @@ raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) { } class FixedLenDecoderEmitter { + RecordKeeper &RK; std::vector<EncodingAndInst> NumberedEncodings; public: @@ -114,7 +130,7 @@ public: std::string ROK = "MCDisassembler::Success", std::string RFail = "MCDisassembler::Fail", std::string L = "") - : Target(R), PredicateNamespace(std::move(PredicateNamespace)), + : RK(R), Target(R), PredicateNamespace(std::move(PredicateNamespace)), GuardPrefix(std::move(GPrefix)), GuardPostfix(std::move(GPostfix)), ReturnOK(std::move(ROK)), ReturnFail(std::move(RFail)), Locals(std::move(L)) {} @@ -252,10 +268,11 @@ protected: bool Mixed; // a mixed region contains both set and unset bits // Map of well-known segment value to the set of uid's with that value. - std::map<uint64_t, std::vector<unsigned>> FilteredInstructions; + std::map<uint64_t, std::vector<EncodingIDAndOpcode>> + FilteredInstructions; // Set of uid's with non-constant segment values. - std::vector<unsigned> VariableInstructions; + std::vector<EncodingIDAndOpcode> VariableInstructions; // Map of well-known segment value to its delegate. std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap; @@ -264,7 +281,7 @@ protected: unsigned NumFiltered; // Keeps track of the last opcode in the filtered bucket. - unsigned LastOpcFiltered; + EncodingIDAndOpcode LastOpcFiltered; public: Filter(Filter &&f); @@ -274,7 +291,7 @@ public: unsigned getNumFiltered() const { return NumFiltered; } - unsigned getSingletonOpc() const { + EncodingIDAndOpcode getSingletonOpc() const { assert(NumFiltered == 1); return LastOpcFiltered; } @@ -341,7 +358,9 @@ protected: ArrayRef<EncodingAndInst> AllInstructions; // Vector of uid's for this filter chooser to work on. - const std::vector<unsigned> &Opcodes; + // The first member of the pair is the opcode id being decoded, the second is + // the opcode id that should be emitted. + const std::vector<EncodingIDAndOpcode> &Opcodes; // Lookup table for the operand decoding of instructions. const std::map<unsigned, std::vector<OperandInfo>> &Operands; @@ -367,7 +386,7 @@ protected: public: FilterChooser(ArrayRef<EncodingAndInst> Insts, - const std::vector<unsigned> &IDs, + const std::vector<EncodingIDAndOpcode> &IDs, const std::map<unsigned, std::vector<OperandInfo>> &Ops, unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), @@ -377,7 +396,7 @@ public: } FilterChooser(ArrayRef<EncodingAndInst> Insts, - const std::vector<unsigned> &IDs, + const std::vector<EncodingIDAndOpcode> &IDs, const std::map<unsigned, std::vector<OperandInfo>> &Ops, const std::vector<bit_value_t> &ParentFilterBitValues, const FilterChooser &parent) @@ -413,6 +432,15 @@ protected: } } + // Emit the name of the encoding/instruction pair. + void emitNameWithID(raw_ostream &OS, unsigned Opcode) const { + const Record *EncodingDef = AllInstructions[Opcode].EncodingDef; + const Record *InstDef = AllInstructions[Opcode].Inst->TheDef; + if (EncodingDef != InstDef) + OS << EncodingDef->getName() << ":"; + OS << InstDef->getName(); + } + // Populates the field of the insn given the start position and the number of // consecutive bits to scan for. // @@ -463,7 +491,7 @@ protected: // Emits table entries to decode the singleton. void emitSingletonTableEntry(DecoderTableInfo &TableInfo, - unsigned Opc) const; + EncodingIDAndOpcode Opc) const; // Emits code to decode the singleton, and then to decode the rest. void emitSingletonTableEntry(DecoderTableInfo &TableInfo, @@ -524,13 +552,13 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, assert(StartBit + NumBits - 1 < Owner->BitWidth); NumFiltered = 0; - LastOpcFiltered = 0; + LastOpcFiltered = {0, 0}; for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { insn_t Insn; // Populates the insn given the uid. - Owner->insnWithID(Insn, Owner->Opcodes[i]); + Owner->insnWithID(Insn, Owner->Opcodes[i].EncodingID); uint64_t Field; // Scans the segment for possibly well-specified encoding bits. @@ -1026,7 +1054,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, // 1: Water (the bit value does not affect decoding) // 2: Island (well-known bit value needed for decoding) int State = 0; - int Val = -1; + int64_t Val = -1; for (unsigned i = 0; i < BitWidth; ++i) { Val = Value(Insn[i]); @@ -1314,12 +1342,12 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, // Emits table entries to decode the singleton. void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, - unsigned Opc) const { + EncodingIDAndOpcode Opc) const { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; std::vector<uint64_t> FieldVals; insn_t Insn; - insnWithID(Insn, Opc); + insnWithID(Insn, Opc.EncodingID); // Look for islands of undecoded bits of the singleton. getIslands(StartBits, EndBits, FieldVals, Insn); @@ -1327,7 +1355,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, unsigned Size = StartBits.size(); // Emit the predicate table entry if one is needed. - emitPredicateTableEntry(TableInfo, Opc); + emitPredicateTableEntry(TableInfo, Opc.EncodingID); // Check any additional encoding fields needed. for (unsigned I = Size; I != 0; --I) { @@ -1351,10 +1379,11 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, } // Check for soft failure of the match. - emitSoftFailTableEntry(TableInfo, Opc); + emitSoftFailTableEntry(TableInfo, Opc.EncodingID); bool HasCompleteDecoder; - unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder); + unsigned DIdx = + getDecoderIndex(TableInfo.Decoders, Opc.EncodingID, HasCompleteDecoder); // Produce OPC_Decode or OPC_TryDecode opcode based on the information // whether the instruction decoder is complete or not. If it is complete @@ -1367,8 +1396,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // can decode it. TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode : MCD::OPC_TryDecode); + NumEncodingsSupported++; uint8_t Buffer[16], *p; - encodeULEB128(Opc, Buffer); + encodeULEB128(Opc.Opcode, Buffer); for (p = Buffer; *p >= 128 ; ++p) TableInfo.Table.push_back(*p); TableInfo.Table.push_back(*p); @@ -1394,7 +1424,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // Emits table entries to decode the singleton, and then to decode the rest. void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, const Filter &Best) const { - unsigned Opc = Best.getSingletonOpc(); + EncodingIDAndOpcode Opc = Best.getSingletonOpc(); // complex singletons need predicate checks from the first singleton // to refer forward to the variable filterchooser that follows. @@ -1454,7 +1484,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { std::vector<uint64_t> FieldVals; insn_t Insn; - insnWithID(Insn, Opcodes[i]); + insnWithID(Insn, Opcodes[i].EncodingID); // Look for islands of undecoded bits of any instruction. if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { @@ -1498,7 +1528,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { insn_t insn; - insnWithID(insn, Opcodes[InsnIndex]); + insnWithID(insn, Opcodes[InsnIndex].EncodingID); for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) { switch (bitAttrs[BitIndex]) { @@ -1717,9 +1747,12 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const { dumpStack(errs(), "\t\t"); for (unsigned i = 0; i < Opcodes.size(); ++i) { - errs() << '\t' << AllInstructions[Opcodes[i]] << " "; - dumpBits(errs(), - getBitsField(*AllInstructions[Opcodes[i]].EncodingDef, "Inst")); + errs() << '\t'; + emitNameWithID(errs(), Opcodes[i].EncodingID); + errs() << " "; + dumpBits( + errs(), + getBitsField(*AllInstructions[Opcodes[i].EncodingID].EncodingDef, "Inst")); errs() << '\n'; } } @@ -1751,24 +1784,25 @@ static std::string findOperandDecoderMethod(TypedInit *TI) { return Decoder; } -static bool populateInstruction(CodeGenTarget &Target, - const CodeGenInstruction &CGI, unsigned Opc, - std::map<unsigned, std::vector<OperandInfo>> &Operands){ +static bool +populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, + const CodeGenInstruction &CGI, unsigned Opc, + std::map<unsigned, std::vector<OperandInfo>> &Operands) { const Record &Def = *CGI.TheDef; // If all the bit positions are not specified; do not decode this instruction. // We are bound to fail! For proper disassembly, the well-known encoding bits // of the instruction must be fully specified. - BitsInit &Bits = getBitsField(Def, "Inst"); + BitsInit &Bits = getBitsField(EncodingDef, "Inst"); if (Bits.allInComplete()) return false; std::vector<OperandInfo> InsnOperands; // If the instruction has specified a custom decoding hook, use that instead // of trying to auto-generate the decoder. - StringRef InstDecoder = Def.getValueAsString("DecoderMethod"); + StringRef InstDecoder = EncodingDef.getValueAsString("DecoderMethod"); if (InstDecoder != "") { - bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder"); + bool HasCompleteInstDecoder = EncodingDef.getValueAsBit("hasCompleteDecoder"); InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder)); Operands[Opc] = InsnOperands; return true; @@ -2144,7 +2178,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " const FeatureBitset& Bits = STI.getFeatureBits();\n" << "\n" << " const uint8_t *Ptr = DecodeTable;\n" - << " uint32_t CurFieldValue = 0;\n" + << " InsnType CurFieldValue = 0;\n" << " DecodeStatus S = MCDisassembler::Success;\n" << " while (true) {\n" << " ptrdiff_t Loc = Ptr - DecodeTable;\n" @@ -2189,7 +2223,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " unsigned Len = *++Ptr;\n" << " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\n" << " // Decode the field value.\n" - << " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\n" + << " InsnType ExpectedValue = decodeULEB128(++Ptr, &Len);\n" << " Ptr += Len;\n" << " // NumToSkip is a plain 24-bit integer.\n" << " unsigned NumToSkip = *Ptr++;\n" @@ -2336,37 +2370,52 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { // Parameterize the decoders based on namespace and instruction width. const auto &NumberedInstructions = Target.getInstructionsByEnumValue(); NumberedEncodings.reserve(NumberedInstructions.size()); - for (const auto &NumberedInstruction : NumberedInstructions) + DenseMap<Record *, unsigned> IndexOfInstruction; + for (const auto &NumberedInstruction : NumberedInstructions) { + IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size(); NumberedEncodings.emplace_back(NumberedInstruction->TheDef, NumberedInstruction); + } + for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding")) + NumberedEncodings.emplace_back( + NumberedAlias, + &Target.getInstruction(NumberedAlias->getValueAsDef("AliasOf"))); - std::map<std::pair<std::string, unsigned>, - std::vector<unsigned>> OpcMap; + std::map<std::pair<std::string, unsigned>, std::vector<EncodingIDAndOpcode>> + OpcMap; std::map<unsigned, std::vector<OperandInfo>> Operands; for (unsigned i = 0; i < NumberedEncodings.size(); ++i) { + const Record *EncodingDef = NumberedEncodings[i].EncodingDef; const CodeGenInstruction *Inst = NumberedEncodings[i].Inst; const Record *Def = Inst->TheDef; - unsigned Size = Def->getValueAsInt("Size"); + unsigned Size = EncodingDef->getValueAsInt("Size"); if (Def->getValueAsString("Namespace") == "TargetOpcode" || Def->getValueAsBit("isPseudo") || Def->getValueAsBit("isAsmParserOnly") || - Def->getValueAsBit("isCodeGenOnly")) + Def->getValueAsBit("isCodeGenOnly")) { + NumEncodingsLackingDisasm++; continue; + } - StringRef DecoderNamespace = Def->getValueAsString("DecoderNamespace"); + if (i < NumberedInstructions.size()) + NumInstructions++; + NumEncodings++; + + StringRef DecoderNamespace = EncodingDef->getValueAsString("DecoderNamespace"); if (Size) { - if (populateInstruction(Target, *Inst, i, Operands)) { - OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i); - } + if (populateInstruction(Target, *EncodingDef, *Inst, i, Operands)) { + OpcMap[std::make_pair(DecoderNamespace, Size)].emplace_back(i, IndexOfInstruction.find(Def)->second); + } else + NumEncodingsOmitted++; } } DecoderTableInfo TableInfo; for (const auto &Opc : OpcMap) { // Emit the decoder for this namespace+width combination. - ArrayRef<EncodingAndInst> NumberedEncodingsRef(NumberedEncodings.data(), - NumberedEncodings.size()); + ArrayRef<EncodingAndInst> NumberedEncodingsRef( + NumberedEncodings.data(), NumberedEncodings.size()); FilterChooser FC(NumberedEncodingsRef, Opc.second, Operands, 8 * Opc.first.second, this); diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index 997ceb12becd..f1c02134198b 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -1,9 +1,8 @@ //===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -233,6 +232,23 @@ static std::string explainPredicates(const TreePatternNode *N) { if (Record *VT = P.getScalarMemoryVT()) Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str(); + if (ListInit *AddrSpaces = P.getAddressSpaces()) { + raw_string_ostream OS(Explanation); + OS << " AddressSpaces=["; + + StringRef AddrSpaceSeparator; + for (Init *Val : AddrSpaces->getValues()) { + IntInit *IntVal = dyn_cast<IntInit>(Val); + if (!IntVal) + continue; + + OS << AddrSpaceSeparator << IntVal->getValue(); + AddrSpaceSeparator = ", "; + } + + OS << ']'; + } + if (P.isAtomicOrderingMonotonic()) Explanation += " monotonic"; if (P.isAtomicOrderingAcquire()) @@ -298,7 +314,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) { Predicate.isSignExtLoad() || Predicate.isZeroExtLoad()) continue; - if (Predicate.isNonTruncStore()) + if (Predicate.isNonTruncStore() || Predicate.isTruncStore()) continue; if (Predicate.isLoad() && Predicate.getMemoryVT()) @@ -309,6 +325,12 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) { continue; } + if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) { + const ListInit *AddrSpaces = Predicate.getAddressSpaces(); + if (AddrSpaces && !AddrSpaces->empty()) + continue; + } + if (Predicate.isAtomic() && Predicate.getMemoryVT()) continue; @@ -882,12 +904,19 @@ public: void defineOperand(StringRef SymbolicName, OperandMatcher &OM); - void defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern, - unsigned RendererID, unsigned SubOperandID) { - assert(ComplexSubOperands.count(SymbolicName) == 0 && "Already defined"); + Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern, + unsigned RendererID, unsigned SubOperandID) { + if (ComplexSubOperands.count(SymbolicName)) + return failedImport( + "Complex suboperand referenced more than once (Operand: " + + SymbolicName + ")"); + ComplexSubOperands[SymbolicName] = std::make_tuple(ComplexPattern, RendererID, SubOperandID); + + return Error::success(); } + Optional<DefinedComplexPatternSubOperand> getComplexSubOperand(StringRef SymbolicName) const { const auto &I = ComplexSubOperands.find(SymbolicName); @@ -1022,6 +1051,7 @@ public: IPM_AtomicOrderingMMO, IPM_MemoryLLTSize, IPM_MemoryVsLLTSize, + IPM_MemoryAddressSpace, IPM_GenericPredicate, OPM_SameOperand, OPM_ComplexPattern, @@ -1507,6 +1537,9 @@ Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy, if (OperandIsAPointer) addPredicate<PointerToAnyOperandMatcher>(OpTyOrNone->get().getSizeInBits()); + else if (VTy.isPointer()) + addPredicate<LLTOperandMatcher>(LLT::pointer(VTy.getPtrAddrSpace(), + OpTyOrNone->get().getSizeInBits())); else addPredicate<LLTOperandMatcher>(*OpTyOrNone); return Error::success(); @@ -1780,6 +1813,42 @@ public: } }; +class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher { +protected: + unsigned MMOIdx; + SmallVector<unsigned, 4> AddrSpaces; + +public: + MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, + ArrayRef<unsigned> AddrSpaces) + : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID), + MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {} + + static bool classof(const PredicateMatcher *P) { + return P->getKind() == IPM_MemoryAddressSpace; + } + bool isIdentical(const PredicateMatcher &B) const override { + if (!InstructionPredicateMatcher::isIdentical(B)) + return false; + auto *Other = cast<MemoryAddressSpacePredicateMatcher>(&B); + return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces; + } + + void emitPredicateOpcodes(MatchTable &Table, + RuleMatcher &Rule) const override { + Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace") + << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID) + << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx) + // Encode number of address spaces to expect. + << MatchTable::Comment("NumAddrSpace") + << MatchTable::IntValue(AddrSpaces.size()); + for (unsigned AS : AddrSpaces) + Table << MatchTable::Comment("AddrSpace") << MatchTable::IntValue(AS); + + Table << MatchTable::LineBreak; + } +}; + /// Generates code to check that the size of an MMO is less-than, equal-to, or /// greater than a given LLT. class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher { @@ -3028,7 +3097,8 @@ private: importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder, TreePatternNode *DstChild); - Error importDefaultOperandRenderers(BuildMIAction &DstMIBuilder, + Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M, + BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const; Error importImplicitDefRenderers(BuildMIAction &DstMIBuilder, @@ -3200,7 +3270,26 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( continue; } - // G_LOAD is used for both non-extending and any-extending loads. + // An address space check is needed in all contexts if there is one. + if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) { + if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) { + SmallVector<unsigned, 4> ParsedAddrSpaces; + + for (Init *Val : AddrSpaces->getValues()) { + IntInit *IntVal = dyn_cast<IntInit>(Val); + if (!IntVal) + return failedImport("Address space is not an integer"); + ParsedAddrSpaces.push_back(IntVal->getValue()); + } + + if (!ParsedAddrSpaces.empty()) { + InsnMatcher.addPredicate<MemoryAddressSpacePredicateMatcher>( + 0, ParsedAddrSpaces); + } + } + } + + // G_LOAD is used for both non-extending and any-extending loads. if (Predicate.isLoad() && Predicate.isNonExtLoad()) { InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0); @@ -3212,6 +3301,13 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( continue; } + if (Predicate.isStore() && Predicate.isTruncStore()) { + // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size. + InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( + 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0); + continue; + } + // No check required. We already did it by swapping the opcode. if (!SrcGIEquivOrNull->isValueUnset("IfSignExtend") && Predicate.isSignExtLoad()) @@ -3422,9 +3518,12 @@ Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule, for (unsigned i = 0, e = SrcChild->getNumChildren(); i != e; ++i) { auto *SubOperand = SrcChild->getChild(i); - if (!SubOperand->getName().empty()) - Rule.defineComplexSubOperand(SubOperand->getName(), - SrcChild->getOperator(), RendererID, i); + if (!SubOperand->getName().empty()) { + if (auto Error = Rule.defineComplexSubOperand(SubOperand->getName(), + SrcChild->getOperator(), + RendererID, i)) + return Error; + } } return Error::success(); @@ -3765,7 +3864,8 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers( // end up with too many rendered operands. if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) { DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps"); - if (auto Error = importDefaultOperandRenderers(DstMIBuilder, DefaultOps)) + if (auto Error = importDefaultOperandRenderers( + InsertPt, M, DstMIBuilder, DefaultOps)) return std::move(Error); ++NumDefaultOps; continue; @@ -3790,19 +3890,39 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers( } Error GlobalISelEmitter::importDefaultOperandRenderers( - BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const { + action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, + DagInit *DefaultOps) const { for (const auto *DefaultOp : DefaultOps->getArgs()) { + Optional<LLTCodeGen> OpTyOrNone = None; + // Look through ValueType operators. if (const DagInit *DefaultDagOp = dyn_cast<DagInit>(DefaultOp)) { if (const DefInit *DefaultDagOperator = dyn_cast<DefInit>(DefaultDagOp->getOperator())) { - if (DefaultDagOperator->getDef()->isSubClassOf("ValueType")) + if (DefaultDagOperator->getDef()->isSubClassOf("ValueType")) { + OpTyOrNone = MVTToLLT(getValueType( + DefaultDagOperator->getDef())); DefaultOp = DefaultDagOp->getArg(0); + } } } if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) { - DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef()); + auto Def = DefaultDefOp->getDef(); + if (Def->getName() == "undef_tied_input") { + unsigned TempRegID = M.allocateTempRegID(); + M.insertAction<MakeTempRegisterAction>( + InsertPt, OpTyOrNone.getValue(), TempRegID); + InsertPt = M.insertAction<BuildMIAction>( + InsertPt, M.allocateOutputInsnID(), + &Target.getInstruction(RK.getDef("IMPLICIT_DEF"))); + BuildMIAction &IDMIBuilder = *static_cast<BuildMIAction *>( + InsertPt->get()); + IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID); + DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID); + } else { + DstMIBuilder.addRenderer<AddRegisterRenderer>(Def); + } continue; } @@ -4489,8 +4609,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) { << ", // " << Record->getName() << "\n"; OS << "};\n\n"; - std::stable_sort(Rules.begin(), Rules.end(), [&](const RuleMatcher &A, - const RuleMatcher &B) { + llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) { int ScoreA = RuleMatcherScores[A.getRuleID()]; int ScoreB = RuleMatcherScores[B.getRuleID()]; if (ScoreA > ScoreB) diff --git a/utils/TableGen/InfoByHwMode.cpp b/utils/TableGen/InfoByHwMode.cpp index 086e12dafd74..d9662889a5db 100644 --- a/utils/TableGen/InfoByHwMode.cpp +++ b/utils/TableGen/InfoByHwMode.cpp @@ -1,9 +1,8 @@ //===--- InfoByHwMode.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Classes that implement data parameterized by HW modes for instruction @@ -39,6 +38,11 @@ ValueTypeByHwMode::ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH) { } } +ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) { + if (R->isSubClassOf("PtrValueType")) + PtrAddrSpace = R->getValueAsInt("AddrSpace"); +} + bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const { assert(isValid() && T.isValid() && "Invalid type in assignment"); bool Simple = isSimple(); @@ -112,7 +116,7 @@ ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec, "Record must be derived from ValueType"); if (Rec->isSubClassOf("HwModeSelect")) return ValueTypeByHwMode(Rec, CGH); - return ValueTypeByHwMode(llvm::getValueType(Rec)); + return ValueTypeByHwMode(Rec, llvm::getValueType(Rec)); } RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) { diff --git a/utils/TableGen/InfoByHwMode.h b/utils/TableGen/InfoByHwMode.h index 7be4678f271b..9e5cc3d5f2a4 100644 --- a/utils/TableGen/InfoByHwMode.h +++ b/utils/TableGen/InfoByHwMode.h @@ -1,9 +1,8 @@ //===--- InfoByHwMode.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Classes that implement data parameterized by HW modes for instruction @@ -120,6 +119,7 @@ struct InfoByHwMode { struct ValueTypeByHwMode : public InfoByHwMode<MVT> { ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH); + ValueTypeByHwMode(Record *R, MVT T); ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); } ValueTypeByHwMode() = default; @@ -135,6 +135,11 @@ struct ValueTypeByHwMode : public InfoByHwMode<MVT> { static StringRef getMVTName(MVT T); void writeToStream(raw_ostream &OS) const; void dump() const; + + unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max(); + bool isPointer() const { + return PtrAddrSpace != std::numeric_limits<unsigned>::max(); + } }; ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, diff --git a/utils/TableGen/InstrDocsEmitter.cpp b/utils/TableGen/InstrDocsEmitter.cpp index 9d50351854ec..91c457ba08fd 100644 --- a/utils/TableGen/InstrDocsEmitter.cpp +++ b/utils/TableGen/InstrDocsEmitter.cpp @@ -1,9 +1,8 @@ //===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 39d9e8526386..2d367f538b71 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -1,9 +1,8 @@ //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -77,7 +76,9 @@ private: std::map<std::vector<Record*>, unsigned> &EL, const OperandInfoMapTy &OpInfo, raw_ostream &OS); - void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target); + void emitOperandTypeMappings( + raw_ostream &OS, const CodeGenTarget &Target, + ArrayRef<const CodeGenInstruction *> NumberedInstructions); void initOperandMapData( ArrayRef<const CodeGenInstruction *> NumberedInstructions, StringRef Namespace, @@ -212,7 +213,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, } /// Initialize data structures for generating operand name mappings. -/// +/// /// \param Operands [out] A map used to generate the OpName enum with operand /// names as its keys and operand enum values as its values. /// \param OperandMap [out] A map for representing the operand name mappings for @@ -325,8 +326,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, /// Generate an enum for all the operand types for this target, under the /// llvm::TargetNamespace::OpTypes namespace. /// Operand types are all definitions derived of the Operand Target.td class. -void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, - const CodeGenTarget &Target) { +void InstrInfoEmitter::emitOperandTypeMappings( + raw_ostream &OS, const CodeGenTarget &Target, + ArrayRef<const CodeGenInstruction *> NumberedInstructions) { StringRef Namespace = Target.getInstNamespace(); std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand"); @@ -350,6 +352,69 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, OS << "} // end namespace " << Namespace << "\n"; OS << "} // end namespace llvm\n"; OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n"; + + OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n"; + OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n"; + OS << "namespace llvm {\n"; + OS << "namespace " << Namespace << " {\n"; + OS << "LLVM_READONLY\n"; + OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n"; + if (!NumberedInstructions.empty()) { + std::vector<int> OperandOffsets; + std::vector<Record *> OperandRecords; + int CurrentOffset = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + OperandOffsets.push_back(CurrentOffset); + for (const auto &Op : Inst->Operands) { + const DagInit *MIOI = Op.MIOperandInfo; + if (!MIOI || MIOI->getNumArgs() == 0) { + // Single, anonymous, operand. + OperandRecords.push_back(Op.Rec); + ++CurrentOffset; + } else { + for (Init *Arg : make_range(MIOI->arg_begin(), MIOI->arg_end())) { + OperandRecords.push_back(cast<DefInit>(Arg)->getDef()); + ++CurrentOffset; + } + } + } + } + + // Emit the table of offsets for the opcode lookup. + OS << " const int Offsets[] = {\n"; + for (int I = 0, E = OperandOffsets.size(); I != E; ++I) + OS << " " << OperandOffsets[I] << ",\n"; + OS << " };\n"; + + // Add an entry for the end so that we don't need to special case it below. + OperandOffsets.push_back(OperandRecords.size()); + // Emit the actual operand types in a flat table. + OS << " const int OpcodeOperandTypes[] = {\n "; + for (int I = 0, E = OperandRecords.size(), CurOffset = 1; I != E; ++I) { + // We print each Opcode's operands in its own row. + if (I == OperandOffsets[CurOffset]) { + OS << "\n "; + // If there are empty rows, mark them with an empty comment. + while (OperandOffsets[++CurOffset] == I) + OS << "/**/\n "; + } + Record *OpR = OperandRecords[I]; + if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous()) + OS << "OpTypes::" << OpR->getName(); + else + OS << -1; + OS << ", "; + } + OS << "\n };\n"; + + OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n"; + } else { + OS << " llvm_unreachable(\"No instructions defined\");\n"; + } + OS << "}\n"; + OS << "} // end namespace " << Namespace << "\n"; + OS << "} // end namespace llvm\n"; + OS << "#endif //GET_INSTRINFO_OPERAND_TYPE\n\n"; } void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS, @@ -561,7 +626,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { emitOperandNameMappings(OS, Target, NumberedInstructions); - emitOperandTypesEnum(OS, Target); + emitOperandTypeMappings(OS, Target, NumberedInstructions); emitMCIIHelperMethods(OS, TargetName); } @@ -604,6 +669,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)"; if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)"; if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)"; + if (Inst.mayRaiseFPException) OS << "|(1ULL<<MCID::MayRaiseFPException)"; if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)"; if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)"; if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)"; @@ -629,13 +695,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); if (!TSF) - PrintFatalError("no TSFlags?"); + PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?"); uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i))) Value |= uint64_t(Bit->getValue()) << i; else - PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); + PrintFatalError(Inst.TheDef->getLoc(), + "Invalid TSFlags bit in " + Inst.TheDef->getName()); } OS << ", 0x"; OS.write_hex(Value); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 049282e5ebfe..979af98f6768 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -1,9 +1,8 @@ //===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -220,7 +219,8 @@ enum IIT_Info { IIT_STRUCT6 = 38, IIT_STRUCT7 = 39, IIT_STRUCT8 = 40, - IIT_F128 = 41 + IIT_F128 = 41, + IIT_VEC_ELEMENT = 42 }; static void EncodeFixedValueType(MVT::SimpleValueType VT, @@ -259,10 +259,12 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, #endif static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, - std::vector<unsigned char> &Sig) { + unsigned &NextArgCode, + std::vector<unsigned char> &Sig, + ArrayRef<unsigned char> Mapping) { if (R->isSubClassOf("LLVMMatchType")) { - unsigned Number = R->getValueAsInt("Number"); + unsigned Number = Mapping[R->getValueAsInt("Number")]; assert(Number < ArgCodes.size() && "Invalid matching number!"); if (R->isSubClassOf("LLVMExtendedType")) Sig.push_back(IIT_EXTEND_ARG); @@ -270,7 +272,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, Sig.push_back(IIT_TRUNC_ARG); else if (R->isSubClassOf("LLVMHalfElementsVectorType")) Sig.push_back(IIT_HALF_VEC_ARG); - else if (R->isSubClassOf("LLVMVectorSameWidth")) { + else if (R->isSubClassOf("LLVMScalarOrSameVectorWidth")) { Sig.push_back(IIT_SAME_VEC_WIDTH_ARG); Sig.push_back((Number << 3) | ArgCodes[Number]); MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy")); @@ -281,18 +283,18 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, Sig.push_back(IIT_PTR_TO_ARG); else if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) { Sig.push_back(IIT_VEC_OF_ANYPTRS_TO_ELT); - unsigned ArgNo = ArgCodes.size(); - ArgCodes.push_back(3 /*vAny*/); // Encode overloaded ArgNo - Sig.push_back(ArgNo); + Sig.push_back(NextArgCode++); // Encode LLVMMatchType<Number> ArgNo Sig.push_back(Number); return; } else if (R->isSubClassOf("LLVMPointerToElt")) Sig.push_back(IIT_PTR_TO_ELT); + else if (R->isSubClassOf("LLVMVectorElementType")) + Sig.push_back(IIT_VEC_ELEMENT); else Sig.push_back(IIT_ARG); - return Sig.push_back((Number << 3) | ArgCodes[Number]); + return Sig.push_back((Number << 3) | 7 /*IITDescriptor::AK_MatchType*/); } MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); @@ -310,8 +312,9 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, Sig.push_back(IIT_ARG); // Figure out what arg # this is consuming, and remember what kind it was. - unsigned ArgNo = ArgCodes.size(); - ArgCodes.push_back(Tmp); + assert(NextArgCode < ArgCodes.size() && ArgCodes[NextArgCode] == Tmp && + "Invalid or no ArgCode associated with overloaded VT!"); + unsigned ArgNo = NextArgCode++; // Encode what sort of argument it must be in the low 3 bits of the ArgNo. return Sig.push_back((ArgNo << 3) | Tmp); @@ -329,7 +332,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, } else { Sig.push_back(IIT_PTR); } - return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig); + return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig, + Mapping); } } @@ -354,6 +358,45 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, EncodeFixedValueType(VT, Sig); } +static void UpdateArgCodes(Record *R, std::vector<unsigned char> &ArgCodes, + unsigned int &NumInserted, + SmallVectorImpl<unsigned char> &Mapping) { + if (R->isSubClassOf("LLVMMatchType")) { + if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) { + ArgCodes.push_back(3 /*vAny*/); + ++NumInserted; + } + return; + } + + unsigned Tmp = 0; + switch (getValueType(R->getValueAsDef("VT"))) { + default: break; + case MVT::iPTR: + UpdateArgCodes(R->getValueAsDef("ElTy"), ArgCodes, NumInserted, Mapping); + break; + case MVT::iPTRAny: + ++Tmp; + LLVM_FALLTHROUGH; + case MVT::vAny: + ++Tmp; + LLVM_FALLTHROUGH; + case MVT::fAny: + ++Tmp; + LLVM_FALLTHROUGH; + case MVT::iAny: + ++Tmp; + LLVM_FALLTHROUGH; + case MVT::Any: + unsigned OriginalIdx = ArgCodes.size() - NumInserted; + assert(OriginalIdx >= Mapping.size()); + Mapping.resize(OriginalIdx+1); + Mapping[OriginalIdx] = ArgCodes.size(); + ArgCodes.push_back(Tmp); + break; + } +} + #if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",on) #endif @@ -364,6 +407,17 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int, std::vector<unsigned char> &TypeSig) { std::vector<unsigned char> ArgCodes; + // Add codes for any overloaded result VTs. + unsigned int NumInserted = 0; + SmallVector<unsigned char, 8> ArgMapping; + for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i) + UpdateArgCodes(Int.IS.RetTypeDefs[i], ArgCodes, NumInserted, ArgMapping); + + // Add codes for any overloaded operand VTs. + for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i) + UpdateArgCodes(Int.IS.ParamTypeDefs[i], ArgCodes, NumInserted, ArgMapping); + + unsigned NextArgCode = 0; if (Int.IS.RetVTs.empty()) TypeSig.push_back(IIT_Done); else if (Int.IS.RetVTs.size() == 1 && @@ -383,11 +437,13 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int, } for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i) - EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig); + EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, NextArgCode, TypeSig, + ArgMapping); } for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i) - EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig); + EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, NextArgCode, TypeSig, + ArgMapping); } static void printIITEntry(raw_ostream &OS, unsigned char X) { @@ -489,6 +545,9 @@ struct AttributeComparator { if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; + if (L->isWillReturn != R->isWillReturn) + return R->isWillReturn; + if (L->isCold != R->isCold) return R->isCold; @@ -505,7 +564,6 @@ struct AttributeComparator { CodeGenIntrinsic::ModRefBehavior LK = L->ModRef; CodeGenIntrinsic::ModRefBehavior RK = R->ModRef; if (LK != RK) return (LK > RK); - // Order by argument attributes. // This is reliable because each side is already sorted internally. return (L->ArgumentAttributes < R->ArgumentAttributes); @@ -613,6 +671,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << "Attribute::ReadNone"; addComma = true; break; + case CodeGenIntrinsic::ImmArg: + if (addComma) + OS << ','; + OS << "Attribute::ImmArg"; + addComma = true; + break; } ++ai; @@ -624,9 +688,10 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, } if (!intrinsic.canThrow || - intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || - intrinsic.isNoReturn || intrinsic.isCold || intrinsic.isNoDuplicate || - intrinsic.isConvergent || intrinsic.isSpeculatable) { + (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) || + intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold || + intrinsic.isNoDuplicate || intrinsic.isConvergent || + intrinsic.isSpeculatable) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -639,6 +704,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << "Attribute::NoReturn"; addComma = true; } + if (intrinsic.isWillReturn) { + if (addComma) + OS << ","; + OS << "Attribute::WillReturn"; + addComma = true; + } if (intrinsic.isCold) { if (addComma) OS << ","; @@ -666,6 +737,8 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, switch (intrinsic.ModRef) { case CodeGenIntrinsic::NoMem: + if (intrinsic.hasSideEffects) + break; if (addComma) OS << ","; OS << "Attribute::ReadNone"; @@ -771,8 +844,9 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap( BuiltinMap[Ints[i].TargetPrefix]; if (!BIM.insert(std::make_pair(BuiltinName, Ints[i].EnumName)).second) - PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() + - "': duplicate " + CompilerName + " builtin name!"); + PrintFatalError(Ints[i].TheDef->getLoc(), + "Intrinsic '" + Ints[i].TheDef->getName() + + "': duplicate " + CompilerName + " builtin name!"); Table.GetOrAddStringOffset(BuiltinName); } } diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 0358cf26509b..51b1cb093b21 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -1,9 +1,8 @@ //===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/PredicateExpander.cpp b/utils/TableGen/PredicateExpander.cpp index 2e01b7c3138e..9f7f40db2626 100644 --- a/utils/TableGen/PredicateExpander.cpp +++ b/utils/TableGen/PredicateExpander.cpp @@ -1,9 +1,8 @@ //===--------------------- PredicateExpander.cpp --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file diff --git a/utils/TableGen/PredicateExpander.h b/utils/TableGen/PredicateExpander.h index 0f3ee6867e65..115a81cf123b 100644 --- a/utils/TableGen/PredicateExpander.h +++ b/utils/TableGen/PredicateExpander.h @@ -1,9 +1,8 @@ //===--------------------- PredicateExpander.h ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index a363015730f3..3a80d8e5d1c4 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -1,9 +1,8 @@ //===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/RISCVCompressInstEmitter.cpp b/utils/TableGen/RISCVCompressInstEmitter.cpp index e03663b40f8a..e62f528ebc2e 100644 --- a/utils/TableGen/RISCVCompressInstEmitter.cpp +++ b/utils/TableGen/RISCVCompressInstEmitter.cpp @@ -1,9 +1,8 @@ //===- RISCVCompressInstEmitter.cpp - Generator for RISCV Compression -===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // RISCVCompressInstEmitter implements a tablegen-driven CompressPat based // RISCV Instruction Compression mechanism. @@ -65,6 +64,7 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include <set> #include <vector> using namespace llvm; @@ -253,12 +253,14 @@ static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, // Source instructions are non compressed instructions and don't have tied // operands. if (IsSource) - PrintFatalError("Input operands for Inst '" + Inst.TheDef->getName() + - "' and input Dag operand count mismatch"); + PrintFatalError(Inst.TheDef->getLoc(), + "Input operands for Inst '" + Inst.TheDef->getName() + + "' and input Dag operand count mismatch"); // The Dag can't have more arguments than the Instruction. if (Dag->getNumArgs() > Inst.Operands.size()) - PrintFatalError("Inst '" + Inst.TheDef->getName() + - "' and Dag operand count mismatch"); + PrintFatalError(Inst.TheDef->getLoc(), + "Inst '" + Inst.TheDef->getName() + + "' and Dag operand count mismatch"); // The Instruction might have tied operands so the Dag might have // a fewer operand count. @@ -268,8 +270,9 @@ static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, --RealCount; if (Dag->getNumArgs() != RealCount) - PrintFatalError("Inst '" + Inst.TheDef->getName() + - "' and Dag operand count mismatch"); + PrintFatalError(Inst.TheDef->getLoc(), + "Inst '" + Inst.TheDef->getName() + + "' and Dag operand count mismatch"); return true; } @@ -472,7 +475,7 @@ void RISCVCompressInstEmitter::evaluateCompressPat(Record *Rec) { SourceOperandMap, DestOperandMap)); } -static void getReqFeatures(std::map<StringRef, int> &FeaturesMap, +static void getReqFeatures(std::set<StringRef> &FeaturesSet, const std::vector<Record *> &ReqFeatures) { for (auto &R : ReqFeatures) { StringRef AsmCondString = R->getValueAsString("AssemblerCondString"); @@ -481,11 +484,9 @@ static void getReqFeatures(std::map<StringRef, int> &FeaturesMap, SmallVector<StringRef, 4> Ops; SplitString(AsmCondString, Ops, ","); assert(!Ops.empty() && "AssemblerCondString cannot be empty"); - for (auto &Op : Ops) { assert(!Op.empty() && "Empty operator"); - if (FeaturesMap.find(Op) == FeaturesMap.end()) - FeaturesMap[Op] = FeaturesMap.size(); + FeaturesSet.insert(Op); } } } @@ -530,7 +531,8 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, bool Compress) { Record *AsmWriter = Target.getAsmWriter(); if (!AsmWriter->getValueAsInt("PassSubtarget")) - PrintFatalError("'PassSubtarget' is false. SubTargetInfo object is needed " + PrintFatalError(AsmWriter->getLoc(), + "'PassSubtarget' is false. SubTargetInfo object is needed " "for target features.\n"); std::string Namespace = Target.getName(); @@ -540,15 +542,15 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the // source and destination are flipped and the sort key needs to change // accordingly. - std::stable_sort(CompressPatterns.begin(), CompressPatterns.end(), - [Compress](const CompressPat &LHS, const CompressPat &RHS) { - if (Compress) - return (LHS.Source.TheDef->getName().str() < - RHS.Source.TheDef->getName().str()); - else - return (LHS.Dest.TheDef->getName().str() < - RHS.Dest.TheDef->getName().str()); - }); + llvm::stable_sort(CompressPatterns, + [Compress](const CompressPat &LHS, const CompressPat &RHS) { + if (Compress) + return (LHS.Source.TheDef->getName().str() < + RHS.Source.TheDef->getName().str()); + else + return (LHS.Dest.TheDef->getName().str() < + RHS.Dest.TheDef->getName().str()); + }); // A list of MCOperandPredicates for all operands in use, and the reverse map. std::vector<const Record *> MCOpPredicates; @@ -617,9 +619,9 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n"; } - std::map<StringRef, int> FeaturesMap; + std::set<StringRef> FeaturesSet; // Add CompressPat required features. - getReqFeatures(FeaturesMap, CompressPat.PatReqFeatures); + getReqFeatures(FeaturesSet, CompressPat.PatReqFeatures); // Add Dest instruction required features. std::vector<Record *> ReqFeatures; @@ -627,11 +629,10 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { return R->getValueAsBit("AssemblerMatcherPredicate"); }); - getReqFeatures(FeaturesMap, ReqFeatures); + getReqFeatures(FeaturesSet, ReqFeatures); // Emit checks for all required features. - for (auto &F : FeaturesMap) { - StringRef Op = F.first; + for (auto &Op : FeaturesSet) { if (Op[0] == '!') CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace + "::" + Op.substr(1) + "]") diff --git a/utils/TableGen/RegisterBankEmitter.cpp b/utils/TableGen/RegisterBankEmitter.cpp index 879b4162d629..7f6b3931d3de 100644 --- a/utils/TableGen/RegisterBankEmitter.cpp +++ b/utils/TableGen/RegisterBankEmitter.cpp @@ -1,9 +1,8 @@ //===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index ded54c828bcd..1b619072c814 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -1,9 +1,8 @@ //===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/SDNodeProperties.cpp b/utils/TableGen/SDNodeProperties.cpp index 343febc99d1e..1843a78aa3cf 100644 --- a/utils/TableGen/SDNodeProperties.cpp +++ b/utils/TableGen/SDNodeProperties.cpp @@ -1,9 +1,8 @@ //===- SDNodeProperties.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -39,9 +38,9 @@ unsigned llvm::parseSDPatternOperatorProperties(Record *R) { } else if (Property->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; } else { - PrintFatalError("Unknown SD Node property '" + - Property->getName() + "' on node '" + - R->getName() + "'!"); + PrintFatalError(R->getLoc(), "Unknown SD Node property '" + + Property->getName() + "' on node '" + + R->getName() + "'!"); } } diff --git a/utils/TableGen/SDNodeProperties.h b/utils/TableGen/SDNodeProperties.h index a8d4efb5dab0..66a04e63150c 100644 --- a/utils/TableGen/SDNodeProperties.h +++ b/utils/TableGen/SDNodeProperties.h @@ -1,9 +1,8 @@ //===- SDNodeProperties.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/SearchableTableEmitter.cpp b/utils/TableGen/SearchableTableEmitter.cpp index f98a7c74bf0c..954b63e7253c 100644 --- a/utils/TableGen/SearchableTableEmitter.cpp +++ b/utils/TableGen/SearchableTableEmitter.cpp @@ -1,9 +1,8 @@ //===- SearchableTableEmitter.cpp - Generate efficiently searchable tables -==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -142,7 +141,7 @@ private: bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index); bool isIntegral(Init *I) { - return isa<BitsInit>(I) || isIntrinsic(I); + return isa<BitsInit>(I) || isa<CodeInit>(I) || isIntrinsic(I); } std::string searchableFieldType(const GenericField &Field, TypeContext Ctx) { @@ -600,9 +599,10 @@ void SearchableTableEmitter::collectTableEntries( for (auto &Field : Table.Fields) { auto TI = dyn_cast<TypedInit>(EntryRec->getValueInit(Field.Name)); if (!TI) { - PrintFatalError(Twine("Record '") + EntryRec->getName() + - "' in table '" + Table.Name + "' is missing field '" + - Field.Name + "'"); + PrintFatalError(EntryRec->getLoc(), + Twine("Record '") + EntryRec->getName() + + "' in table '" + Table.Name + + "' is missing field '" + Field.Name + "'"); } if (!Field.RecType) { Field.RecType = TI->getType(); @@ -611,7 +611,7 @@ void SearchableTableEmitter::collectTableEntries( if (!Ty) PrintFatalError(Twine("Field '") + Field.Name + "' of table '" + Table.Name + "' has incompatible type: " + - Ty->getAsString() + " vs. " + + Field.RecType->getAsString() + " vs. " + TI->getType()->getAsString()); Field.RecType = Ty; } @@ -654,8 +654,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) { StringRef FilterClass = EnumRec->getValueAsString("FilterClass"); Enum->Class = Records.getClass(FilterClass); if (!Enum->Class) - PrintFatalError(Twine("Enum FilterClass '") + FilterClass + - "' does not exist"); + PrintFatalError(EnumRec->getLoc(), Twine("Enum FilterClass '") + + FilterClass + "' does not exist"); collectEnumEntries(*Enum, NameField, ValueField, Records.getAllDerivedDefinitions(FilterClass)); @@ -675,9 +675,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) { if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) { if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) { - PrintFatalError(Twine("Table '") + Table->Name + - "' has bad 'TypeOf_" + FieldName + "': " + - TypeOfVal->getValue()->getAsString()); + PrintFatalError(TableRec->getLoc(), + Twine("Table '") + Table->Name + + "' has bad 'TypeOf_" + FieldName + + "': " + TypeOfVal->getValue()->getAsString()); } } } @@ -705,8 +706,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) { Record *TableRec = IndexRec->getValueAsDef("Table"); auto It = TableMap.find(TableRec); if (It == TableMap.end()) - PrintFatalError(Twine("SearchIndex '") + IndexRec->getName() + - "' refers to non-existing table '" + TableRec->getName()); + PrintFatalError(IndexRec->getLoc(), + Twine("SearchIndex '") + IndexRec->getName() + + "' refers to non-existing table '" + + TableRec->getName()); GenericTable &Table = *It->second; Table.Indices.push_back(parseSearchIndex( diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index 2b8f66a3bf3e..8a826eff311d 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -1,9 +1,8 @@ //===-- SequenceToOffsetTable.h - Compress similar sequences ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 731c14bdb9a0..9ce2b3b275c8 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -1,9 +1,8 @@ //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -74,9 +73,11 @@ class SubtargetEmitter { CodeGenSchedModels &SchedModels; std::string Target; - void Enumeration(raw_ostream &OS); - unsigned FeatureKeyValues(raw_ostream &OS); - unsigned CPUKeyValues(raw_ostream &OS); + void Enumeration(raw_ostream &OS, DenseMap<Record *, unsigned> &FeatureMap); + unsigned FeatureKeyValues(raw_ostream &OS, + const DenseMap<Record *, unsigned> &FeatureMap); + unsigned CPUKeyValues(raw_ostream &OS, + const DenseMap<Record *, unsigned> &FeatureMap); void FormItineraryStageString(const std::string &Names, Record *ItinData, std::string &ItinString, unsigned &NStages); @@ -138,7 +139,8 @@ public: // // Enumeration - Emit the specified class as an enumeration. // -void SubtargetEmitter::Enumeration(raw_ostream &OS) { +void SubtargetEmitter::Enumeration(raw_ostream &OS, + DenseMap<Record *, unsigned> &FeatureMap) { // Get all records of class and sort std::vector<Record*> DefList = Records.getAllDerivedDefinitions("SubtargetFeature"); @@ -147,7 +149,7 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) { unsigned N = DefList.size(); if (N == 0) return; - if (N > MAX_SUBTARGET_FEATURES) + if (N + 1 > MAX_SUBTARGET_FEATURES) PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); OS << "namespace " << Target << " {\n"; @@ -162,18 +164,42 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) { // Get and emit name OS << " " << Def->getName() << " = " << i << ",\n"; + + // Save the index for this feature. + FeatureMap[Def] = i; } + OS << " " + << "NumSubtargetFeatures = " << N << "\n"; + // Close enumeration and namespace OS << "};\n"; OS << "} // end namespace " << Target << "\n"; } +static void printFeatureMask(raw_ostream &OS, RecVec &FeatureList, + const DenseMap<Record *, unsigned> &FeatureMap) { + std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {}; + for (unsigned j = 0, M = FeatureList.size(); j < M; ++j) { + unsigned Bit = FeatureMap.lookup(FeatureList[j]); + Mask[Bit / 64] |= 1ULL << (Bit % 64); + } + + OS << "{ { { "; + for (unsigned i = 0; i != Mask.size(); ++i) { + OS << "0x"; + OS.write_hex(Mask[i]); + OS << "ULL, "; + } + OS << "} } }"; +} + // // FeatureKeyValues - Emit data of all the subtarget features. Used by the // command line. // -unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { +unsigned SubtargetEmitter::FeatureKeyValues( + raw_ostream &OS, const DenseMap<Record *, unsigned> &FeatureMap) { // Gather and sort all the features std::vector<Record*> FeatureList = Records.getAllDerivedDefinitions("SubtargetFeature"); @@ -204,16 +230,13 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " - << "{ " << Target << "::" << Name << " }, "; + << Target << "::" << Name << ", "; RecVec ImpliesList = Feature->getValueAsListOfDefs("Implies"); - OS << "{"; - for (unsigned j = 0, M = ImpliesList.size(); j < M;) { - OS << " " << Target << "::" << ImpliesList[j]->getName(); - if (++j < M) OS << ","; - } - OS << " } },\n"; + printFeatureMask(OS, ImpliesList, FeatureMap); + + OS << " },\n"; ++NumFeatures; } @@ -227,7 +250,9 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // CPUKeyValues - Emit data of all the subtarget processors. Used by command // line. // -unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { +unsigned +SubtargetEmitter::CPUKeyValues(raw_ostream &OS, + const DenseMap<Record *, unsigned> &FeatureMap) { // Gather and sort processor information std::vector<Record*> ProcessorList = Records.getAllDerivedDefinitions("Processor"); @@ -235,7 +260,7 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Begin processor table OS << "// Sorted (by key) array of values for CPU subtype.\n" - << "extern const llvm::SubtargetFeatureKV " << Target + << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[] = {\n"; // For each processor @@ -243,18 +268,16 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { StringRef Name = Processor->getValueAsString("Name"); RecVec FeatureList = Processor->getValueAsListOfDefs("Features"); - // Emit as { "cpu", "description", { f1 , f2 , ... fn } }, - OS << " { " - << "\"" << Name << "\", " - << "\"Select the " << Name << " processor\", "; + // Emit as { "cpu", "description", 0, { f1 , f2 , ... fn } }, + OS << " { " + << "\"" << Name << "\", "; - OS << "{"; - for (unsigned j = 0, M = FeatureList.size(); j < M;) { - OS << " " << Target << "::" << FeatureList[j]->getName(); - if (++j < M) OS << ","; - } - // The { } is for the "implies" section of this data structure. - OS << " }, { } },\n"; + printFeatureMask(OS, FeatureList, FeatureMap); + + // Emit the scheduler model pointer. + const std::string &ProcModelName = + SchedModels.getModelForProc(Processor).ModelName; + OS << ", &" << ProcModelName << " },\n"; } // End processor table @@ -1369,33 +1392,6 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { } // -// EmitProcessorLookup - generate cpu name to sched model lookup tables. -// -void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { - // Gather and sort processor information - std::vector<Record*> ProcessorList = - Records.getAllDerivedDefinitions("Processor"); - llvm::sort(ProcessorList, LessRecordFieldName()); - - // Begin processor->sched model table - OS << "\n"; - OS << "// Sorted (by key) array of sched model for CPU subtype.\n" - << "extern const llvm::SubtargetInfoKV " << Target - << "ProcSchedKV[] = {\n"; - // For each processor - for (Record *Processor : ProcessorList) { - StringRef Name = Processor->getValueAsString("Name"); - const std::string &ProcModelName = - SchedModels.getModelForProc(Processor).ModelName; - - // Emit as { "cpu", procinit }, - OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " },\n"; - } - // End processor->sched model table - OS << "};\n"; -} - -// // EmitSchedModel - Emits all scheduling model tables, folding common patterns. // void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { @@ -1423,12 +1419,10 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { } EmitSchedClassTables(SchedTables, OS); + OS << "\n#undef DBGFIELD\n"; + // Emit the processor machine model EmitProcessorModels(OS); - // Emit the processor lookup data - EmitProcessorLookup(OS); - - OS << "\n#undef DBGFIELD"; } static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) { @@ -1740,13 +1734,12 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { << "GenMCSubtargetInfo : public MCSubtargetInfo {\n"; OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT, \n" << " StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF,\n" - << " ArrayRef<SubtargetFeatureKV> PD,\n" - << " const SubtargetInfoKV *ProcSched,\n" + << " ArrayRef<SubtargetSubTypeKV> PD,\n" << " const MCWriteProcResEntry *WPR,\n" << " const MCWriteLatencyEntry *WL,\n" << " const MCReadAdvanceEntry *RA, const InstrStage *IS,\n" << " const unsigned *OC, const unsigned *FP) :\n" - << " MCSubtargetInfo(TT, CPU, FS, PF, PD, ProcSched,\n" + << " MCSubtargetInfo(TT, CPU, FS, PF, PD,\n" << " WPR, WL, RA, IS, OC, FP) { }\n\n" << " unsigned resolveVariantSchedClass(unsigned SchedClass,\n" << " const MCInst *MI, unsigned CPUID) const override {\n" @@ -1790,8 +1783,10 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; OS << "#undef GET_SUBTARGETINFO_ENUM\n\n"; + DenseMap<Record *, unsigned> FeatureMap; + OS << "namespace llvm {\n"; - Enumeration(OS); + Enumeration(OS, FeatureMap); OS << "} // end namespace llvm\n\n"; OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; @@ -1802,12 +1797,12 @@ void SubtargetEmitter::run(raw_ostream &OS) { #if 0 OS << "namespace {\n"; #endif - unsigned NumFeatures = FeatureKeyValues(OS); - OS << "\n"; - unsigned NumProcs = CPUKeyValues(OS); + unsigned NumFeatures = FeatureKeyValues(OS, FeatureMap); OS << "\n"; EmitSchedModel(OS); OS << "\n"; + unsigned NumProcs = CPUKeyValues(OS, FeatureMap); + OS << "\n"; #if 0 OS << "} // end anonymous namespace\n\n"; #endif @@ -1828,8 +1823,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { else OS << "None, "; OS << '\n'; OS.indent(22); - OS << Target << "ProcSchedKV, " - << Target << "WriteProcResTable, " + OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; OS << '\n'; OS.indent(22); @@ -1895,8 +1889,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n"; OS << "namespace llvm {\n"; OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; - OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; - OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n"; + OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n"; OS << "extern const llvm::MCWriteProcResEntry " << Target << "WriteProcResTable[];\n"; OS << "extern const llvm::MCWriteLatencyEntry " @@ -1922,8 +1915,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { else OS << "None, "; OS << '\n'; OS.indent(24); - OS << Target << "ProcSchedKV, " - << Target << "WriteProcResTable, " + OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; OS << '\n'; OS.indent(24); diff --git a/utils/TableGen/SubtargetFeatureInfo.cpp b/utils/TableGen/SubtargetFeatureInfo.cpp index f9b8853cc117..edf0b4a01c6d 100644 --- a/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/utils/TableGen/SubtargetFeatureInfo.cpp @@ -1,9 +1,8 @@ //===- SubtargetFeatureInfo.cpp - Helpers for subtarget features ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -45,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 " @@ -121,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; @@ -157,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 71e6748c863f..d72f8b93461f 100644 --- a/utils/TableGen/SubtargetFeatureInfo.h +++ b/utils/TableGen/SubtargetFeatureInfo.h @@ -1,9 +1,8 @@ -//===- SubtargetFeatureInfo.h - Helpers for subtarget features ------------===// +//===- SubtargetFeatureInfo.h - Helpers for subtarget features --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -56,13 +55,6 @@ struct SubtargetFeatureInfo { /// 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 /// more than 64 feature bits. static void diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index d5b6a3c12647..c485ed2feb7a 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -1,9 +1,8 @@ //===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -56,6 +55,12 @@ enum ActionType { GenExegesis, }; +namespace llvm { +/// Storage for TimeRegionsOpt as a global so that backends aren't required to +/// include CommandLine.h +bool TimeRegions = false; +} // end namespace llvm + namespace { cl::opt<ActionType> Action(cl::desc("Action to perform:"), @@ -127,6 +132,11 @@ namespace { Class("class", cl::desc("Print Enum list for this class"), cl::value_desc("class name"), cl::cat(PrintEnumsCat)); +cl::opt<bool, true> + TimeRegionsOpt("time-regions", + cl::desc("Time regions of tablegens execution"), + cl::location(TimeRegions)); + bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { switch (Action) { case PrintRecords: diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index f4f2909f8e88..135ec65c0f95 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -1,9 +1,8 @@ //===- TableGenBackends.h - Declarations for LLVM TableGen Backends -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/Types.cpp b/utils/TableGen/Types.cpp index 04d9e40f6743..a6682da90e6b 100644 --- a/utils/TableGen/Types.cpp +++ b/utils/TableGen/Types.cpp @@ -1,9 +1,8 @@ //===- Types.cpp - Helper for the selection of C++ data types. ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/Types.h b/utils/TableGen/Types.h index d511b7eae6e8..17c7742ccaac 100644 --- a/utils/TableGen/Types.h +++ b/utils/TableGen/Types.h @@ -1,9 +1,8 @@ //===- Types.h - Helper for the selection of C++ types. ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp b/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp index 788f142e125f..365cba5a60ca 100644 --- a/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp +++ b/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp @@ -1,9 +1,8 @@ //===- WebAssemblyDisassemblerEmitter.cpp - Disassembler tables -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -51,12 +50,33 @@ void emitWebAssemblyDisassemblerTables( auto IsStackBased = StackString && reinterpret_cast<const StringInit *>(StackString)->getValue() == "true"; - if (IsStackBased && !CGIP.second) { - // this picks the first of many typed variants, which is - // currently the except_ref one, though this shouldn't matter for - // disassembly purposes. - CGIP = std::make_pair(I, &CGI); + if (!IsStackBased) + continue; + if (CGIP.second) { + // We already have an instruction for this slot, so decide which one + // should be the canonical one. This determines which variant gets + // printed in a disassembly. We want e.g. "call" not "i32.call", and + // "end" when we don't know if its "end_loop" or "end_block" etc. + auto IsCanonicalExisting = CGIP.second->TheDef->getValue("IsCanonical") + ->getValue() + ->getAsString() == "1"; + // We already have one marked explicitly as canonical, so keep it. + if (IsCanonicalExisting) + continue; + auto IsCanonicalNew = + Def.getValue("IsCanonical")->getValue()->getAsString() == "1"; + // If the new one is explicitly marked as canonical, take it. + if (!IsCanonicalNew) { + // Neither the existing or new instruction is canonical. + // Pick the one with the shortest name as heuristic. + // Though ideally IsCanonical is always defined for at least one + // variant so this never has to apply. + if (CGIP.second->AsmString.size() <= CGI.AsmString.size()) + continue; + } } + // Set this instruction as the one to use. + CGIP = std::make_pair(I, &CGI); } OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n"; OS << "\n"; diff --git a/utils/TableGen/WebAssemblyDisassemblerEmitter.h b/utils/TableGen/WebAssemblyDisassemblerEmitter.h index 91f820f120a2..60d3d9433eca 100644 --- a/utils/TableGen/WebAssemblyDisassemblerEmitter.h +++ b/utils/TableGen/WebAssemblyDisassemblerEmitter.h @@ -1,9 +1,8 @@ //===- WebAssemblyDisassemblerEmitter.h - Disassembler tables ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 220765f72410..093f220fda5e 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -1,9 +1,8 @@ //===- X86DisassemblerShared.h - Emitter shared header ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 2b5cc1279605..8036aecc4f4b 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -1,9 +1,8 @@ //===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -889,67 +888,44 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, } void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { - const unsigned int tableSize = 16384; o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR - "[" << tableSize << "] = {\n"; + "[" << ATTR_max << "] = {\n"; i++; - for (unsigned index = 0; index < tableSize; ++index) { + for (unsigned index = 0; index < ATTR_max; ++index) { o.indent(i * 2); - if (index & ATTR_EVEX) { - o << "IC_EVEX"; - if (index & ATTR_EVEXL2) + if ((index & ATTR_EVEX) || (index & ATTR_VEX) || (index & ATTR_VEXL)) { + if (index & ATTR_EVEX) + o << "IC_EVEX"; + else + o << "IC_VEX"; + + if ((index & ATTR_EVEX) && (index & ATTR_EVEXL2)) o << "_L2"; - else if (index & ATTR_EVEXL) + else if (index & ATTR_VEXL) o << "_L"; + if (index & ATTR_REXW) o << "_W"; + if (index & ATTR_OPSIZE) o << "_OPSIZE"; else if (index & ATTR_XD) o << "_XD"; else if (index & ATTR_XS) o << "_XS"; - if (index & ATTR_EVEXKZ) - o << "_KZ"; - else if (index & ATTR_EVEXK) - o << "_K"; - if (index & ATTR_EVEXB) - o << "_B"; + + if ((index & ATTR_EVEX)) { + if (index & ATTR_EVEXKZ) + o << "_KZ"; + else if (index & ATTR_EVEXK) + o << "_K"; + + if (index & ATTR_EVEXB) + o << "_B"; + } } - else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) - o << "IC_VEX_L_W_OPSIZE"; - else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD)) - o << "IC_VEX_L_W_XD"; - else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS)) - o << "IC_VEX_L_W_XS"; - else if ((index & ATTR_VEXL) && (index & ATTR_REXW)) - o << "IC_VEX_L_W"; - else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) - o << "IC_VEX_L_OPSIZE"; - else if ((index & ATTR_VEXL) && (index & ATTR_XD)) - o << "IC_VEX_L_XD"; - else if ((index & ATTR_VEXL) && (index & ATTR_XS)) - o << "IC_VEX_L_XS"; - else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) - o << "IC_VEX_W_OPSIZE"; - else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) - o << "IC_VEX_W_XD"; - else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) - o << "IC_VEX_W_XS"; - else if (index & ATTR_VEXL) - o << "IC_VEX_L"; - else if ((index & ATTR_VEX) && (index & ATTR_REXW)) - o << "IC_VEX_W"; - else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) - o << "IC_VEX_OPSIZE"; - else if ((index & ATTR_VEX) && (index & ATTR_XD)) - o << "IC_VEX_XD"; - else if ((index & ATTR_VEX) && (index & ATTR_XS)) - o << "IC_VEX_XS"; - else if (index & ATTR_VEX) - o << "IC_VEX"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) o << "IC_64BIT_REXW_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) @@ -1004,12 +980,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { else o << "IC"; - if (index < tableSize - 1) - o << ","; - else - o << " "; - - o << " /* " << index << " */"; + o << ", /* " << index << " */"; o << "\n"; } diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index b0ea9c2e8625..63af68b6fbfa 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -1,9 +1,8 @@ //===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp b/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp index d5dc10ecad25..3df14f40e4a9 100644 --- a/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp +++ b/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp @@ -1,9 +1,8 @@ //===- utils/TableGen/X86EVEX2VEXTablesEmitter.cpp - X86 backend-*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -69,23 +68,6 @@ void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table, } // Return true if the 2 BitsInits are equal -static inline bool equalBitsInits(const BitsInit *B1, const BitsInit *B2) { - if (B1->getNumBits() != B2->getNumBits()) - PrintFatalError("Comparing two BitsInits with different sizes!"); - - for (unsigned i = 0, e = B1->getNumBits(); i != e; ++i) { - if (BitInit *Bit1 = dyn_cast<BitInit>(B1->getBit(i))) { - if (BitInit *Bit2 = dyn_cast<BitInit>(B2->getBit(i))) { - if (Bit1->getValue() != Bit2->getValue()) - return false; - } else - PrintFatalError("Invalid BitsInit bit"); - } else - PrintFatalError("Invalid BitsInit bit"); - } - return true; -} - // Calculates the integer value residing BitsInit object static inline uint64_t getValueFromBitsInit(const BitsInit *B) { uint64_t Value = 0; @@ -109,26 +91,25 @@ public: bool operator()(const CodeGenInstruction *VEXInst) { Record *RecE = EVEXInst->TheDef; Record *RecV = VEXInst->TheDef; - uint64_t EVEX_W = - getValueFromBitsInit(RecE->getValueAsBitsInit("VEX_WPrefix")); - uint64_t VEX_W = - getValueFromBitsInit(RecV->getValueAsBitsInit("VEX_WPrefix")); + bool EVEX_W = RecE->getValueAsBit("HasVEX_W"); + bool VEX_W = RecV->getValueAsBit("HasVEX_W"); + bool VEX_WIG = RecV->getValueAsBit("IgnoresVEX_W"); + bool EVEX_WIG = RecE->getValueAsBit("IgnoresVEX_W"); + bool EVEX_W1_VEX_W0 = RecE->getValueAsBit("EVEX_W1_VEX_W0"); if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" || // VEX/EVEX fields RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") || RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") || RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") || - !equalBitsInits(RecV->getValueAsBitsInit("EVEX_LL"), - RecE->getValueAsBitsInit("EVEX_LL")) || + RecV->getValueAsBit("hasEVEX_L2") != RecE->getValueAsBit("hasEVEX_L2") || + RecV->getValueAsBit("hasVEX_L") != RecE->getValueAsBit("hasVEX_L") || // Match is allowed if either is VEX_WIG, or they match, or EVEX // is VEX_W1X and VEX is VEX_W0. - (!(EVEX_W == 2 || VEX_W == 2 || EVEX_W == VEX_W || - (EVEX_W == 3 && VEX_W == 0))) || + (!(VEX_WIG || (!EVEX_WIG && EVEX_W == VEX_W) || + (EVEX_W1_VEX_W0 && EVEX_W && !VEX_W))) || // Instruction's format - RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form") || - RecV->getValueAsBit("isAsmParserOnly") != - RecE->getValueAsBit("isAsmParserOnly")) + RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form")) return false; // This is needed for instructions with intrinsic version (_Int). @@ -150,8 +131,9 @@ public: } else if (isMemoryOperand(OpRec1) && isMemoryOperand(OpRec2)) { return false; } else if (isImmediateOperand(OpRec1) && isImmediateOperand(OpRec2)) { - if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type")) + if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type")) { return false; + } } else return false; } @@ -207,8 +189,7 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) { else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" && !Inst->TheDef->getValueAsBit("hasEVEX_K") && !Inst->TheDef->getValueAsBit("hasEVEX_B") && - getValueFromBitsInit(Inst->TheDef-> - getValueAsBitsInit("EVEX_LL")) != 2 && + !Inst->TheDef->getValueAsBit("hasEVEX_L2") && !Inst->TheDef->getValueAsBit("notEVEX2VEXConvertible")) EVEXInsts.push_back(Inst); } @@ -236,17 +217,10 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) { continue; // In case a match is found add new entry to the appropriate table - switch (getValueFromBitsInit( - EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) { - case 0: - EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0} - break; - case 1: + if (EVEXInst->TheDef->getValueAsBit("hasVEX_L")) EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1} - break; - default: - llvm_unreachable("Instruction's size not fit for the mapping!"); - } + else + EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0} } // Print both tables diff --git a/utils/TableGen/X86FoldTablesEmitter.cpp b/utils/TableGen/X86FoldTablesEmitter.cpp index 1ea668643575..2c15e35f234d 100644 --- a/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/utils/TableGen/X86FoldTablesEmitter.cpp @@ -1,9 +1,8 @@ //===- utils/TableGen/X86FoldTablesEmitter.cpp - X86 backend-*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #include "CodeGenTarget.h" #include "X86RecognizableInstr.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/TableGenBackend.h" @@ -62,9 +62,12 @@ const ManualMapEntry ManualMapSet[] = { { "ADD64ri32_DB", "ADD64mi32", NO_UNFOLD }, { "ADD64ri8_DB", "ADD64mi8", NO_UNFOLD }, { "ADD64rr_DB", "ADD64mr", NO_UNFOLD }, + { "ADD8ri_DB", "ADD8mi", NO_UNFOLD }, + { "ADD8rr_DB", "ADD8mr", NO_UNFOLD }, { "ADD16rr_DB", "ADD16rm", NO_UNFOLD }, { "ADD32rr_DB", "ADD32rm", NO_UNFOLD }, { "ADD64rr_DB", "ADD64rm", NO_UNFOLD }, + { "ADD8rr_DB", "ADD8rm", NO_UNFOLD }, { "PUSH16r", "PUSH16rmm", UNFOLD }, { "PUSH32r", "PUSH32rmm", UNFOLD }, { "PUSH64r", "PUSH64rmm", UNFOLD }, @@ -106,23 +109,23 @@ class X86FoldTablesEmitter { const CodeGenInstruction *MemInst) : RegInst(RegInst), MemInst(MemInst) {} - friend raw_ostream &operator<<(raw_ostream &OS, - const X86FoldTableEntry &E) { - OS << "{ X86::" << E.RegInst->TheDef->getName() - << ", X86::" << E.MemInst->TheDef->getName() << ", "; + void print(formatted_raw_ostream &OS) const { + OS.indent(2); + OS << "{ X86::" << RegInst->TheDef->getName() << ","; + OS.PadToColumn(40); + OS << "X86::" << MemInst->TheDef->getName() << ","; + OS.PadToColumn(75); - if (E.IsLoad) + if (IsLoad) OS << "TB_FOLDED_LOAD | "; - if (E.IsStore) + if (IsStore) OS << "TB_FOLDED_STORE | "; - if (E.CannotUnfold) + if (CannotUnfold) OS << "TB_NO_REVERSE | "; - if (E.IsAligned) - OS << "TB_ALIGN_" << E.Alignment << " | "; + if (IsAligned) + OS << "TB_ALIGN_" << Alignment << " | "; OS << "0 },\n"; - - return OS; } }; @@ -142,7 +145,7 @@ public: X86FoldTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {} // run - Generate the 6 X86 memory fold tables. - void run(raw_ostream &OS); + void run(formatted_raw_ostream &OS); private: // Decides to which table to add the entry with the given instructions. @@ -160,21 +163,21 @@ private: // Print the given table as a static const C++ array of type // X86MemoryFoldTableEntry. void printTable(const FoldTable &Table, StringRef TableName, - raw_ostream &OS) { + formatted_raw_ostream &OS) { OS << "static const X86MemoryFoldTableEntry MemoryFold" << TableName << "[] = {\n"; for (const X86FoldTableEntry &E : Table) - OS << E; + E.print(OS); - OS << "};\n"; + OS << "};\n\n"; } }; // Return true if one of the instruction's operands is a RST register class static bool hasRSTRegClass(const CodeGenInstruction *Inst) { return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) { - return OpIn.Rec->getName() == "RST"; + return OpIn.Rec->getName() == "RST" || OpIn.Rec->getName() == "RSTi"; }); } @@ -345,10 +348,18 @@ public: MemRec->getValueAsBit("hasLockPrefix") || RegRec->getValueAsBit("hasNoTrackPrefix") != MemRec->getValueAsBit("hasNoTrackPrefix") || - !equalBitsInits(RegRec->getValueAsBitsInit("EVEX_LL"), - MemRec->getValueAsBitsInit("EVEX_LL")) || - !equalBitsInits(RegRec->getValueAsBitsInit("VEX_WPrefix"), - MemRec->getValueAsBitsInit("VEX_WPrefix")) || + RegRec->getValueAsBit("hasVEX_L") != + MemRec->getValueAsBit("hasVEX_L") || + RegRec->getValueAsBit("hasEVEX_L2") != + MemRec->getValueAsBit("hasEVEX_L2") || + RegRec->getValueAsBit("ignoresVEX_L") != + MemRec->getValueAsBit("ignoresVEX_L") || + RegRec->getValueAsBit("HasVEX_W") != + MemRec->getValueAsBit("HasVEX_W") || + RegRec->getValueAsBit("IgnoresVEX_W") != + MemRec->getValueAsBit("IgnoresVEX_W") || + RegRec->getValueAsBit("EVEX_W1_VEX_W0") != + MemRec->getValueAsBit("EVEX_W1_VEX_W0") || // Instruction's format - The register form's "Form" field should be // the opposite of the memory form's "Form" field. !areOppositeForms(RegRec->getValueAsBitsInit("FormBits"), @@ -421,6 +432,7 @@ private: (MemFormNum == X86Local::MRM6m && RegFormNum == X86Local::MRM6r) || (MemFormNum == X86Local::MRM7m && RegFormNum == X86Local::MRM7r) || (MemFormNum == X86Local::MRMXm && RegFormNum == X86Local::MRMXr) || + (MemFormNum == X86Local::MRMXmCC && RegFormNum == X86Local::MRMXrCC) || (MemFormNum == X86Local::MRMDestMem && RegFormNum == X86Local::MRMDestReg) || (MemFormNum == X86Local::MRMSrcMem && @@ -428,7 +440,9 @@ private: (MemFormNum == X86Local::MRMSrcMem4VOp3 && RegFormNum == X86Local::MRMSrcReg4VOp3) || (MemFormNum == X86Local::MRMSrcMemOp4 && - RegFormNum == X86Local::MRMSrcRegOp4)) + RegFormNum == X86Local::MRMSrcRegOp4) || + (MemFormNum == X86Local::MRMSrcMemCC && + RegFormNum == X86Local::MRMSrcRegCC)) return true; return false; @@ -558,7 +572,7 @@ void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInstr, return; } -void X86FoldTablesEmitter::run(raw_ostream &OS) { +void X86FoldTablesEmitter::run(formatted_raw_ostream &OS) { emitSourceFileHeader("X86 fold tables", OS); // Holds all memory instructions @@ -639,7 +653,7 @@ void X86FoldTablesEmitter::run(raw_ostream &OS) { &(Target.getInstruction(MemInstIter)), Entry.Strategy); } - // Print all tables to raw_ostream OS. + // Print all tables. printTable(Table2Addr, "Table2Addr", OS); printTable(Table0, "Table0", OS); printTable(Table1, "Table1", OS); @@ -650,7 +664,8 @@ void X86FoldTablesEmitter::run(raw_ostream &OS) { namespace llvm { -void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS) { +void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &o) { + formatted_raw_ostream OS(o); X86FoldTablesEmitter(RK).run(OS); } } // namespace llvm diff --git a/utils/TableGen/X86ModRMFilters.cpp b/utils/TableGen/X86ModRMFilters.cpp index 1641613aa32d..98e6fb6104d7 100644 --- a/utils/TableGen/X86ModRMFilters.cpp +++ b/utils/TableGen/X86ModRMFilters.cpp @@ -1,9 +1,8 @@ //===- X86ModRMFilters.cpp - Disassembler ModR/M filterss -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index b0248e878d07..c77b4c21aec4 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -1,9 +1,8 @@ //===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 2f9b428b8cfe..ab8a8855c478 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -1,9 +1,8 @@ //===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -84,7 +83,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, AdSize = byteFromRec(Rec, "AdSizeBits"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); HasVEX_4V = Rec->getValueAsBit("hasVEX_4V"); - VEX_WPrefix = byteFromRec(Rec,"VEX_WPrefix"); + HasVEX_W = Rec->getValueAsBit("HasVEX_W"); + IgnoresVEX_W = Rec->getValueAsBit("IgnoresVEX_W"); IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2"); HasEVEX_K = Rec->getValueAsBit("hasEVEX_K"); @@ -110,7 +110,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates"); for (unsigned i = 0, e = Predicates.size(); i != e; ++i) { if (Predicates[i]->getName().find("Not64Bit") != Name.npos || - Predicates[i]->getName().find("In32Bit") != Name.npos) { + Predicates[i]->getName().find("In32Bit") != Name.npos) { Is32Bit = true; break; } @@ -164,8 +164,7 @@ InstructionContext RecognizableInstr::insnContext() const { llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled"); } // VEX_L & VEX_W - if (!EncodeRC && HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X)) { + if (!EncodeRC && HasVEX_LPrefix && HasVEX_W) { if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE); else if (OpPrefix == X86Local::XS) @@ -192,9 +191,7 @@ InstructionContext RecognizableInstr::insnContext() const { errs() << "Instruction does not use a prefix: " << Name << "\n"; llvm_unreachable("Invalid prefix"); } - } else if (!EncodeRC && HasEVEX_L2Prefix && - (VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X)) { + } else if (!EncodeRC && HasEVEX_L2Prefix && HasVEX_W) { // EVEX_L2 & VEX_W if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE); @@ -223,8 +220,7 @@ InstructionContext RecognizableInstr::insnContext() const { llvm_unreachable("Invalid prefix"); } } - else if (VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X) { + else if (HasVEX_W) { // VEX_W if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_W_OPSIZE); @@ -254,8 +250,7 @@ InstructionContext RecognizableInstr::insnContext() const { } /// eof EVEX } else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) { - if (HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X)) { + if (HasVEX_LPrefix && HasVEX_W) { if (OpPrefix == X86Local::PD) insnContext = IC_VEX_L_W_OPSIZE; else if (OpPrefix == X86Local::XS) @@ -270,8 +265,7 @@ InstructionContext RecognizableInstr::insnContext() const { } } else if (OpPrefix == X86Local::PD && HasVEX_LPrefix) insnContext = IC_VEX_L_OPSIZE; - else if (OpPrefix == X86Local::PD && (VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X)) + else if (OpPrefix == X86Local::PD && HasVEX_W) insnContext = IC_VEX_W_OPSIZE; else if (OpPrefix == X86Local::PD) insnContext = IC_VEX_OPSIZE; @@ -279,14 +273,11 @@ InstructionContext RecognizableInstr::insnContext() const { insnContext = IC_VEX_L_XS; else if (HasVEX_LPrefix && OpPrefix == X86Local::XD) insnContext = IC_VEX_L_XD; - else if ((VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XS) + else if (HasVEX_W && OpPrefix == X86Local::XS) insnContext = IC_VEX_W_XS; - else if ((VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XD) + else if (HasVEX_W && OpPrefix == X86Local::XD) insnContext = IC_VEX_W_XD; - else if ((VEX_WPrefix == X86Local::VEX_W1 || - VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::PS) + else if (HasVEX_W && OpPrefix == X86Local::PS) insnContext = IC_VEX_W; else if (HasVEX_LPrefix && OpPrefix == X86Local::PS) insnContext = IC_VEX_L; @@ -496,6 +487,13 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPERAND(opcodeModifier) HANDLE_OPTIONAL(relocation) break; + case X86Local::AddCCFrm: + // Operand 1 (optional) is an address or immediate. + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for AddCCFrm"); + HANDLE_OPERAND(relocation) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. // - In AVX512 there may be a mask operand here - @@ -581,6 +579,13 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPERAND(rmRegister) HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMSrcRegCC: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMSrcRegCC"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(rmRegister) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a memory operand (possibly SIB-extended) @@ -621,6 +626,19 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPERAND(memory) HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMSrcMemCC: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMSrcMemCC"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(memory) + HANDLE_OPERAND(opcodeModifier) + break; + case X86Local::MRMXrCC: + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for MRMXrCC"); + HANDLE_OPERAND(rmRegister) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMXr: case X86Local::MRM0r: case X86Local::MRM1r: @@ -646,6 +664,12 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(relocation) HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMXmCC: + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for MRMXm"); + HANDLE_OPERAND(memory) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMXm: case X86Local::MRM0m: case X86Local::MRM1m: @@ -724,12 +748,15 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::RawFrmDstSrc: case X86Local::RawFrmImm8: case X86Local::RawFrmImm16: + case X86Local::AddCCFrm: filter = llvm::make_unique<DumbFilter>(); break; case X86Local::MRMDestReg: case X86Local::MRMSrcReg: case X86Local::MRMSrcReg4VOp3: case X86Local::MRMSrcRegOp4: + case X86Local::MRMSrcRegCC: + case X86Local::MRMXrCC: case X86Local::MRMXr: filter = llvm::make_unique<ModFilter>(true); break; @@ -737,6 +764,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::MRMSrcMem: case X86Local::MRMSrcMem4VOp3: case X86Local::MRMSrcMemOp4: + case X86Local::MRMSrcMemCC: + case X86Local::MRMXmCC: case X86Local::MRMXm: filter = llvm::make_unique<ModFilter>(false); break; @@ -769,23 +798,24 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { assert(opcodeType && "Opcode type not set"); assert(filter && "Filter not set"); - if (Form == X86Local::AddRegFrm) { - assert(((opcodeToSet & 7) == 0) && - "ADDREG_FRM opcode not aligned"); + if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC || + Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC || + Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm) { + unsigned Count = Form == X86Local::AddRegFrm ? 8 : 16; + assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned"); uint8_t currentOpcode; - for (currentOpcode = opcodeToSet; - currentOpcode < opcodeToSet + 8; + for (currentOpcode = opcodeToSet; currentOpcode < opcodeToSet + Count; ++currentOpcode) tables.setTableFields(*opcodeType, insnContext(), currentOpcode, *filter, UID, Is32Bit, OpPrefix == 0, IgnoresVEX_L || EncodeRC, - VEX_WPrefix == X86Local::VEX_WIG, AddressSize); + IgnoresVEX_W, AddressSize); } else { tables.setTableFields(*opcodeType, insnContext(), opcodeToSet, *filter, UID, Is32Bit, OpPrefix == 0, IgnoresVEX_L || EncodeRC, - VEX_WPrefix == X86Local::VEX_WIG, AddressSize); + IgnoresVEX_W, AddressSize); } #undef MAP @@ -825,7 +855,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i8mem", TYPE_M) TYPE("i8imm", TYPE_IMM) TYPE("u8imm", TYPE_UIMM8) + TYPE("i16u8imm", TYPE_UIMM8) TYPE("i32u8imm", TYPE_UIMM8) + TYPE("i64u8imm", TYPE_UIMM8) TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM) TYPE("VR128X", TYPE_XMM) @@ -842,16 +874,14 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("f32mem", TYPE_M) TYPE("ssmem", TYPE_M) TYPE("RST", TYPE_ST) + TYPE("RSTi", TYPE_ST) TYPE("i128mem", TYPE_M) TYPE("i256mem", TYPE_M) TYPE("i512mem", TYPE_M) TYPE("i64i32imm_pcrel", TYPE_REL) TYPE("i16imm_pcrel", TYPE_REL) TYPE("i32imm_pcrel", TYPE_REL) - TYPE("SSECC", TYPE_IMM3) - TYPE("XOPCC", TYPE_IMM3) - TYPE("AVXCC", TYPE_IMM5) - TYPE("AVX512ICC", TYPE_AVX512ICC) + TYPE("ccode", TYPE_IMM) TYPE("AVX512RC", TYPE_IMM) TYPE("brtarget32", TYPE_REL) TYPE("brtarget16", TYPE_REL) @@ -902,6 +932,11 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("VK32WM", TYPE_VK) TYPE("VK64", TYPE_VK) TYPE("VK64WM", TYPE_VK) + TYPE("VK1Pair", TYPE_VK_PAIR) + TYPE("VK2Pair", TYPE_VK_PAIR) + TYPE("VK4Pair", TYPE_VK_PAIR) + TYPE("VK8Pair", TYPE_VK_PAIR) + TYPE("VK16Pair", TYPE_VK_PAIR) TYPE("vx64mem", TYPE_MVSIBX) TYPE("vx128mem", TYPE_MVSIBX) TYPE("vx256mem", TYPE_MVSIBX) @@ -931,10 +966,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) - ENCODING("SSECC", ENCODING_IB) - ENCODING("XOPCC", ENCODING_IB) - ENCODING("AVXCC", ENCODING_IB) - ENCODING("AVX512ICC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IRC) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) @@ -943,7 +974,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) ENCODING("u8imm", ENCODING_IB) + ENCODING("i16u8imm", ENCODING_IB) ENCODING("i32u8imm", ENCODING_IB) + ENCODING("i64u8imm", ENCODING_IB) // This is not a typo. Instructions like BLENDVPD put // register IDs in 8-bit immediates nowadays. ENCODING("FR32", ENCODING_IB) @@ -964,6 +997,7 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, uint8_t OpSize) { ENCODING("RST", ENCODING_FP) + ENCODING("RSTi", ENCODING_FP) ENCODING("GR16", ENCODING_RM) ENCODING("GR32", ENCODING_RM) ENCODING("GR32orGR64", ENCODING_RM) @@ -987,6 +1021,11 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VK16", ENCODING_RM) ENCODING("VK32", ENCODING_RM) ENCODING("VK64", ENCODING_RM) + ENCODING("VK1PAIR", ENCODING_RM) + ENCODING("VK2PAIR", ENCODING_RM) + ENCODING("VK4PAIR", ENCODING_RM) + ENCODING("VK8PAIR", ENCODING_RM) + ENCODING("VK16PAIR", ENCODING_RM) ENCODING("BNDR", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); @@ -1021,6 +1060,11 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("VK16", ENCODING_REG) ENCODING("VK32", ENCODING_REG) ENCODING("VK64", ENCODING_REG) + ENCODING("VK1Pair", ENCODING_REG) + ENCODING("VK2Pair", ENCODING_REG) + ENCODING("VK4Pair", ENCODING_REG) + ENCODING("VK8Pair", ENCODING_REG) + ENCODING("VK16Pair", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) ENCODING("VK2WM", ENCODING_REG) ENCODING("VK4WM", ENCODING_REG) @@ -1055,6 +1099,11 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("VK16", ENCODING_VVVV) ENCODING("VK32", ENCODING_VVVV) ENCODING("VK64", ENCODING_VVVV) + ENCODING("VK1PAIR", ENCODING_VVVV) + ENCODING("VK2PAIR", ENCODING_VVVV) + ENCODING("VK4PAIR", ENCODING_VVVV) + ENCODING("VK8PAIR", ENCODING_VVVV) + ENCODING("VK16PAIR", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } @@ -1128,7 +1177,9 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) ENCODING("u8imm", ENCODING_IB) + ENCODING("i16u8imm", ENCODING_IB) ENCODING("i32u8imm", ENCODING_IB) + ENCODING("i64u8imm", ENCODING_IB) ENCODING("i64i32imm_pcrel", ENCODING_ID) ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) @@ -1166,6 +1217,7 @@ RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s, ENCODING("GR64", ENCODING_RO) ENCODING("GR16", ENCODING_Rv) ENCODING("GR8", ENCODING_RB) + ENCODING("ccode", ENCODING_CC) errs() << "Unhandled opcode modifier encoding " << s << "\n"; llvm_unreachable("Unhandled opcode modifier encoding"); } diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index c4d34ee6c80c..b15bef4e1931 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -1,9 +1,8 @@ //===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -102,18 +101,21 @@ namespace X86Local { RawFrmDstSrc = 6, RawFrmImm8 = 7, RawFrmImm16 = 8, + AddCCFrm = 9, MRMDestMem = 32, MRMSrcMem = 33, MRMSrcMem4VOp3 = 34, MRMSrcMemOp4 = 35, - MRMXm = 39, + MRMSrcMemCC = 36, + MRMXmCC = 38, MRMXm = 39, MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43, MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47, MRMDestReg = 48, MRMSrcReg = 49, MRMSrcReg4VOp3 = 50, MRMSrcRegOp4 = 51, - MRMXr = 55, + MRMSrcRegCC = 52, + MRMXrCC = 54, MRMXr = 55, MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59, MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63, #define MAP(from, to) MRM_##from = to, @@ -140,10 +142,6 @@ namespace X86Local { enum { AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 }; - - enum { - VEX_W0 = 0, VEX_W1 = 1, VEX_WIG = 2, VEX_W1X = 3 - }; } namespace X86Disassembler { @@ -177,8 +175,10 @@ private: bool HasREX_WPrefix; /// The hasVEX_4V field from the record bool HasVEX_4V; - /// The VEX_WPrefix field from the record - uint8_t VEX_WPrefix; + /// The HasVEX_WPrefix field from the record + bool HasVEX_W; + /// The IgnoresVEX_W field from the record + bool IgnoresVEX_W; /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set bool HasVEX_LPrefix; /// The ignoreVEX_L field from the record |