diff options
Diffstat (limited to 'contrib/llvm/utils')
38 files changed, 1599 insertions, 807 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 76228e0..1272d2b 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -97,6 +97,9 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "Types.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -126,7 +129,6 @@ MatchPrefix("match-prefix", cl::init(""), namespace { class AsmMatcherInfo; -struct SubtargetFeatureInfo; // Register sets are used as keys in some second-order sets TableGen creates // when generating its data structures. This means that the order of two @@ -353,6 +355,7 @@ public: std::string TokenizingCharacters; std::string SeparatorCharacters; std::string BreakCharacters; + std::string Name; int AsmVariantNo; }; @@ -556,20 +559,17 @@ struct MatchableInfo { /// findAsmOperand - Find the AsmOperand with the specified name and /// suboperand index. int findAsmOperand(StringRef N, int SubOpIdx) const { - auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(), - [&](const AsmOperand &Op) { - return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx; - }); + auto I = find_if(AsmOperands, [&](const AsmOperand &Op) { + return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx; + }); return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1; } /// findAsmOperandNamed - Find the first AsmOperand with the specified name. /// This does not check the suboperand index. int findAsmOperandNamed(StringRef N) const { - auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(), - [&](const AsmOperand &Op) { - return Op.SrcOpName == N; - }); + auto I = find_if(AsmOperands, + [&](const AsmOperand &Op) { return Op.SrcOpName == N; }); return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1; } @@ -653,28 +653,6 @@ private: void addAsmOperand(StringRef Token, bool IsIsolatedToken = false); }; -/// SubtargetFeatureInfo - Helper class for storing information on a subtarget -/// feature which participates in instruction matching. -struct SubtargetFeatureInfo { - /// \brief The predicate record for this feature. - Record *TheDef; - - /// \brief An unique index assigned to represent this feature. - uint64_t Index; - - SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} - - /// \brief The name of the enumerated constant identifying this feature. - std::string getEnumName() const { - return "Feature_" + TheDef->getName(); - } - - void dump() const { - errs() << getEnumName() << " " << Index << "\n"; - TheDef->dump(); - } -}; - struct OperandMatchEntry { unsigned OperandMask; const MatchableInfo* MI; @@ -754,7 +732,7 @@ public: CodeGenTarget &Target, RecordKeeper &Records); - /// buildInfo - Construct the various tables used during matching. + /// Construct the various tables used during matching. void buildInfo(); /// buildOperandMatchInfo - Build the necessary information to handle user @@ -774,9 +752,9 @@ public: } bool hasOptionalOperands() const { - return std::find_if(Classes.begin(), Classes.end(), - [](const ClassInfo& Class){ return Class.IsOptional; }) - != Classes.end(); + return find_if(Classes, [](const ClassInfo &Class) { + return Class.IsOptional; + }) != Classes.end(); } }; @@ -1311,10 +1289,10 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) { if (CI->ValueName.empty()) { CI->ClassName = Rec->getName(); - CI->Name = "MCK_" + Rec->getName(); + CI->Name = "MCK_" + Rec->getName().str(); CI->ValueName = Rec->getName(); } else - CI->ValueName = CI->ValueName + "," + Rec->getName(); + CI->ValueName = CI->ValueName + "," + Rec->getName().str(); } } @@ -1437,21 +1415,15 @@ void AsmMatcherInfo::buildOperandMatchInfo() { void AsmMatcherInfo::buildInfo() { // Build information about all of the AssemblerPredicates. - std::vector<Record*> AllPredicates = - Records.getAllDerivedDefinitions("Predicate"); - for (Record *Pred : AllPredicates) { - // Ignore predicates that are not intended for the assembler. - if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) - continue; - - if (Pred->getName().empty()) - PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - - SubtargetFeatures.insert(std::make_pair( - Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); - DEBUG(SubtargetFeatures.find(Pred)->second.dump()); - assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); - } + const std::vector<std::pair<Record *, SubtargetFeatureInfo>> + &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records); + SubtargetFeatures.insert(SubtargetFeaturePairs.begin(), + SubtargetFeaturePairs.end()); +#ifndef NDEBUG + for (const auto &Pair : SubtargetFeatures) + DEBUG(Pair.second.dump()); +#endif // NDEBUG + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); @@ -1471,6 +1443,7 @@ void AsmMatcherInfo::buildInfo() { AsmVariant->getValueAsString("SeparatorCharacters"); Variant.BreakCharacters = AsmVariant->getValueAsString("BreakCharacters"); + Variant.Name = AsmVariant->getValueAsString("Name"); Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant"); for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) { @@ -1484,6 +1457,11 @@ void AsmMatcherInfo::buildInfo() { if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; + // Ignore instructions for different instructions + const std::string V = CGI->TheDef->getValueAsString("AsmVariantName"); + if (!V.empty() && V != Variant.Name) + continue; + auto II = llvm::make_unique<MatchableInfo>(*CGI); II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); @@ -1512,6 +1490,10 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; + const std::string V = Alias->TheDef->getValueAsString("AsmVariantName"); + if (!V.empty() && V != Variant.Name) + continue; + auto II = llvm::make_unique<MatchableInfo>(std::move(Alias)); II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); @@ -1613,15 +1595,15 @@ void AsmMatcherInfo::buildInfo() { // Reorder classes so that classes precede super classes. Classes.sort(); -#ifndef NDEBUG - // Verify that the table is now sorted +#ifdef EXPENSIVE_CHECKS + // Verify that the table is sorted and operator < works transitively. for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) { for (auto J = I; J != E; ++J) { assert(!(*J < *I)); assert(I == J || !J->isSubsetOf(*I)); } } -#endif // NDEBUG +#endif } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1814,13 +1796,13 @@ void MatchableInfo::buildAliasResultOperands() { } } -static unsigned getConverterOperandID(const std::string &Name, - SmallSetVector<std::string, 16> &Table, - bool &IsNew) { - IsNew = Table.insert(Name); +static unsigned +getConverterOperandID(const std::string &Name, + SmallSetVector<CachedHashString, 16> &Table, + bool &IsNew) { + IsNew = Table.insert(CachedHashString(Name)); - unsigned ID = IsNew ? Table.size() - 1 : - std::find(Table.begin(), Table.end(), Name) - Table.begin(); + unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin(); assert(ID < Table.size()); @@ -1831,13 +1813,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector<std::unique_ptr<MatchableInfo>> &Infos, bool HasMnemonicFirst, bool HasOptionalOperands, raw_ostream &OS) { - SmallSetVector<std::string, 16> OperandConversionKinds; - SmallSetVector<std::string, 16> InstructionConversionKinds; + SmallSetVector<CachedHashString, 16> OperandConversionKinds; + SmallSetVector<CachedHashString, 16> InstructionConversionKinds; std::vector<std::vector<uint8_t> > ConversionTable; size_t MaxRowLength = 2; // minimum is custom converter plus terminator. // TargetOperandClass - This is the target's operand class, like X86Operand. - std::string TargetOperandClass = Target.getName() + "Operand"; + std::string TargetOperandClass = Target.getName().str() + "Operand"; // Write the convert function to a separate stream, so we can drop it after // the enum. We'll build up the conversion handlers for the individual @@ -1904,9 +1886,9 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Pre-populate the operand conversion kinds with the standard always // available entries. - OperandConversionKinds.insert("CVT_Done"); - OperandConversionKinds.insert("CVT_Reg"); - OperandConversionKinds.insert("CVT_Tied"); + OperandConversionKinds.insert(CachedHashString("CVT_Done")); + OperandConversionKinds.insert(CachedHashString("CVT_Reg")); + OperandConversionKinds.insert(CachedHashString("CVT_Tied")); enum { CVT_Done, CVT_Reg, CVT_Tied }; for (auto &II : Infos) { @@ -1918,13 +1900,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, II->ConversionFnKind = Signature; // Check if we have already generated this signature. - if (!InstructionConversionKinds.insert(Signature)) + if (!InstructionConversionKinds.insert(CachedHashString(Signature))) continue; // Remember this converter for the kind enum. unsigned KindID = OperandConversionKinds.size(); - OperandConversionKinds.insert("CVT_" + - getEnumNameForToken(AsmMatchConverter)); + OperandConversionKinds.insert( + CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter))); // Add the converter row for this instruction. ConversionTable.emplace_back(); @@ -2072,7 +2054,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, Reg = "0"; } else { Reg = getQualifiedName(OpInfo.Register); - Name = "reg" + OpInfo.Register->getName(); + Name = "reg" + OpInfo.Register->getName().str(); } Signature += "__" + Name; Name = "CVT_" + Name; @@ -2106,7 +2088,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Save the signature. If we already have it, don't add a new row // to the table. - if (!InstructionConversionKinds.insert(Signature)) + if (!InstructionConversionKinds.insert(CachedHashString(Signature))) continue; // Add the row to the table. @@ -2123,14 +2105,14 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Output the operand conversion kind enum. OS << "enum OperatorConversionKind {\n"; - for (const std::string &Converter : OperandConversionKinds) + for (const auto &Converter : OperandConversionKinds) OS << " " << Converter << ",\n"; OS << " CVT_NUM_CONVERTERS\n"; OS << "};\n\n"; // Output the instruction conversion kind enum. OS << "enum InstructionConversionKind {\n"; - for (const std::string &Signature : InstructionConversionKinds) + for (const auto &Signature : InstructionConversionKinds) OS << " " << Signature << ",\n"; OS << " CVT_NUM_SIGNATURES\n"; OS << "};\n\n"; @@ -2382,40 +2364,6 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser, OS << "}\n\n"; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFFFFFFULL) - return "uint64_t"; - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - -static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) { - uint64_t MaxIndex = Info.SubtargetFeatures.size(); - if (MaxIndex > 0) - MaxIndex--; - return getMinimalTypeForRange(1ULL << MaxIndex); -} - -/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, - raw_ostream &OS) { - OS << "// Flags for subtarget features that participate in " - << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) - << " {\n"; - for (const auto &SF : Info.SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; - } - OS << " Feature_None = 0\n"; - OS << "};\n\n"; -} - /// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types. static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { // Get the set of diagnostic types from all of the operand classes. @@ -2456,55 +2404,6 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "}\n\n"; } -/// emitComputeAvailableFeatures - Emit the function to compute the list of -/// available features given a subtarget. -static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, - raw_ostream &OS) { - std::string ClassName = - Info.AsmParser->getValueAsString("AsmParserClassName"); - - OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; - OS << " uint64_t Features = 0;\n"; - for (const auto &SF : Info.SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - - OS << " if ("; - std::string CondStorage = - SFI.TheDef->getValueAsString("AssemblerCondString"); - StringRef Conds = CondStorage; - std::pair<StringRef,StringRef> Comma = Conds.split(','); - bool First = true; - do { - if (!First) - OS << " && "; - - bool Neg = false; - StringRef Cond = Comma.first; - if (Cond[0] == '!') { - Neg = true; - Cond = Cond.substr(1); - } - - OS << "("; - if (Neg) - OS << "!"; - OS << "FB[" << Info.Target.getName() << "::" << Cond << "])"; - - if (Comma.second.empty()) - break; - - First = false; - Comma = Comma.second.split(','); - } while (true); - - OS << ")\n"; - OS << " Features |= " << SFI.getEnumName() << ";\n"; - } - OS << " return Features;\n"; - OS << "}\n\n"; -} - static std::string GetAliasRequiredFeatures(Record *R, const AsmMatcherInfo &Info) { std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates"); @@ -2646,7 +2545,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2719,8 +2618,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the operand class switch to call the correct custom parser for // the found operand class. - OS << Target.getName() << ClassName << "::OperandMatchResultTy " - << Target.getName() << ClassName << "::\n" + OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n" << "tryCustomParseOperand(OperandVector" << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; @@ -2741,8 +2639,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parser. This code is very similar with // the other matcher. Also use MatchResultTy here just in case we go for // a better error handling. - OS << Target.getName() << ClassName << "::OperandMatchResultTy " - << Target.getName() << ClassName << "::\n" + OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n" << "MatchOperandParserImpl(OperandVector" << " &Operands,\n StringRef Mnemonic) {\n"; @@ -2822,15 +2719,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { const std::unique_ptr<MatchableInfo> &b){ return *a < *b;}); -#ifndef NDEBUG - // Verify that the table is now sorted +#ifdef EXPENSIVE_CHECKS + // Verify that the table is sorted and operator < works transitively. for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; ++I) { for (auto J = I; J != E; ++J) { assert(!(**J < **I)); } } -#endif // NDEBUG +#endif DEBUG_WITH_TYPE("instruction_info", { for (const auto &MI : Info.Matchables) @@ -2896,11 +2793,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " unsigned VariantID = 0);\n"; if (!Info.OperandMatchInfo.empty()) { - OS << "\n enum OperandMatchResultTy {\n"; - OS << " MatchOperand_Success, // operand matched successfully\n"; - OS << " MatchOperand_NoMatch, // operand did not match\n"; - OS << " MatchOperand_ParseFail // operand matched but had errors\n"; - OS << " };\n"; OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; OS << " OperandVector &Operands,\n"; OS << " StringRef Mnemonic);\n"; @@ -2922,7 +2814,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_REGISTER_MATCHER\n\n"; // Emit the subtarget feature enumeration. - emitSubtargetFeatureFlagEnumeration(Info, OS); + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + Info.SubtargetFeatures, OS); // Emit the function to match a register name to number. // This should be omitted for Mips target @@ -2967,7 +2860,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { emitValidateOperandClass(Info, OS); // Emit the available features compute function. - emitComputeAvailableFeatures(Info, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Info.Target.getName(), ClassName, "ComputeAvailableFeatures", + Info.SubtargetFeatures, OS); StringToOffsetTable StringTable; @@ -3005,7 +2900,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) @@ -3254,8 +3149,24 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " }\n"; OS << "\n"; OS << " Inst.clear();\n\n"; + OS << " Inst.setOpcode(it->Opcode);\n"; + // Verify the instruction with the target-specific match predicate function. + OS << " // We have a potential match but have not rendered the operands.\n" + << " // Check the target predicate to handle any context sensitive\n" + " // constraints.\n" + << " // For example, Ties that are referenced multiple times must be\n" + " // checked here to ensure the input is the same for each match\n" + " // constraints. If we leave it any later the ties will have been\n" + " // canonicalized\n" + << " unsigned MatchResult;\n" + << " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, " + "Operands)) != Match_Success) {\n" + << " Inst.clear();\n" + << " RetCode = MatchResult;\n" + << " HadMatchOtherThanPredicate = true;\n" + << " continue;\n" + << " }\n\n"; OS << " if (matchingInlineAsm) {\n"; - OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; OS << " return Match_Success;\n"; OS << " }\n\n"; @@ -3272,7 +3183,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Verify the instruction with the target-specific match predicate function. OS << " // We have a potential match. Check the target predicate to\n" << " // handle any context sensitive constraints.\n" - << " unsigned MatchResult;\n" << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !=" << " Match_Success) {\n" << " Inst.clear();\n" @@ -3289,7 +3199,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasDeprecation) { OS << " std::string Info;\n"; - OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; + OS << " if (!getParser().getTargetParser().\n"; + OS << " getTargetOptions().MCNoDeprecatedWarn &&\n"; + OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; OS << " getParser().Warning(Loc, Info, None);\n"; diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index fc2138f..a7c6104 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -13,32 +13,53 @@ //===----------------------------------------------------------------------===// #include "AsmWriterInst.h" +#include "CodeGenInstruction.h" +#include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" +#include "Types.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <algorithm> #include <cassert> +#include <cstddef> +#include <cstdint> +#include <deque> +#include <iterator> #include <map> +#include <set> +#include <string> +#include <tuple> #include <utility> #include <vector> + using namespace llvm; #define DEBUG_TYPE "asm-writer-emitter" namespace { + class AsmWriterEmitter { RecordKeeper &Records; CodeGenTarget Target; ArrayRef<const CodeGenInstruction *> NumberedInstructions; std::vector<AsmWriterInst> Instructions; + public: AsmWriterEmitter(RecordKeeper &R); @@ -54,10 +75,11 @@ private: std::vector<unsigned> &InstOpsUsed, bool PassSubtarget) const; }; + } // end anonymous namespace static void PrintCases(std::vector<std::pair<std::string, - AsmWriterOperand> > &OpsToPrint, raw_ostream &O, + AsmWriterOperand>> &OpsToPrint, raw_ostream &O, bool PassSubtarget) { O << " case " << OpsToPrint.back().first << ":"; AsmWriterOperand TheOp = OpsToPrint.back().second; @@ -76,7 +98,6 @@ static void PrintCases(std::vector<std::pair<std::string, O << "\n break;\n"; } - /// EmitInstructions - Emit the last instruction in the vector and any other /// instructions that are suitably similar to it. static void EmitInstructions(std::vector<AsmWriterInst> &Insts, @@ -115,14 +136,14 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts, // emit a switch for just this operand now. O << " switch (MI->getOpcode()) {\n"; O << " default: llvm_unreachable(\"Unexpected opcode.\");\n"; - std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; + std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint; OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" + - FirstInst.CGI->TheDef->getName(), + FirstInst.CGI->TheDef->getName().str(), FirstInst.Operands[i])); for (const AsmWriterInst &AWI : SimilarInsts) { - OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+ - AWI.CGI->TheDef->getName(), + OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::" + + AWI.CGI->TheDef->getName().str(), AWI.Operands[i])); } std::reverse(OpsToPrint.begin(), OpsToPrint.end()); @@ -140,7 +161,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, std::vector<std::vector<unsigned>> &InstIdxs, std::vector<unsigned> &InstOpsUsed, bool PassSubtarget) const { - // This vector parallels UniqueOperandCommands, keeping track of which // instructions each case are used for. It is a comma separated string of // enums. @@ -157,8 +177,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, // Check to see if we already have 'Command' in UniqueOperandCommands. // If not, add it. - auto I = std::find(UniqueOperandCommands.begin(), - UniqueOperandCommands.end(), Command); + auto I = llvm::find(UniqueOperandCommands, Command); if (I != UniqueOperandCommands.end()) { size_t idx = I - UniqueOperandCommands.begin(); InstrsForCase[idx] += ", "; @@ -225,7 +244,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, } } - static void UnescapeString(std::string &Str) { for (unsigned i = 0; i != Str.size(); ++i) { if (Str[i] == '\\' && i != Str.size()-1) { @@ -317,7 +335,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { std::vector<std::vector<std::string>> TableDrivenOperandPrinters; - while (1) { + while (true) { std::vector<std::string> UniqueOperandCommands; std::vector<std::vector<unsigned>> InstIdxs; std::vector<unsigned> NumInstOpsHandled; @@ -451,10 +469,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Okay, delete instructions with no operand info left. - auto I = std::remove_if(Instructions.begin(), Instructions.end(), - [](AsmWriterInst &Inst) { - return Inst.Operands.empty(); - }); + auto I = llvm::remove_if(Instructions, + [](AsmWriterInst &Inst) { return Inst.Operands.empty(); }); Instructions.erase(I, Instructions.end()); @@ -480,15 +496,6 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << "}\n"; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - static void emitRegisterNameString(raw_ostream &O, StringRef AltName, const std::deque<CodeGenRegister> &Registers) { @@ -533,7 +540,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, StringTable.emit(O, printChar); O << " };\n\n"; - O << " static const " << getMinimalTypeForRange(StringTable.size()-1) + O << " static const " << getMinimalTypeForRange(StringTable.size() - 1, 32) << " RegAsmOffset" << AltName << "[] = {"; for (unsigned i = 0, e = Registers.size(); i != e; ++i) { if ((i % 14) == 0) @@ -595,6 +602,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { } namespace { + // IAPrinter - Holds information about an InstAlias. Two InstAliases match if // they both have the same conditionals. In which case, we cannot print out the // alias for that pattern. @@ -604,6 +612,7 @@ class IAPrinter { std::string Result; std::string AsmString; + public: IAPrinter(std::string R, std::string AS) : Result(std::move(R)), AsmString(std::move(AS)) {} @@ -725,9 +734,10 @@ static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) { } namespace { + struct AliasPriorityComparator { typedef std::pair<CodeGenInstAlias, int> ValueType; - bool operator()(const ValueType &LHS, const ValueType &RHS) { + bool operator()(const ValueType &LHS, const ValueType &RHS) const { if (LHS.second == RHS.second) { // We don't actually care about the order, but for consistency it // shouldn't depend on pointer comparisons. @@ -738,8 +748,8 @@ struct AliasPriorityComparator { return LHS.second > RHS.second; } }; -} +} // end anonymous namespace void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); @@ -814,14 +824,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { NumMIOps += Operand.getMINumOperands(); std::string Cond; - Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps); + Cond = std::string("MI->getNumOperands() == ") + utostr(NumMIOps); IAP.addCond(Cond); bool CantHandle = false; unsigned MIOpNum = 0; for (unsigned i = 0, e = LastOpNo; i != e; ++i) { - std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")"; + std::string Op = "MI->getOperand(" + utostr(MIOpNum) + ")"; const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i]; @@ -838,9 +848,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Rec->isSubClassOf("Operand")) { std::string PrintMethod = Rec->getValueAsString("PrintMethod"); if (PrintMethod != "" && PrintMethod != "printOperand") { - PrintMethodIdx = std::find(PrintMethods.begin(), - PrintMethods.end(), PrintMethod) - - PrintMethods.begin(); + PrintMethodIdx = + llvm::find(PrintMethods, PrintMethod) - PrintMethods.begin(); if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size()) PrintMethods.push_back(PrintMethod); } @@ -856,12 +865,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Record *R = CGA.ResultOperands[i].getRecord(); if (R->isSubClassOf("RegisterOperand")) R = R->getValueAsDef("RegClass"); - Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + - R->getName() + "RegClassID)" - ".contains(" + Op + ".getReg())"; + Cond = std::string("MRI.getRegClass(") + Target.getName().str() + + "::" + R->getName().str() + "RegClassID).contains(" + Op + + ".getReg())"; } else { Cond = Op + ".getReg() == MI->getOperand(" + - llvm::utostr(IAP.getOpIndex(ROName)) + ").getReg()"; + utostr(IAP.getOpIndex(ROName)) + ").getReg()"; } } else { // Assume all printable operands are desired for now. This can be @@ -878,8 +887,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } else break; // No conditions on this operand at all } - Cond = Target.getName() + ClassName + "ValidateMCOperand(" + - Op + ", STI, " + llvm::utostr(Entry) + ")"; + Cond = Target.getName().str() + ClassName + "ValidateMCOperand(" + + Op + ", STI, " + utostr(Entry) + ")"; } // for all subcases of ResultOperand::K_Record: IAP.addCond(Cond); @@ -890,8 +899,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // MCInst will. An MCExpr could be present, for example. IAP.addCond(Op + ".isImm()"); - Cond = Op + ".getImm() == " + - llvm::utostr(CGA.ResultOperands[i].getImm()); + Cond = Op + ".getImm() == " + itostr(CGA.ResultOperands[i].getImm()); IAP.addCond(Cond); break; } @@ -903,8 +911,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; } - Cond = Op + ".getReg() == " + Target.getName() + "::" + - CGA.ResultOperands[i].getRegister()->getName(); + Cond = Op + ".getReg() == " + Target.getName().str() + "::" + + CGA.ResultOperands[i].getRegister()->getName().str(); IAP.addCond(Cond); break; } @@ -1112,7 +1120,6 @@ void AsmWriterEmitter::run(raw_ostream &O) { EmitPrintAliasInstruction(O); } - namespace llvm { void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) { @@ -1120,4 +1127,4 @@ void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) { AsmWriterEmitter(RK).run(OS); } -} // End llvm namespace +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp index 58dbe57..927f6e0 100644 --- a/contrib/llvm/utils/TableGen/Attributes.cpp +++ b/contrib/llvm/utils/TableGen/Attributes.cpp @@ -156,7 +156,7 @@ void Attributes::printStrBoolAttrClasses(raw_ostream &OS, OS << "// StrBoolAttr classes\n"; for (const auto *R : Records) { OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n"; - OS << " static const char *getKind() {\n"; + OS << " static StringRef getKind() {\n"; OS << " return \"" << R->getValueAsString("AttrString") << "\";\n"; OS << " }\n"; OS << "};\n"; diff --git a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp index 35f4ad6..5213cd9 100644 --- a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp +++ b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp @@ -37,7 +37,7 @@ public: void emit(raw_ostream &OS) const { const MemoryBuffer *CurMB = SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc)); - const char *BufferName = CurMB->getBufferIdentifier(); + auto BufferName = CurMB->getBufferIdentifier(); std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; } diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 400913e..f34c0de 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -13,24 +13,35 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenInstruction.h" #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include <cassert> +#include <cstdint> #include <map> +#include <set> #include <string> +#include <utility> #include <vector> + using namespace llvm; namespace { class CodeEmitterGen { RecordKeeper &Records; + public: CodeEmitterGen(RecordKeeper &R) : Records(R) {} void run(raw_ostream &o); + private: int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); std::string getInstructionCase(Record *R, CodeGenTarget &Target); @@ -173,7 +184,6 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, } } - std::string CodeEmitterGen::getInstructionCase(Record *R, CodeGenTarget &Target) { std::string Case; @@ -259,7 +269,7 @@ void CodeEmitterGen::run(raw_ostream &o) { o << " UINT64_C(0)\n };\n"; // Map to accumulate all the cases. - std::map<std::string, std::vector<std::string> > CaseMap; + std::map<std::string, std::vector<std::string>> CaseMap; // Construct all cases statement for each opcode for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); @@ -269,7 +279,7 @@ void CodeEmitterGen::run(raw_ostream &o) { R->getValueAsBit("isPseudo")) continue; const std::string &InstName = R->getValueAsString("Namespace") + "::" - + R->getName(); + + R->getName().str(); std::string Case = getInstructionCase(R, Target); CaseMap[Case].push_back(InstName); @@ -283,7 +293,7 @@ void CodeEmitterGen::run(raw_ostream &o) { << " switch (opcode) {\n"; // Emit each case statement - std::map<std::string, std::vector<std::string> >::iterator IE, EE; + std::map<std::string, std::vector<std::string>>::iterator IE, EE; for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { const std::string &Case = IE->first; std::vector<std::string> &InstList = IE->second; @@ -307,9 +317,72 @@ void CodeEmitterGen::run(raw_ostream &o) { << " }\n" << " return Value;\n" << "}\n\n"; + + const auto &All = SubtargetFeatureInfo::getAll(Records); + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; + SubtargetFeatures.insert(All.begin(), All.end()); + + o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#include <sstream>\n\n"; + + // Emit the subtarget feature enumeration. + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures, + o); + + // Emit the name table for error messages. + o << "#ifndef NDEBUG\n"; + SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o); + o << "#endif // NDEBUG\n"; + + // Emit the available features compute function. + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", + SubtargetFeatures, o); + + // Emit the predicate verifier. + o << "void " << Target.getName() + << "MCCodeEmitter::verifyInstructionPredicates(\n" + << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n" + << "#ifndef NDEBUG\n" + << " static uint64_t RequiredFeatures[] = {\n"; + unsigned InstIdx = 0; + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + o << " "; + for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) + o << I->second.getEnumName() << " | "; + } + o << "0, // " << 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" + << " 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" + << " Msg << SubtargetFeatureNames[i] << \" \";\n" + << " Msg << \"predicate(s) are not met\";\n" + << " report_fatal_error(Msg.str());\n" + << " }\n" + << "#else\n" + << "// Silence unused variable warning on targets that don't use MCII for " + "other purposes (e.g. BPF).\n" + << "(void)MCII;\n" + << "#endif // NDEBUG\n"; + o << "}\n"; + o << "#endif\n"; } -} // End anonymous namespace +} // end anonymous namespace namespace llvm { @@ -318,4 +391,4 @@ void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) { CodeEmitterGen(RK).run(OS); } -} // End llvm namespace +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index 307a953..b82a76b 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -108,24 +108,24 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, /// hasIntegerTypes - Return true if this TypeSet contains iAny or an /// integer value type. bool EEVT::TypeSet::hasIntegerTypes() const { - return std::any_of(TypeVec.begin(), TypeVec.end(), isInteger); + return any_of(TypeVec, isInteger); } /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or /// a floating point value type. bool EEVT::TypeSet::hasFloatingPointTypes() const { - return std::any_of(TypeVec.begin(), TypeVec.end(), isFloatingPoint); + return any_of(TypeVec, isFloatingPoint); } /// hasScalarTypes - Return true if this TypeSet contains a scalar value type. bool EEVT::TypeSet::hasScalarTypes() const { - return std::any_of(TypeVec.begin(), TypeVec.end(), isScalar); + return any_of(TypeVec, isScalar); } /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector /// value type. bool EEVT::TypeSet::hasVectorTypes() const { - return std::any_of(TypeVec.begin(), TypeVec.end(), isVector); + return any_of(TypeVec, isVector); } @@ -239,8 +239,7 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { TypeSet InputSet(*this); // Filter out all the fp types. - TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), - std::not1(std::ptr_fun(isInteger))), + TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isInteger))), TypeVec.end()); if (TypeVec.empty()) { @@ -265,8 +264,7 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { TypeSet InputSet(*this); // Filter out all the integer types. - TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), - std::not1(std::ptr_fun(isFloatingPoint))), + TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isFloatingPoint))), TypeVec.end()); if (TypeVec.empty()) { @@ -292,8 +290,7 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { TypeSet InputSet(*this); // Filter out all the vector types. - TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), - std::not1(std::ptr_fun(isScalar))), + TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isScalar))), TypeVec.end()); if (TypeVec.empty()) { @@ -317,8 +314,7 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { bool MadeChange = false; // Filter out all the scalar types. - TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), - std::not1(std::ptr_fun(isVector))), + TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isVector))), TypeVec.end()); if (TypeVec.empty()) { @@ -395,16 +391,15 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { A.getSizeInBits() < B.getSizeInBits()); }); - auto I = std::remove_if(Other.TypeVec.begin(), Other.TypeVec.end(), - [Smallest](MVT OtherVT) { - // Don't compare vector and non-vector types. - if (OtherVT.isVector() != Smallest.isVector()) - return false; - // The getSizeInBits() check here is only needed for vectors, but is - // a subset of the scalar check for scalars so no need to qualify. - return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits()|| - OtherVT.getSizeInBits() < Smallest.getSizeInBits(); - }); + auto I = remove_if(Other.TypeVec, [Smallest](MVT OtherVT) { + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Smallest.isVector()) + return false; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() || + OtherVT.getSizeInBits() < Smallest.getSizeInBits(); + }); MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types. Other.TypeVec.erase(I, Other.TypeVec.end()); @@ -428,14 +423,13 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { (A.getScalarSizeInBits() == B.getScalarSizeInBits() && A.getSizeInBits() < B.getSizeInBits()); }); - auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), - [Largest](MVT OtherVT) { - // Don't compare vector and non-vector types. - if (OtherVT.isVector() != Largest.isVector()) - return false; - return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || - OtherVT.getSizeInBits() > Largest.getSizeInBits(); - }); + auto I = remove_if(TypeVec, [Largest](MVT OtherVT) { + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Largest.isVector()) + return false; + return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || + OtherVT.getSizeInBits() > Largest.getSizeInBits(); + }); MadeChange |= I != TypeVec.end(); // If we're about to remove types. TypeVec.erase(I, TypeVec.end()); @@ -460,10 +454,9 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TypeSet InputSet(*this); // Filter out all the types which don't have the right element type. - auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), - [VT](MVT VVT) { - return VVT.getVectorElementType().SimpleTy != VT; - }); + auto I = remove_if(TypeVec, [VT](MVT VVT) { + return VVT.getVectorElementType().SimpleTy != VT; + }); MadeChange |= I != TypeVec.end(); TypeVec.erase(I, TypeVec.end()); @@ -547,10 +540,9 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, // Only keep types that have less elements than VTOperand. TypeSet InputSet(VTOperand); - auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), - [NumElems](MVT VVT) { - return VVT.getVectorNumElements() >= NumElems; - }); + auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) { + return VVT.getVectorNumElements() >= NumElems; + }); MadeChange |= I != VTOperand.TypeVec.end(); VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); @@ -571,10 +563,9 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, // Only keep types that have more elements than 'this'. TypeSet InputSet(*this); - auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), - [NumElems](MVT VVT) { - return VVT.getVectorNumElements() <= NumElems; - }); + auto I = remove_if(TypeVec, [NumElems](MVT VVT) { + return VVT.getVectorNumElements() <= NumElems; + }); MadeChange |= I != TypeVec.end(); TypeVec.erase(I, TypeVec.end()); @@ -609,10 +600,9 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, // Only keep types that have same elements as 'this'. TypeSet InputSet(VTOperand); - auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), - [NumElems](MVT VVT) { - return VVT.getVectorNumElements() != NumElems; - }); + auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) { + return VVT.getVectorNumElements() != NumElems; + }); MadeChange |= I != VTOperand.TypeVec.end(); VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); @@ -629,10 +619,9 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, // Only keep types that have same elements as VTOperand. TypeSet InputSet(*this); - auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), - [NumElems](MVT VVT) { - return VVT.getVectorNumElements() != NumElems; - }); + auto I = remove_if(TypeVec, [NumElems](MVT VVT) { + return VVT.getVectorNumElements() != NumElems; + }); MadeChange |= I != TypeVec.end(); TypeVec.erase(I, TypeVec.end()); @@ -663,10 +652,8 @@ bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand, // Only keep types that have the same size as 'this'. TypeSet InputSet(VTOperand); - auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), - [&](MVT VT) { - return VT.getSizeInBits() != Size; - }); + auto I = remove_if(VTOperand.TypeVec, + [&](MVT VT) { return VT.getSizeInBits() != Size; }); MadeChange |= I != VTOperand.TypeVec.end(); VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); @@ -683,10 +670,8 @@ bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand, // Only keep types that have the same size as VTOperand. TypeSet InputSet(*this); - auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), - [&](MVT VT) { - return VT.getSizeInBits() != Size; - }); + auto I = + remove_if(TypeVec, [&](MVT VT) { return VT.getSizeInBits() != Size; }); MadeChange |= I != TypeVec.end(); TypeVec.erase(I, TypeVec.end()); @@ -770,7 +755,7 @@ bool TreePredicateFn::isAlwaysTrue() const { /// Return the name to use in the generated code to reference this, this is /// "Predicate_foo" if from a pattern fragment "foo". std::string TreePredicateFn::getFnName() const { - return "Predicate_" + PatFragRec->getRecord()->getName(); + return "Predicate_" + PatFragRec->getRecord()->getName().str(); } /// getCodeToRunOnSDNode - Return the code for the function body that @@ -820,14 +805,9 @@ static unsigned getPatternSize(const TreePatternNode *P, if (P->isLeaf() && isa<IntInit>(P->getLeafValue())) Size += 2; - // FIXME: This is a hack to statically increase the priority of patterns - // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. - // Later we can allow complexity / cost for each pattern to be (optionally) - // specified. To get best possible pattern match we'll need to dynamically - // calculate the complexity of all patterns a dag can potentially map to. const ComplexPattern *AM = P->getComplexPatternInfo(CGP); if (AM) { - Size += AM->getNumOperands() * 3; + Size += AM->getComplexity(); // We don't want to count any children twice, so return early. return Size; @@ -2026,7 +2006,7 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, // Scan all of the operands of the node and make sure that only the last one // is a constant node, unless the RHS also is. if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) { - bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. + unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i) if (OnlyOnRHSOfCommutative(getChild(i))) { Reason="Immediate value must be on the RHS of commutative operators!"; @@ -2092,8 +2072,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ /// (foo GPR, imm) -> (foo GPR, (imm)) if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) return ParseTreePattern( - DagInit::get(DI, "", - std::vector<std::pair<Init*, std::string> >()), + DagInit::get(DI, nullptr, + std::vector<std::pair<Init*, StringInit*> >()), OpName); // Input argument? @@ -2147,7 +2127,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ if (Dag->getNumArgs() != 1) error("Type cast only takes one operand!"); - TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0)); + TreePatternNode *New = ParseTreePattern(Dag->getArg(0), + Dag->getArgNameStr(0)); // Apply the type cast. assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); @@ -2198,7 +2179,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ // Parse all the operands. for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) - Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i))); + Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i))); // If the operator is an intrinsic, then this is just syntactic sugar for for // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and @@ -2246,9 +2227,9 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(OpName); - if (!Dag->getName().empty()) { + if (Dag->getName()) { assert(Result->getName().empty()); - Result->setName(Dag->getName()); + Result->setName(Dag->getNameStr()); } return Result; } @@ -2504,13 +2485,14 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { if (!isa<DefInit>(OpsList->getArg(j)) || cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node") P->error("Operands list should all be 'node' values."); - if (OpsList->getArgName(j).empty()) + if (!OpsList->getArgName(j)) P->error("Operands list should have names for each operand!"); - if (!OperandsSet.count(OpsList->getArgName(j))) - P->error("'" + OpsList->getArgName(j) + + StringRef ArgNameStr = OpsList->getArgNameStr(j); + if (!OperandsSet.count(ArgNameStr)) + P->error("'" + ArgNameStr + "' does not occur in pattern or was multiply specified!"); - OperandsSet.erase(OpsList->getArgName(j)); - Args.push_back(OpsList->getArgName(j)); + OperandsSet.erase(ArgNameStr); + Args.push_back(ArgNameStr); } if (!OperandsSet.empty()) @@ -2562,11 +2544,11 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { // Clone the DefaultInfo dag node, changing the operator from 'ops' to // SomeSDnode so that we can parse this. - std::vector<std::pair<Init*, std::string> > Ops; + std::vector<std::pair<Init*, StringInit*> > Ops; for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) Ops.push_back(std::make_pair(DefaultInfo->getArg(op), DefaultInfo->getArgName(op))); - DagInit *DI = DagInit::get(SomeSDNode, "", Ops); + DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops); // Create a TreePattern to parse this. TreePattern P(DefaultOps[i], DI, false, *this); @@ -3602,10 +3584,9 @@ static void CombineChildVariants(TreePatternNode *Orig, // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) // which are the same pattern. Ignore the dups. if (R->canPatternMatch(ErrString, CDP) && - std::none_of(OutVariants.begin(), OutVariants.end(), - [&](TreePatternNode *Variant) { - return R->isIsomorphicTo(Variant, DepVars); - })) + none_of(OutVariants, [&](TreePatternNode *Variant) { + return R->isIsomorphicTo(Variant, DepVars); + })) OutVariants.push_back(R.release()); // Increment indices to the next permutation by incrementing the diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index 819c4b8..97401cd 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -412,8 +412,7 @@ public: } void addPredicateFn(const TreePredicateFn &Fn) { assert(!Fn.isAlwaysTrue() && "Empty predicate string!"); - if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) == - PredicateFns.end()) + if (!is_contained(PredicateFns, Fn)) PredicateFns.push_back(Fn); } @@ -810,11 +809,13 @@ public: LessRecordByID>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } pf_iterator pf_end() const { return PatternFragments.end(); } + iterator_range<pf_iterator> ptfs() const { return PatternFragments; } // Patterns to match information. typedef std::vector<PatternToMatch>::const_iterator ptm_iterator; ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); } ptm_iterator ptm_end() const { return PatternsToMatch.end(); } + iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; } /// Parse the Pattern for an instruction, and insert the result in DAGInsts. typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap; diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index ec80236..bb2ec2a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -53,13 +53,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { OperandList.reserve(e); for (unsigned i = 0; i != e; ++i){ Init *ArgInit; - std::string ArgName; + StringRef ArgName; if (i < NumDefs) { ArgInit = OutDI->getArg(i); - ArgName = OutDI->getArgName(i); + ArgName = OutDI->getArgNameStr(i); } else { ArgInit = InDI->getArg(i-NumDefs); - ArgName = InDI->getArgName(i-NumDefs); + ArgName = InDI->getArgNameStr(i-NumDefs); } DefInit *Arg = dyn_cast<DefInit>(ArgInit); @@ -165,7 +165,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { std::string SubOpName; // Check to see if this is $foo.bar. - std::string::size_type DotIdx = OpName.find_first_of("."); + std::string::size_type DotIdx = OpName.find_first_of('.'); if (DotIdx != std::string::npos) { SubOpName = OpName.substr(DotIdx+1); if (SubOpName.empty()) @@ -193,7 +193,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // Find the operand with the right name. for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) - if (MIOpInfo->getArgName(i) == SubOpName) + if (MIOpInfo->getArgNameStr(i) == SubOpName) return std::make_pair(OpIdx, i); // Otherwise, didn't find it! @@ -309,6 +309,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) isSelect = R->getValueAsBit("isSelect"); isBarrier = R->getValueAsBit("isBarrier"); isCall = R->getValueAsBit("isCall"); + isAdd = R->getValueAsBit("isAdd"); canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); @@ -448,10 +449,10 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (ADI && ADI->getDef() == InstOpRec) { // If the operand is a record, it must have a name, and the record type // must match up with the instruction's argument type. - if (Result->getArgName(AliasOpNo).empty()) + if (!Result->getArgName(AliasOpNo)) PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + " must have a name!"); - ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord); + ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord); return true; } @@ -469,7 +470,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (!T.getRegisterClass(InstOpRec) .hasSubClass(&T.getRegisterClass(ADI->getDef()))) return false; - ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord); + ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord); return true; } @@ -491,7 +492,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, " is not a member of the " + InstOpRec->getName() + " register class!"); - if (!Result->getArgName(AliasOpNo).empty()) + if (Result->getArgName(AliasOpNo)) PrintFatalError(Loc, "result fixed register argument must " "not have a name!"); @@ -520,7 +521,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) return false; // Integer arguments can't have names. - if (!Result->getArgName(AliasOpNo).empty()) + if (Result->getArgName(AliasOpNo)) PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + " must not have a name!"); ResOp = ResultOperand(II->getValue()); @@ -551,7 +552,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // MIOperandInfo perhaps? if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) return false; - ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ADI->getDef()); return true; } @@ -596,14 +597,14 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant, StringMap<Record*> NameClass; for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i)); - if (!ADI || Result->getArgName(i).empty()) + if (!ADI || !Result->getArgName(i)) continue; // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) // $foo can exist multiple times in the result list, but it must have the // same type. - Record *&Entry = NameClass[Result->getArgName(i)]; + Record *&Entry = NameClass[Result->getArgNameStr(i)]; if (Entry && Entry != ADI->getDef()) - PrintFatalError(R->getLoc(), "result value $" + Result->getArgName(i) + + PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) + " is both " + Entry->getName() + " and " + ADI->getDef()->getName() + "!"); Entry = ADI->getDef(); @@ -646,9 +647,9 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant, // Take care to instantiate each of the suboperands with the correct // nomenclature: $foo.bar - ResultOperands.emplace_back(Result->getArgName(AliasOpNo) + "." + - MIOI->getArgName(SubOp), - SubRec); + ResultOperands.emplace_back( + Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." + + MIOI->getArgName(SubOp)->getAsUnquotedString(), SubRec); ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); } ++AliasOpNo; diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h index 8e5a03d..75db17b 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h @@ -230,6 +230,7 @@ template <typename T> class ArrayRef; bool isSelect : 1; bool isBarrier : 1; bool isCall : 1; + bool isAdd : 1; bool canFoldAsLoad : 1; bool mayLoad : 1; bool mayLoad_Unset : 1; diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h index ea3ec67..6df0e6a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -62,15 +62,23 @@ struct CodeGenIntrinsic { /// accesses that may be performed by the intrinsics. Analogous to /// \c FunctionModRefBehaviour. enum ModRefBits { + /// The intrinsic may access memory that is otherwise inaccessible via + /// LLVM IR. + MR_InaccessibleMem = 1, + + /// The intrinsic may access memory through pointer arguments. + /// LLVM IR. + MR_ArgMem = 2, + /// The intrinsic may access memory anywhere, i.e. it is not restricted /// to access through pointer arguments. - MR_Anywhere = 1, + MR_Anywhere = 4 | MR_ArgMem | MR_InaccessibleMem, /// The intrinsic may read memory. - MR_Ref = 2, + MR_Ref = 8, /// The intrinsic may write memory. - MR_Mod = 4, + MR_Mod = 16, /// The intrinsic may both read and write memory. MR_ModRef = MR_Ref | MR_Mod, @@ -80,11 +88,18 @@ struct CodeGenIntrinsic { /// properties (IntrReadMem, IntrArgMemOnly, etc.). enum ModRefBehavior { NoMem = 0, - ReadArgMem = MR_Ref, + ReadArgMem = MR_Ref | MR_ArgMem, + ReadInaccessibleMem = MR_Ref | MR_InaccessibleMem, + ReadInaccessibleMemOrArgMem = MR_Ref | MR_ArgMem | MR_InaccessibleMem, ReadMem = MR_Ref | MR_Anywhere, - WriteArgMem = MR_Mod, + WriteArgMem = MR_Mod | MR_ArgMem, + WriteInaccessibleMem = MR_Mod | MR_InaccessibleMem, + WriteInaccessibleMemOrArgMem = MR_Mod | MR_ArgMem | MR_InaccessibleMem, WriteMem = MR_Mod | MR_Anywhere, - ReadWriteArgMem = MR_ModRef, + ReadWriteArgMem = MR_ModRef | MR_ArgMem, + ReadWriteInaccessibleMem = MR_ModRef | MR_InaccessibleMem, + ReadWriteInaccessibleMemOrArgMem = MR_ModRef | MR_ArgMem | + MR_InaccessibleMem, ReadWriteMem = MR_ModRef | MR_Anywhere, }; ModRefBehavior ModRef; diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp index 527f530..8032d7b 100644 --- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp @@ -542,6 +542,7 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { for (unsigned j = i+1; j < FieldValues.size(); j++) { if (CurVal == FieldValues[j]) { FieldValues.erase(FieldValues.begin()+j); + --j; } } } diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index 626144f..c03e0d1 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -14,13 +14,33 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntEqClasses.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <iterator> +#include <map> +#include <set> +#include <string> +#include <tuple> +#include <utility> +#include <vector> using namespace llvm; @@ -31,7 +51,7 @@ using namespace llvm; //===----------------------------------------------------------------------===// CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) - : TheDef(R), EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) { + : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true) { Name = R->getName(); if (R->getValue("Namespace")) Namespace = R->getValueAsString("Namespace"); @@ -42,7 +62,7 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) : TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1), - EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) { + EnumValue(Enum), AllSuperRegsCovered(true) { } std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -82,19 +102,19 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { } } -unsigned CodeGenSubRegIndex::computeLaneMask() const { +LaneBitmask CodeGenSubRegIndex::computeLaneMask() const { // Already computed? - if (LaneMask) + if (LaneMask.any()) return LaneMask; // Recursion guard, shouldn't be required. - LaneMask = ~0u; + LaneMask = LaneBitmask::getAll(); // The lane mask is simply the union of all sub-indices. - unsigned M = 0; + LaneBitmask M; for (const auto &C : Composed) M |= C.second->computeLaneMask(); - assert(M && "Missing lane mask, sub-register cycle?"); + assert(M.any() && "Missing lane mask, sub-register cycle?"); LaneMask = M; return LaneMask; } @@ -145,12 +165,13 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) { } } -const std::string &CodeGenRegister::getName() const { +const StringRef CodeGenRegister::getName() const { assert(TheDef && "no def"); return TheDef->getName(); } namespace { + // Iterate over all register units in a set of registers. class RegUnitIterator { CodeGenRegister::Vec::const_iterator RegI, RegE; @@ -158,7 +179,7 @@ class RegUnitIterator { public: RegUnitIterator(const CodeGenRegister::Vec &Regs): - RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() { + RegI(Regs.begin()), RegE(Regs.end()) { if (RegI != RegE) { UnitI = (*RegI)->getRegUnits().begin(); @@ -190,7 +211,8 @@ protected: } } }; -} // namespace + +} // end anonymous namespace // Return true of this unit appears in RegUnits. static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) { @@ -538,6 +560,7 @@ unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { // sub-registers. We provide a SetTheory expander class that returns the new // registers. namespace { + struct TupleExpander : SetTheory::Expander { void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override { std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices"); @@ -639,7 +662,8 @@ struct TupleExpander : SetTheory::Expander { } } }; -} + +} // end anonymous namespace //===----------------------------------------------------------------------===// // CodeGenRegisterClass @@ -654,8 +678,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(R->getName()), TopoSigs(RegBank.getNumTopoSigs()), - EnumValue(-1), - LaneMask(0) { + EnumValue(-1) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; @@ -767,13 +790,15 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { } namespace llvm { + raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) { OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment; for (const auto R : *K.Members) OS << ", " << R->getName(); return OS << " }"; } -} + +} // end namespace llvm // This is a simple lexicographical order that can be used to search for sets. // It is not the same as the topological order provided by TopoOrderRC. @@ -813,7 +838,7 @@ static bool TopoOrderRC(const CodeGenRegisterClass &PA, auto *A = &PA; auto *B = &PB; if (A == B) - return 0; + return false; // Order by ascending spill size. if (A->SpillSize < B->SpillSize) @@ -1167,7 +1192,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // First assign individual bits to all the leaf indices. unsigned Bit = 0; // Determine mask of lanes that cover their registers. - CoveringLanes = ~0u; + CoveringLanes = LaneBitmask::getAll(); for (auto &Idx : SubRegIndices) { if (Idx.getComposites().empty()) { if (Bit > 32) { @@ -1175,10 +1200,10 @@ void CodeGenRegBank::computeSubRegLaneMasks() { Twine("Ran out of lanemask bits to represent subregister ") + Idx.getName()); } - Idx.LaneMask = 1u << Bit; + Idx.LaneMask = LaneBitmask(1 << Bit); ++Bit; } else { - Idx.LaneMask = 0; + Idx.LaneMask = LaneBitmask::getNone(); } } @@ -1197,9 +1222,12 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // Moving from a class with no subregisters we just had a single lane: // The subregister must be a leaf subregister and only occupies 1 bit. // Move the bit from the class without subregisters into that position. - unsigned DstBit = Log2_32(Idx.LaneMask); - assert(Idx.LaneMask == 1u << DstBit && "Must be a leaf subregister"); - MaskRolPair MaskRol = { 1, (uint8_t)DstBit }; + static_assert(sizeof(Idx.LaneMask.getAsInteger()) == 4, + "Change Log2_32 to a proper one"); + unsigned DstBit = Log2_32(Idx.LaneMask.getAsInteger()); + assert(Idx.LaneMask == LaneBitmask(1 << DstBit) && + "Must be a leaf subregister"); + MaskRolPair MaskRol = { LaneBitmask(1), (uint8_t)DstBit }; LaneTransforms.push_back(MaskRol); } else { // Go through all leaf subregisters and find the ones that compose with @@ -1213,8 +1241,8 @@ void CodeGenRegBank::computeSubRegLaneMasks() { continue; // Replicate the behaviour from the lane mask generation loop above. unsigned SrcBit = NextBit; - unsigned SrcMask = 1u << SrcBit; - if (NextBit < 31) + LaneBitmask SrcMask = LaneBitmask(1 << SrcBit); + if (NextBit < LaneBitmask::BitWidth-1) ++NextBit; assert(Idx2.LaneMask == SrcMask); @@ -1227,16 +1255,19 @@ void CodeGenRegBank::computeSubRegLaneMasks() { assert(Composite->getComposites().empty()); // Create Mask+Rotate operation and merge with existing ops if possible. - unsigned DstBit = Log2_32(Composite->LaneMask); + static_assert(sizeof(Composite->LaneMask.getAsInteger()) == 4, + "Change Log2_32 to a proper one"); + unsigned DstBit = Log2_32(Composite->LaneMask.getAsInteger()); int Shift = DstBit - SrcBit; - uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift; + uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift + : LaneBitmask::BitWidth + Shift; for (auto &I : LaneTransforms) { if (I.RotateLeft == RotateLeft) { I.Mask |= SrcMask; - SrcMask = 0; + SrcMask = LaneBitmask::getNone(); } } - if (SrcMask != 0) { + if (SrcMask.any()) { MaskRolPair MaskRol = { SrcMask, RotateLeft }; LaneTransforms.push_back(MaskRol); } @@ -1247,13 +1278,13 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // 0xffffffff (including some irrelevant invalid bits) so that it should // merge with more entries later while compressing the table. if (LaneTransforms.size() == 1) - LaneTransforms[0].Mask = ~0u; + LaneTransforms[0].Mask = LaneBitmask::getAll(); // Further compression optimization: For invalid compositions resulting // in a sequence with 0 entries we can just pick any other. Choose // Mask 0xffffffff with Rotation 0. if (LaneTransforms.size() == 0) { - MaskRolPair P = { ~0u, 0 }; + MaskRolPair P = { LaneBitmask::getAll(), 0 }; LaneTransforms.push_back(P); } } @@ -1263,7 +1294,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // Inherit lanes from composites. for (const auto &Idx : SubRegIndices) { - unsigned Mask = Idx.computeLaneMask(); + LaneBitmask Mask = Idx.computeLaneMask(); // If some super-registers without CoveredBySubRegs use this index, we can // no longer assume that the lanes are covering their registers. if (!Idx.AllSuperRegsCovered) @@ -1272,7 +1303,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // Compute lane mask combinations for register classes. for (auto &RegClass : RegClasses) { - unsigned LaneMask = 0; + LaneBitmask LaneMask; for (const auto &SubRegIndex : SubRegIndices) { if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr) continue; @@ -1281,14 +1312,15 @@ void CodeGenRegBank::computeSubRegLaneMasks() { // For classes without any subregisters set LaneMask to 1 instead of 0. // This makes it easier for client code to handle classes uniformly. - if (LaneMask == 0) - LaneMask = 1; + if (LaneMask.none()) + LaneMask = LaneBitmask(1); RegClass.LaneMask = LaneMask; } } namespace { + // UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is // the transitive closure of the union of overlapping register // classes. Together, the UberRegSets form a partition of the registers. If we @@ -1307,12 +1339,13 @@ namespace { // their weight increased. struct UberRegSet { CodeGenRegister::Vec Regs; - unsigned Weight; + unsigned Weight = 0; CodeGenRegister::RegUnitList SingularDeterminants; - UberRegSet(): Weight(0) {} + UberRegSet() = default; }; -} // namespace + +} // end anonymous namespace // Partition registers into UberRegSets, where each set is the transitive // closure of the union of overlapping register classes. @@ -1321,7 +1354,6 @@ struct UberRegSet { static void computeUberSets(std::vector<UberRegSet> &UberSets, std::vector<UberRegSet*> &RegSets, CodeGenRegBank &RegBank) { - const auto &Registers = RegBank.getRegisters(); // The Register EnumValue is one greater than its index into Registers. @@ -1756,8 +1788,7 @@ void CodeGenRegBank::computeRegUnitSets() { std::vector<unsigned> RUSets; for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) { RegUnitSet &RUSet = RegUnitSets[i]; - if (std::find(RUSet.Units.begin(), RUSet.Units.end(), UnitIdx) - == RUSet.Units.end()) + if (!is_contained(RUSet.Units, UnitIdx)) continue; RUSets.push_back(i); } @@ -1781,7 +1812,8 @@ void CodeGenRegBank::computeRegUnitLaneMasks() { for (auto &Register : Registers) { // Create an initial lane mask for all register units. const auto &RegUnits = Register.getRegUnits(); - CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.count(), 0); + CodeGenRegister::RegUnitLaneMaskList + RegUnitLaneMasks(RegUnits.count(), LaneBitmask::getNone()); // Iterate through SubRegisters. typedef CodeGenRegister::SubRegMap SubRegMap; const SubRegMap &SubRegs = Register.getSubRegs(); @@ -1790,11 +1822,11 @@ void CodeGenRegBank::computeRegUnitLaneMasks() { CodeGenRegister *SubReg = S->second; // Ignore non-leaf subregisters, their lane masks are fully covered by // the leaf subregisters anyway. - if (SubReg->getSubRegs().size() != 0) + if (!SubReg->getSubRegs().empty()) continue; CodeGenSubRegIndex *SubRegIndex = S->first; const CodeGenRegister *SubRegister = S->second; - unsigned LaneMask = SubRegIndex->LaneMask; + LaneBitmask LaneMask = SubRegIndex->LaneMask; // Distribute LaneMask to Register Units touched. for (unsigned SUI : SubRegister->getRegUnits()) { bool Found = false; @@ -2009,7 +2041,6 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, } } - // // Infer missing register classes. // diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index b8d47aa..3ed26fa 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -18,20 +18,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" -#include <cstdlib> +#include <cassert> +#include <cstdint> #include <deque> #include <list> #include <map> #include <string> +#include <utility> #include <vector> namespace llvm { + class CodeGenRegBank; template <typename T, typename Vector, typename Set> class SetVector; @@ -39,8 +48,9 @@ namespace llvm { /// Mask the bits specified in Mask, then rotate them Rol bits to the left /// assuming a wraparound at 32bits. struct MaskRolPair { - unsigned Mask; + LaneBitmask Mask; uint8_t RotateLeft; + bool operator==(const MaskRolPair Other) const { return Mask == Other.Mask && RotateLeft == Other.RotateLeft; } @@ -59,7 +69,7 @@ namespace llvm { uint16_t Size; uint16_t Offset; const unsigned EnumValue; - mutable unsigned LaneMask; + mutable LaneBitmask LaneMask; mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform; // Are all super-registers containing this SubRegIndex covered by their @@ -111,7 +121,7 @@ namespace llvm { const CompMap &getComposites() const { return Composed; } // Compute LaneMask from Composed. Return LaneMask. - unsigned computeLaneMask() const; + LaneBitmask computeLaneMask() const; private: CompMap Composed; @@ -136,7 +146,7 @@ namespace llvm { CodeGenRegister(Record *R, unsigned Enum); - const std::string &getName() const; + const StringRef getName() const; // Extract more information from TheDef. This is used to build an object // graph after all CodeGenRegister objects have been created. @@ -197,7 +207,7 @@ namespace llvm { // List of register units in ascending order. typedef SparseBitVector<> RegUnitList; - typedef SmallVector<unsigned, 16> RegUnitLaneMaskList; + typedef SmallVector<LaneBitmask, 16> RegUnitLaneMaskList; // How many entries in RegUnitList are native? RegUnitList NativeRegUnits; @@ -206,7 +216,7 @@ namespace llvm { // This is only valid after computeSubRegs() completes. const RegUnitList &getRegUnits() const { return RegUnits; } - ArrayRef<unsigned> getRegUnitLaneMasks() const { + ArrayRef<LaneBitmask> getRegUnitLaneMasks() const { return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count()); } @@ -266,7 +276,7 @@ namespace llvm { class CodeGenRegisterClass { CodeGenRegister::Vec Members; // Allocation orders. Order[0] always contains all registers in Members. - std::vector<SmallVector<Record*, 16> > Orders; + std::vector<SmallVector<Record*, 16>> Orders; // Bit mask of sub-classes including this, indexed by their EnumValue. BitVector SubClasses; // List of super-classes, topologocally ordered to have the larger classes @@ -307,7 +317,7 @@ namespace llvm { std::string AltOrderSelect; uint8_t AllocationPriority; /// Contains the combination of the lane masks of all subregisters. - unsigned LaneMask; + LaneBitmask LaneMask; /// True if there are at least 2 subregisters which do not interfere. bool HasDisjunctSubRegs; bool CoveredBySubRegs; @@ -463,10 +473,10 @@ namespace llvm { std::string Name; std::vector<unsigned> Units; - unsigned Weight; // Cache the sum of all unit weights. - unsigned Order; // Cache the sort key. + unsigned Weight = 0; // Cache the sum of all unit weights. + unsigned Order = 0; // Cache the sort key. - RegUnitSet() : Weight(0), Order(0) {} + RegUnitSet() = default; }; // Base vector for identifying TopoSigs. The contents uniquely identify a @@ -515,7 +525,7 @@ namespace llvm { // NOTE: This could grow beyond the number of register classes when we map // register units to lists of unit sets. If the list of unit sets does not // already exist for a register class, we create a new entry in this vector. - std::vector<std::vector<unsigned> > RegClassUnitSets; + std::vector<std::vector<unsigned>> RegClassUnitSets; // Give each register unit set an order based on sorting criteria. std::vector<unsigned> RegUnitSetOrder; @@ -532,6 +542,7 @@ namespace llvm { void computeInferredRegisterClasses(); void inferCommonSubClass(CodeGenRegisterClass *RC); void inferSubClassWithSubReg(CodeGenRegisterClass *RC); + void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) { inferMatchingSuperRegClass(RC, RegClasses.begin()); } @@ -590,6 +601,7 @@ namespace llvm { } const std::deque<CodeGenRegister> &getRegisters() { return Registers; } + const StringMap<CodeGenRegister*> &getRegistersByName() { return RegistersByName; } @@ -674,6 +686,7 @@ namespace llvm { unsigned getRegSetIDAt(unsigned Order) const { return RegUnitSetOrder[Order]; } + const RegUnitSet &getRegSetAt(unsigned Order) const { return RegUnitSets[RegUnitSetOrder[Order]]; } @@ -721,8 +734,9 @@ namespace llvm { // Bit mask of lanes that cover their registers. A sub-register index whose // LaneMask is contained in CoveringLanes will be completely covered by // another sub-register with the same or larger lane mask. - unsigned CoveringLanes; + LaneBitmask CoveringLanes; }; -} -#endif +} // end namespace llvm + +#endif // LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp index d1b141e..cae1cf4 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -12,12 +12,21 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenInstruction.h" #include "CodeGenSchedule.h" #include "CodeGenTarget.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Regex.h" #include "llvm/TableGen/Error.h" +#include <algorithm> +#include <iterator> +#include <utility> using namespace llvm; @@ -31,6 +40,7 @@ static void dumpIdxVec(ArrayRef<unsigned> V) { #endif namespace { + // (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp. struct InstrsOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, @@ -76,6 +86,7 @@ struct InstRegexOp : public SetTheory::Operator { } } }; + } // end anonymous namespace /// CodeGenModels ctor interprets machine model records and populates maps. @@ -356,8 +367,7 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const { continue; RecVec ValidWrites = ReadDef->getValueAsListOfDefs("ValidWrites"); - if (std::find(ValidWrites.begin(), ValidWrites.end(), WriteDef) - != ValidWrites.end()) { + if (is_contained(ValidWrites, WriteDef)) { return true; } } @@ -365,6 +375,7 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const { } namespace llvm { + void splitSchedReadWrites(const RecVec &RWDefs, RecVec &WriteDefs, RecVec &ReadDefs) { for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) { @@ -376,7 +387,8 @@ void splitSchedReadWrites(const RecVec &RWDefs, } } } -} // namespace llvm + +} // end namespace llvm // Split the SchedReadWrites defs and call findRWs for each list. void CodeGenSchedModels::findRWs(const RecVec &RWDefs, @@ -574,11 +586,14 @@ void CodeGenSchedModels::collectSchedClasses() { dbgs() << " " << SchedReads[*RI].Name; dbgs() << '\n'; } - for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), - PE = ProcModels.end(); PI != PE; ++PI) { - if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) - dbgs() << "No machine model for " << Inst->TheDef->getName() - << " on processor " << PI->ModelName << '\n'; + // If ProcIndices contains zero, the class applies to all processors. + if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) { + for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), + PE = ProcModels.end(); PI != PE; ++PI) { + if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) + dbgs() << "No machine model for " << Inst->TheDef->getName() + << " on processor " << PI->ModelName << '\n'; + } } } } @@ -674,7 +689,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { // intersects with an existing class via a previous InstRWDef. Instrs that do // not intersect with an existing class refer back to their former class as // determined from ItinDef or SchedRW. - SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs; + SmallVector<std::pair<unsigned, SmallVector<Record *, 8>>, 4> ClassInstrs; // Sort Instrs into sets. const RecVec *InstDefs = Sets.expand(InstRWDef); if (InstDefs->empty()) @@ -913,6 +928,7 @@ void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) { } namespace { + // Helper for substituteVariantOperand. struct TransVariant { Record *VarOrSeqDef; // Variant or sequence. @@ -969,7 +985,8 @@ private: std::vector<TransVariant> &IntersectingVariants); void pushVariant(const TransVariant &VInfo, bool IsRead); }; -} // anonymous + +} // end anonymous namespace // Return true if this predicate is mutually exclusive with a PredTerm. This // degenerates into checking if the predicate is mutually exclusive with any @@ -982,7 +999,6 @@ private: // conditions implicitly negate any prior condition. bool PredTransitions::mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term) { - for (ArrayRef<PredCheck>::iterator I = Term.begin(), E = Term.end(); I != E; ++I) { if (I->Predicate == PredDef) @@ -1029,7 +1045,7 @@ static bool hasVariant(ArrayRef<PredTransition> Transitions, for (ArrayRef<PredTransition>::iterator PTI = Transitions.begin(), PTE = Transitions.end(); PTI != PTE; ++PTI) { - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end(); WSI != WSE; ++WSI) { for (SmallVectorImpl<unsigned>::const_iterator @@ -1038,7 +1054,7 @@ static bool hasVariant(ArrayRef<PredTransition> Transitions, return true; } } - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end(); RSI != RSE; ++RSI) { for (SmallVectorImpl<unsigned>::const_iterator @@ -1145,7 +1161,6 @@ void PredTransitions::getIntersectingVariants( // specified by VInfo. void PredTransitions:: pushVariant(const TransVariant &VInfo, bool IsRead) { - PredTransition &Trans = TransVec[VInfo.TransVecIdx]; // If this operand transition is reached through a processor-specific alias, @@ -1168,7 +1183,7 @@ pushVariant(const TransVariant &VInfo, bool IsRead) { const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead); - SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead + SmallVectorImpl<SmallVector<unsigned,4>> &RWSequences = IsRead ? Trans.ReadSequences : Trans.WriteSequences; if (SchedRW.IsVariadic) { unsigned OperIdx = RWSequences.size()-1; @@ -1264,7 +1279,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) { TransVec.back().ProcIndices = Trans.ProcIndices; // Visit each original write sequence. - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end(); WSI != WSE; ++WSI) { // Push a new (empty) write sequence onto all partial Transitions. @@ -1275,7 +1290,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) { substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx); } // Visit each original read sequence. - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end(); RSI != RSE; ++RSI) { // Push a new (empty) read sequence onto all partial Transitions. @@ -1296,7 +1311,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, for (ArrayRef<PredTransition>::iterator I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) { IdxVec OperWritesVariant; - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end(); WSI != WSE; ++WSI) { // Create a new write representing the expanded sequence. @@ -1304,7 +1319,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false)); } IdxVec OperReadsVariant; - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end(); RSI != RSE; ++RSI) { // Create a new read representing the expanded sequence. @@ -1400,8 +1415,7 @@ bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) { PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources"); RecIter RI = SubUnits.begin(), RE = SubUnits.end(); for ( ; RI != RE; ++RI) { - if (std::find(SuperUnits.begin(), SuperUnits.end(), *RI) - == SuperUnits.end()) { + if (!is_contained(SuperUnits, *RI)) { break; } } @@ -1500,9 +1514,7 @@ void CodeGenSchedModels::collectProcResources() { if (!(*RI)->getValueInit("SchedModel")->isComplete()) continue; CodeGenProcModel &PM = getProcModel((*RI)->getValueAsDef("SchedModel")); - RecIter I = std::find(PM.ProcResourceDefs.begin(), - PM.ProcResourceDefs.end(), *RI); - if (I == PM.ProcResourceDefs.end()) + if (!is_contained(PM.ProcResourceDefs, *RI)) PM.ProcResourceDefs.push_back(*RI); } // Finalize each ProcModel by sorting the record arrays. @@ -1568,15 +1580,14 @@ void CodeGenSchedModels::checkCompleteness() { const CodeGenSchedClass &SC = getSchedClass(SCIdx); if (!SC.Writes.empty()) continue; - if (SC.ItinClassDef != nullptr) + if (SC.ItinClassDef != nullptr && + SC.ItinClassDef->getName() != "NoItinerary") continue; const RecVec &InstRWs = SC.InstRWs; - auto I = std::find_if(InstRWs.begin(), InstRWs.end(), - [&ProcModel] (const Record *R) { - return R->getValueAsDef("SchedModel") == - ProcModel.ModelDef; - }); + auto I = find_if(InstRWs, [&ProcModel](const Record *R) { + return R->getValueAsDef("SchedModel") == ProcModel.ModelDef; + }); if (I == InstRWs.end()) { PrintError("'" + ProcModel.ModelName + "' lacks information for '" + Inst->TheDef->getName() + "'"); @@ -1660,7 +1671,6 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead, void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads, ArrayRef<unsigned> ProcIndices) { - for (unsigned Idx : Writes) collectRWResources(Idx, /*IsRead=*/false, ProcIndices); @@ -1668,7 +1678,6 @@ void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes, collectRWResources(Idx, /*IsRead=*/true, ProcIndices); } - // Find the processor's resource units for this kind of resource. Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM) const { @@ -1716,13 +1725,11 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, // Iteratively add a resource and its super resources. void CodeGenSchedModels::addProcResource(Record *ProcResKind, CodeGenProcModel &PM) { - for (;;) { + while (true) { Record *ProcResUnits = findProcResUnits(ProcResKind, PM); // See if this ProcResource is already associated with this processor. - RecIter I = std::find(PM.ProcResourceDefs.begin(), - PM.ProcResourceDefs.end(), ProcResUnits); - if (I != PM.ProcResourceDefs.end()) + if (is_contained(PM.ProcResourceDefs, ProcResUnits)) return; PM.ProcResourceDefs.push_back(ProcResUnits); @@ -1741,8 +1748,7 @@ void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) { assert(PIdx && "don't add resources to an invalid Processor model"); RecVec &WRDefs = ProcModels[PIdx].WriteResDefs; - RecIter WRI = std::find(WRDefs.begin(), WRDefs.end(), ProcWriteResDef); - if (WRI != WRDefs.end()) + if (is_contained(WRDefs, ProcWriteResDef)) return; WRDefs.push_back(ProcWriteResDef); @@ -1758,15 +1764,13 @@ void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) { void CodeGenSchedModels::addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx) { RecVec &RADefs = ProcModels[PIdx].ReadAdvanceDefs; - RecIter I = std::find(RADefs.begin(), RADefs.end(), ProcReadAdvanceDef); - if (I != RADefs.end()) + if (is_contained(RADefs, ProcReadAdvanceDef)) return; RADefs.push_back(ProcReadAdvanceDef); } unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const { - RecIter PRPos = std::find(ProcResourceDefs.begin(), ProcResourceDefs.end(), - PRDef); + RecIter PRPos = find(ProcResourceDefs, PRDef); if (PRPos == ProcResourceDefs.end()) PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in " "the ProcResources list for " + ModelName); @@ -1842,7 +1846,7 @@ void PredTransitions::dump() const { << ":" << PCI->Predicate->getName(); } dbgs() << "},\n => {"; - for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator + for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end(); WSI != WSE; ++WSI) { dbgs() << "("; diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index 245b9ee..6503d5a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -138,7 +138,7 @@ std::string llvm::getQualifiedName(const Record *R) { if (R->getValue("Namespace")) Namespace = R->getValueAsString("Namespace"); if (Namespace.empty()) return R->getName(); - return Namespace + "::" + R->getName(); + return Namespace + "::" + R->getName().str(); } @@ -157,7 +157,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) CodeGenTarget::~CodeGenTarget() { } -const std::string &CodeGenTarget::getName() const { +const StringRef CodeGenTarget::getName() const { return TargetRec->getName(); } @@ -301,7 +301,7 @@ GetInstByName(const char *Name, /// their enum value. void CodeGenTarget::ComputeInstrsByEnum() const { static const char *const FixedInstrs[] = { -#define HANDLE_TARGET_OPCODE(OPC, NUM) #OPC, +#define HANDLE_TARGET_OPCODE(OPC) #OPC, #include "llvm/Target/TargetOpcodes.def" nullptr}; const auto &Insts = getInstructions(); @@ -393,6 +393,16 @@ ComplexPattern::ComplexPattern(Record *R) { SelectFunc = R->getValueAsString("SelectFunc"); RootNodes = R->getValueAsListOfDefs("RootNodes"); + // FIXME: This is a hack to statically increase the priority of patterns which + // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best + // possible pattern match we'll need to dynamically calculate the complexity + // of all patterns a dag can potentially map to. + int64_t RawComplexity = R->getValueAsInt("Complexity"); + if (RawComplexity == -1) + Complexity = NumOperands * 3; + else + Complexity = RawComplexity; + // Parse the properties. Properties = 0; std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); @@ -550,8 +560,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && !TyEl->isSubClassOf("LLVMTruncatedType") && - !TyEl->isSubClassOf("LLVMVectorSameWidth") && - !TyEl->isSubClassOf("LLVMPointerToElt")) || + !TyEl->isSubClassOf("LLVMVectorSameWidth")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else @@ -584,7 +593,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { else if (Property->getName() == "IntrWriteMem") ModRef = ModRefBehavior(ModRef & ~MR_Ref); else if (Property->getName() == "IntrArgMemOnly") - ModRef = ModRefBehavior(ModRef & ~MR_Anywhere); + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem); + else if (Property->getName() == "IntrInaccessibleMemOnly") + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem); + else if (Property->getName() == "IntrInaccessibleMemOrArgMemOnly") + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem | + MR_InaccessibleMem); else if (Property->getName() == "Commutative") isCommutative = true; else if (Property->getName() == "Throws") diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index 85a8c1b..c822e94 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -82,7 +82,7 @@ public: ~CodeGenTarget(); Record *getTargetRecord() const { return TargetRec; } - const std::string &getName() const; + const StringRef getName() const; /// getInstNamespace - Return the target-specific instruction namespace. /// @@ -139,7 +139,7 @@ public: /// supported by the target (i.e. there are registers that directly hold it). bool isLegalValueType(MVT::SimpleValueType VT) const { ArrayRef<MVT::SimpleValueType> LegalVTs = getLegalValueTypes(); - return std::find(LegalVTs.begin(), LegalVTs.end(), VT) != LegalVTs.end(); + return is_contained(LegalVTs, VT); } CodeGenSchedModels &getSchedModels() const; @@ -196,8 +196,8 @@ class ComplexPattern { std::string SelectFunc; std::vector<Record*> RootNodes; unsigned Properties; // Node properties + unsigned Complexity; public: - ComplexPattern() : NumOperands(0) {} ComplexPattern(Record *R); MVT::SimpleValueType getValueType() const { return Ty; } @@ -207,6 +207,7 @@ public: return RootNodes; } bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } + unsigned getComplexity() const { return Complexity; } }; } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp index 0fe3bbd..60fe866 100644 --- a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp @@ -121,7 +121,7 @@ struct PatternSortingPredicate { void DAGISelEmitter::run(raw_ostream &OS) { emitSourceFileHeader("DAG Instruction Selector for the " + - CGP.getTargetInfo().getName() + " target", OS); + CGP.getTargetInfo().getName().str() + " target", OS); OS << "// *** NOTE: This file is #included into the middle of the target\n" << "// *** instruction selector class. These functions are really " diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 4110e97..aafc115 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -250,7 +250,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { // If we have a physreg reference like (mul gpr:$src, EAX) then we need to // record the register if (LeafRec->isSubClassOf("Register")) { - AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(), + AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName().str(), NextRecordedOperandNo)); PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++)); return; @@ -354,7 +354,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, unsigned OpNo = 0; if (N->NodeHasProperty(SDNPHasChain, CGP)) { // Record the node and remember it in our chained nodes list. - AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() + + AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() + "' chained node", NextRecordedOperandNo)); // Remember all of the input chains our pattern will match. @@ -418,7 +418,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // TODO: This redundantly records nodes with both glues and chains. // Record the node and remember it in our chained nodes list. - AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() + + AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() + "' glue output node", NextRecordedOperandNo)); } @@ -887,7 +887,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) && "Node has no result"); - AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), + AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName().str(), ResultVTs, InstOps, NodeHasChain, TreeHasInGlue, TreeHasOutGlue, NodeHasMemRefs, NumFixedArityOperands, diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp index ad385fa..783b35e 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -200,8 +200,15 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { std::unique_ptr<Matcher> Child(Scope->takeChild(i)); FactorNodes(Child); - if (Matcher *N = Child.release()) - OptionsToMatch.push_back(N); + if (Child) { + // If the child is a ScopeMatcher we can just merge its contents. + if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) { + for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j) + OptionsToMatch.push_back(SM->takeChild(j)); + } else { + OptionsToMatch.push_back(Child.release()); + } + } } SmallVector<Matcher*, 32> NewOptionsToMatch; @@ -414,9 +421,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { } Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM }; - std::unique_ptr<Matcher> Case(new ScopeMatcher(Entries)); - FactorNodes(Case); - Cases[Entry-1].second = Case.release(); + Cases[Entry-1].second = new ScopeMatcher(Entries); continue; } @@ -424,6 +429,16 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM)); } + // Make sure we recursively factor any scopes we may have created. + for (auto &M : Cases) { + if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) { + std::unique_ptr<Matcher> Scope(SM); + FactorNodes(Scope); + M.second = Scope.release(); + assert(M.second && "null matcher"); + } + } + if (Cases.size() != 1) { MatcherPtr.reset(new SwitchTypeMatcher(Cases)); } else { diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp index e31caaf..f879a5b 100644 --- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -19,14 +19,18 @@ #include "CodeGenTarget.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> #include <map> +#include <set> #include <string> -#include <queue> +#include <vector> using namespace llvm; @@ -58,6 +62,7 @@ typedef int64_t DFAStateInput; #define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable. namespace { + DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) { return (Inp << DFA_MAX_RESOURCES) | FuncUnits; } @@ -67,12 +72,13 @@ namespace { /// DFAPacketizerEmitter.cpp. DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) { DFAInput InsnInput = 0; - assert ((InsnClass.size() <= DFA_MAX_RESTERMS) && - "Exceeded maximum number of DFA terms"); + assert((InsnClass.size() <= DFA_MAX_RESTERMS) && + "Exceeded maximum number of DFA terms"); for (auto U : InsnClass) InsnInput = addDFAFuncUnits(InsnInput, U); return InsnInput; } + } // end anonymous namespace // -------------------------------------------------------------------- @@ -98,6 +104,7 @@ void dbgsIndent(unsigned indent); // for resource tracking. // namespace { + class DFAPacketizerEmitter { private: std::string TargetName; @@ -150,10 +157,8 @@ public: void run(raw_ostream &OS); }; -} // end anonymous namespace // -// // State represents the usage of machine resources if the packet contains // a set of instruction classes. // @@ -174,7 +179,6 @@ public: // A State instance also contains a collection of transitions from that state: // a map from inputs to new states. // -namespace { class State { public: static int currentStateNum; @@ -204,6 +208,7 @@ class State { // bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass, std::map<unsigned, unsigned> &ComboBitToBitsMap) const; + // // AddInsnClass - Return all combinations of resource reservation // which are possible from this state (PossibleStates). @@ -214,6 +219,7 @@ class State { void AddInsnClass(std::vector<unsigned> &InsnClass, std::map<unsigned, unsigned> &ComboBitToBitsMap, std::set<unsigned> &PossibleStates) const; + // // AddInsnClassStages - Return all combinations of resource reservation // resulting from the cross product of all stages for this InsnClass @@ -225,31 +231,31 @@ class State { unsigned prevState, unsigned origState, DenseSet<unsigned> &VisitedResourceStates, std::set<unsigned> &PossibleStates) const; + // // addTransition - Add a transition from this state given the input InsnClass // void addTransition(std::vector<unsigned> InsnClass, const State *To) const; + // // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // bool hasTransition(std::vector<unsigned> InsnClass) const; }; -} // end anonymous namespace // // class DFA: deterministic finite automaton for processor resource tracking. // -namespace { class DFA { public: - DFA(); + DFA() = default; // Set of states. Need to keep this sorted to emit the transition table. typedef std::set<State> StateSet; StateSet states; - State *currentState; + State *currentState = nullptr; // // Modify the DFA. @@ -263,6 +269,7 @@ public: int numInsnClasses = 0, int maxResources = 0, int numCombos = 0, int maxStages = 0); }; + } // end anonymous namespace #ifndef NDEBUG @@ -314,8 +321,6 @@ void dbgsIndent(unsigned indent) { State::State() : stateNum(currentStateNum++), isInitial(false) {} -DFA::DFA(): currentState(nullptr) {} - // // addTransition - Add a transition from this state given the input InsnClass // @@ -370,7 +375,6 @@ void State::AddInsnClassStages(std::vector<unsigned> &InsnClass, unsigned prevState, unsigned origState, DenseSet<unsigned> &VisitedResourceStates, std::set<unsigned> &PossibleStates) const { - assert((chkstage < numstages) && "AddInsnClassStages: stage out of range"); unsigned thisStage = InsnClass[chkstage]; @@ -469,7 +473,6 @@ bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass, std::map<unsigned, unsigned> &ComboBitToBitsMap) const { for (std::set<unsigned>::const_iterator SI = stateInfo.begin(); SI != stateInfo.end(); ++SI) { - // Check to see if all required resources are available. bool available = true; @@ -514,8 +517,7 @@ const State &DFA::newState() { int State::currentStateNum = 0; DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): - TargetName(CodeGenTarget(R).getName()), - allInsnClasses(), Records(R) {} + TargetName(CodeGenTarget(R).getName()), Records(R) {} // // writeTableAndAPI - Print out a table representing the DFA and the @@ -531,7 +533,6 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName, int numInsnClasses, int maxResources, int numCombos, int maxStages) { - unsigned numStates = states.size(); DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"); @@ -783,7 +784,7 @@ int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName, DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n"); } - if (UnitBits.size() > 0) + if (!UnitBits.empty()) allInsnClasses.push_back(UnitBits); DEBUG({ @@ -831,7 +832,6 @@ int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName, // Run the worklist algorithm to generate the DFA. // void DFAPacketizerEmitter::run(raw_ostream &OS) { - // Collect processor iteraries. std::vector<Record*> ProcItinList = Records.getAllDerivedDefinitions("ProcessorItineraries"); @@ -890,7 +890,6 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { Initial->isInitial = true; Initial->stateInfo.insert(0x0); SmallVector<const State*, 32> WorkList; -// std::queue<State*> WorkList; std::map<std::set<unsigned>, const State*> Visited; WorkList.push_back(Initial); @@ -937,7 +936,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) { const State *NewState = nullptr; current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources); - if (NewStateResources.size() == 0) { + if (NewStateResources.empty()) { DEBUG(dbgs() << " Skipped - no new states generated\n"); continue; } @@ -989,4 +988,4 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) { DFAPacketizerEmitter(RK).run(OS); } -} // end namespaec llvm +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index 44815b0..6e1d8dd 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -104,7 +104,7 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS, void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { CodeGenTarget Target(Records); - emitSourceFileHeader(" * " + Target.getName() + " Disassembler", OS); + emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS); // X86 uses a custom disassembler. if (Target.getName() == "X86") { diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp index debb12c..43c6a98 100644 --- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp @@ -564,8 +564,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true); SuffixOS.flush(); if (!StringSwitch<bool>(ManglingSuffix) - .Cases("", "r", "rr", "ri", "rf", true) - .Cases("rri", "i", "f", true) + .Cases("", "r", "rr", "ri", "i", "f", true) .Default(false)) continue; @@ -874,7 +873,7 @@ void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) { CodeGenDAGPatterns CGP(RK); const CodeGenTarget &Target = CGP.getTargetInfo(); emitSourceFileHeader("\"Fast\" Instruction Selector for the " + - Target.getName() + " target", OS); + Target.getName().str() + " target", OS); // Determine the target's namespace name. std::string InstNS = Target.getInstNamespace() + "::"; diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 0506400..e1aaecc 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -12,21 +12,32 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenInstruction.h" #include "CodeGenTarget.h" #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/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" #include "llvm/MC/MCFixedLenDisassembler.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <map> +#include <memory> +#include <set> #include <string> #include <utility> #include <vector> @@ -36,6 +47,7 @@ using namespace llvm; #define DEBUG_TYPE "decoder-emitter" namespace { + struct EncodingField { unsigned Base, Width, Offset; EncodingField(unsigned B, unsigned W, unsigned O) @@ -66,8 +78,8 @@ typedef std::vector<uint8_t> DecoderTable; typedef uint32_t DecoderFixup; typedef std::vector<DecoderFixup> FixupList; typedef std::vector<FixupList> FixupScopeList; -typedef SmallSetVector<std::string, 16> PredicateSet; -typedef SmallSetVector<std::string, 16> DecoderSet; +typedef SmallSetVector<CachedHashString, 16> PredicateSet; +typedef SmallSetVector<CachedHashString, 16> DecoderSet; struct DecoderTableInfo { DecoderTable Table; FixupScopeList FixupStack; @@ -75,13 +87,10 @@ struct DecoderTableInfo { DecoderSet Decoders; }; -} // End anonymous namespace - -namespace { class FixedLenDecoderEmitter { ArrayRef<const CodeGenInstruction *> NumberedInstructions; -public: +public: // Defaults preserved here for documentation, even though they aren't // strictly necessary given the way that this is currently being called. FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace, @@ -111,13 +120,15 @@ public: private: CodeGenTarget Target; + public: std::string PredicateNamespace; std::string GuardPrefix, GuardPostfix; std::string ReturnOK, ReturnFail; std::string Locals; }; -} // End anonymous namespace + +} // end anonymous namespace // The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system // for a bit value. @@ -134,12 +145,15 @@ typedef enum { static bool ValueSet(bit_value_t V) { return (V == BIT_TRUE || V == BIT_FALSE); } + static bool ValueNotSet(bit_value_t V) { return (V == BIT_UNSET); } + static int Value(bit_value_t V) { return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1); } + static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) { if (BitInit *bit = dyn_cast<BitInit>(bits.getBit(index))) return bit->getValue() ? BIT_TRUE : BIT_FALSE; @@ -147,6 +161,7 @@ static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) { // The bit is uninitialized. return BIT_UNSET; } + // Prints the bit value for each position. static void dumpBits(raw_ostream &o, const BitsInit &bits) { for (unsigned index = bits.getNumBits(); index > 0; --index) { @@ -166,19 +181,18 @@ static void dumpBits(raw_ostream &o, const BitsInit &bits) { } } -static BitsInit &getBitsField(const Record &def, const char *str) { +static BitsInit &getBitsField(const Record &def, StringRef str) { BitsInit *bits = def.getValueAsBitsInit(str); return *bits; } -// Forward declaration. -namespace { -class FilterChooser; -} // End anonymous namespace - // Representation of the instruction to work on. typedef std::vector<bit_value_t> insn_t; +namespace { + +class FilterChooser; + /// Filter - Filter works with FilterChooser to produce the decoding tree for /// the ISA. /// @@ -215,7 +229,6 @@ typedef std::vector<bit_value_t> insn_t; /// decoder could try to decode the even/odd register numbering and assign to /// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a" /// version and return the Opcode since the two have the same Asm format string. -namespace { class Filter { protected: const FilterChooser *Owner;// points to the FilterChooser who owns this filter @@ -224,7 +237,7 @@ 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<unsigned>> FilteredInstructions; // Set of uid's with non-constant segment values. std::vector<unsigned> VariableInstructions; @@ -239,11 +252,18 @@ protected: unsigned LastOpcFiltered; public: + Filter(Filter &&f); + Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); + + ~Filter() = default; + unsigned getNumFiltered() const { return NumFiltered; } + unsigned getSingletonOpc() const { assert(NumFiltered == 1); return LastOpcFiltered; } + // Return the filter chooser for the group of instructions without constant // segment values. const FilterChooser &getVariableFC() const { @@ -252,11 +272,6 @@ public: return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(Filter &&f); - Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); - - ~Filter(); - // Divides the decoding task into sub tasks and delegates them to the // inferior FilterChooser's. // @@ -272,8 +287,9 @@ public: // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. unsigned usefulness() const; -}; // End of class Filter -} // End anonymous namespace +}; // end class Filter + +} // end anonymous namespace // These are states of our finite state machines used in FilterChooser's // filterProcessor() which produces the filter candidates to use. @@ -301,6 +317,7 @@ typedef enum { /// decoding tree. And each case is delegated to an inferior FilterChooser to /// decide what further remaining bits to look at. namespace { + class FilterChooser { protected: friend class Filter; @@ -312,7 +329,7 @@ protected: const std::vector<unsigned> &Opcodes; // Lookup table for the operand decoding of instructions. - const std::map<unsigned, std::vector<OperandInfo> > &Operands; + const std::map<unsigned, std::vector<OperandInfo>> &Operands; // Vector of candidate filters. std::vector<Filter> Filters; @@ -333,16 +350,13 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; - FilterChooser(const FilterChooser &) = delete; - void operator=(const FilterChooser &) = delete; public: - FilterChooser(ArrayRef<const CodeGenInstruction *> Insts, const std::vector<unsigned> &IDs, - const std::map<unsigned, std::vector<OperandInfo> > &Ops, + const std::map<unsigned, std::vector<OperandInfo>> &Ops, unsigned BW, const FixedLenDecoderEmitter *E) - : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), + : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { doFilter(); @@ -350,16 +364,18 @@ public: FilterChooser(ArrayRef<const CodeGenInstruction *> Insts, const std::vector<unsigned> &IDs, - const std::map<unsigned, std::vector<OperandInfo> > &Ops, + const std::map<unsigned, std::vector<OperandInfo>> &Ops, const std::vector<bit_value_t> &ParentFilterBitValues, const FilterChooser &parent) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), - Filters(), FilterBitValues(ParentFilterBitValues), - Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth), - Emitter(parent.Emitter) { + FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1), + BitWidth(parent.BitWidth), Emitter(parent.Emitter) { doFilter(); } + FilterChooser(const FilterChooser &) = delete; + void operator=(const FilterChooser &) = delete; + unsigned getBitWidth() const { return BitWidth; } protected: @@ -384,7 +400,7 @@ protected: } // Returns the record name. - const std::string &nameWithID(unsigned Opcode) const { + const StringRef nameWithID(unsigned Opcode) const { return AllInstructions[Opcode]->TheDef->getName(); } @@ -476,7 +492,8 @@ public: // instructions. void emitTableEntries(DecoderTableInfo &TableInfo) const; }; -} // End anonymous namespace + +} // end anonymous namespace /////////////////////////// // // @@ -527,9 +544,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, && "Filter returns no instruction categories"); } -Filter::~Filter() { -} - // Divides the decoding task into sub tasks and delegates them to the // inferior FilterChooser's. // @@ -1071,7 +1085,7 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, for (const auto &Op : Operands.find(Opc)->second) { // If a custom instruction decoder was specified, use that. - if (Op.numFields() == 0 && Op.Decoder.size()) { + if (Op.numFields() == 0 && !Op.Decoder.empty()) { HasCompleteDecoder = Op.HasCompleteDecoder; OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder << "(MI, insn, Address, Decoder)" @@ -1106,11 +1120,9 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, // overkill for now, though. // Make sure the predicate is in the table. - Decoders.insert(StringRef(Decoder)); + Decoders.insert(CachedHashString(Decoder)); // Now figure out the index for when we write out the table. - DecoderSet::const_iterator P = std::find(Decoders.begin(), - Decoders.end(), - Decoder.str()); + DecoderSet::const_iterator P = find(Decoders, Decoder.str()); return (unsigned)(P - Decoders.begin()); } @@ -1143,7 +1155,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, StringRef SR(P); std::pair<StringRef, StringRef> pairs = SR.split(','); - while (pairs.second.size()) { + while (!pairs.second.empty()) { emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace); o << " && "; pairs = pairs.second.split(','); @@ -1181,11 +1193,9 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo, // overkill for now, though. // Make sure the predicate is in the table. - TableInfo.Predicates.insert(Predicate.str()); + TableInfo.Predicates.insert(CachedHashString(Predicate)); // Now figure out the index for when we write out the table. - PredicateSet::const_iterator P = std::find(TableInfo.Predicates.begin(), - TableInfo.Predicates.end(), - Predicate.str()); + PredicateSet::const_iterator P = find(TableInfo.Predicates, Predicate); return (unsigned)(P - TableInfo.Predicates.begin()); } @@ -1374,7 +1384,6 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, Best.getVariableFC().emitTableEntries(TableInfo); } - // Assign a single filter and run with it. Top level API client can initialize // with a single filter to start the filtering process. void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, @@ -1692,9 +1701,37 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const { } } +static std::string findOperandDecoderMethod(TypedInit *TI) { + std::string Decoder; + + RecordRecTy *Type = cast<RecordRecTy>(TI->getType()); + Record *TypeRecord = Type->getRecord(); + + RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); + StringInit *String = DecoderString ? + dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; + if (String) { + Decoder = String->getValue(); + if (!Decoder.empty()) + return Decoder; + } + + if (TypeRecord->isSubClassOf("RegisterOperand")) + TypeRecord = TypeRecord->getValueAsDef("RegClass"); + + if (TypeRecord->isSubClassOf("RegisterClass")) { + Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass"; + } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) { + Decoder = "DecodePointerLikeRegClass" + + utostr(TypeRecord->getValueAsInt("RegClassKind")); + } + + return Decoder; +} + static bool populateInstruction(CodeGenTarget &Target, const CodeGenInstruction &CGI, unsigned Opc, - std::map<unsigned, std::vector<OperandInfo> > &Operands){ + 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 @@ -1722,13 +1759,15 @@ static bool populateInstruction(CodeGenTarget &Target, // Gather the outputs/inputs of the instruction, so we can find their // positions in the encoding. This assumes for now that they appear in the // MCInst in the order that they're listed. - std::vector<std::pair<Init*, std::string> > InOutOperands; + std::vector<std::pair<Init*, StringRef>> InOutOperands; DagInit *Out = Def.getValueAsDag("OutOperandList"); DagInit *In = Def.getValueAsDag("InOperandList"); for (unsigned i = 0; i < Out->getNumArgs(); ++i) - InOutOperands.push_back(std::make_pair(Out->getArg(i), Out->getArgName(i))); + InOutOperands.push_back(std::make_pair(Out->getArg(i), + Out->getArgNameStr(i))); for (unsigned i = 0; i < In->getNumArgs(); ++i) - InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i))); + InOutOperands.push_back(std::make_pair(In->getArg(i), + In->getArgNameStr(i))); // Search for tied operands, so that we can correctly instantiate // operands that are not explicitly represented in the encoding. @@ -1743,7 +1782,7 @@ static bool populateInstruction(CodeGenTarget &Target, } } - std::map<std::string, std::vector<OperandInfo> > NumberedInsnOperands; + std::map<std::string, std::vector<OperandInfo>> NumberedInsnOperands; std::set<std::string> NumberedInsnOperandsNoTie; if (Target.getInstructionSet()-> getValueAsBit("decodePositionallyEncodedOperands")) { @@ -1828,7 +1867,7 @@ static bool populateInstruction(CodeGenTarget &Target, Name << "(" << SO.first << ", " << SO.second << ") => " << Vals[i].getName() << "\n"); - std::string Decoder = ""; + std::string Decoder; Record *TypeRecord = CGI.Operands[SO.first].Rec; RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); @@ -1852,7 +1891,7 @@ static bool populateInstruction(CodeGenTarget &Target, if (TypeRecord->isSubClassOf("RegisterOperand")) TypeRecord = TypeRecord->getValueAsDef("RegClass"); if (TypeRecord->isSubClassOf("RegisterClass")) { - Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; + Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass"; isReg = true; } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) { Decoder = "DecodePointerLikeRegClass" + @@ -1917,33 +1956,13 @@ static bool populateInstruction(CodeGenTarget &Target, continue; } - std::string Decoder = ""; - - // At this point, we can locate the field, but we need to know how to - // interpret it. As a first step, require the target to provide callbacks - // for decoding register classes. - // FIXME: This need to be extended to handle instructions with custom - // decoder methods, and operands with (simple) MIOperandInfo's. TypedInit *TI = cast<TypedInit>(Op.first); - RecordRecTy *Type = cast<RecordRecTy>(TI->getType()); - Record *TypeRecord = Type->getRecord(); - bool isReg = false; - if (TypeRecord->isSubClassOf("RegisterOperand")) - TypeRecord = TypeRecord->getValueAsDef("RegClass"); - if (TypeRecord->isSubClassOf("RegisterClass")) { - Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; - isReg = true; - } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) { - Decoder = "DecodePointerLikeRegClass" + - utostr(TypeRecord->getValueAsInt("RegClassKind")); - isReg = true; - } - RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); - StringInit *String = DecoderString ? - dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; - if (!isReg && String && String->getValue() != "") - Decoder = String->getValue(); + // At this point, we can locate the decoder field, but we need to know how + // to interpret it. As a first step, require the target to provide + // callbacks for decoding register classes. + std::string Decoder = findOperandDecoderMethod(TI); + Record *TypeRecord = cast<RecordRecTy>(TI->getType())->getRecord(); RecordVal *HasCompleteDecoderVal = TypeRecord->getValue("hasCompleteDecoder"); @@ -2009,7 +2028,6 @@ static bool populateInstruction(CodeGenTarget &Target, Operands[Opc] = InsnOperands; - #if 0 DEBUG({ // Dumps the instruction encoding bits. @@ -2062,7 +2080,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " const uint8_t *Ptr = DecodeTable;\n" << " uint32_t CurFieldValue = 0;\n" << " DecodeStatus S = MCDisassembler::Success;\n" - << " for (;;) {\n" + << " while (true) {\n" << " ptrdiff_t Loc = Ptr - DecodeTable;\n" << " switch (*Ptr) {\n" << " default:\n" @@ -2230,8 +2248,8 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { // Parameterize the decoders based on namespace and instruction width. NumberedInstructions = Target.getInstructionsByEnumValue(); std::map<std::pair<std::string, unsigned>, - std::vector<unsigned> > OpcMap; - std::map<unsigned, std::vector<OperandInfo> > Operands; + std::vector<unsigned>> OpcMap; + std::map<unsigned, std::vector<OperandInfo>> Operands; for (unsigned i = 0; i < NumberedInstructions.size(); ++i) { const CodeGenInstruction *Inst = NumberedInstructions[i]; @@ -2304,4 +2322,4 @@ void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS, ROK, RFail, L).run(OS); } -} // End llvm namespace +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp new file mode 100644 index 0000000..2bc6181 --- /dev/null +++ b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -0,0 +1,388 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This tablegen backend emits code for use by the GlobalISel instruction +/// selector. See include/llvm/CodeGen/TargetGlobalISel.td. +/// +/// This file analyzes the patterns recognized by the SelectionDAGISel tablegen +/// backend, filters out the ones that are unsupported, maps +/// SelectionDAG-specific constructs to their GlobalISel counterpart +/// (when applicable: MVT to LLT; SDNode to generic Instruction). +/// +/// Not all patterns are supported: pass the tablegen invocation +/// "-warn-on-skipped-patterns" to emit a warning when a pattern is skipped, +/// as well as why. +/// +/// The generated file defines a single method: +/// bool <Target>InstructionSelector::selectImpl(MachineInstr &I) const; +/// intended to be used in InstructionSelector::select as the first-step +/// selector for the patterns that don't require complex C++. +/// +/// FIXME: We'll probably want to eventually define a base +/// "TargetGenInstructionSelector" class. +/// +//===----------------------------------------------------------------------===// + +#include "CodeGenDAGPatterns.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <string> +using namespace llvm; + +#define DEBUG_TYPE "gisel-emitter" + +STATISTIC(NumPatternTotal, "Total number of patterns"); +STATISTIC(NumPatternSkipped, "Number of patterns skipped"); +STATISTIC(NumPatternEmitted, "Number of patterns emitted"); + +static cl::opt<bool> WarnOnSkippedPatterns( + "warn-on-skipped-patterns", + cl::desc("Explain why a pattern was skipped for inclusion " + "in the GlobalISel selector"), + cl::init(false)); + +namespace { + +class GlobalISelEmitter { +public: + explicit GlobalISelEmitter(RecordKeeper &RK); + void run(raw_ostream &OS); + +private: + const RecordKeeper &RK; + const CodeGenDAGPatterns CGP; + const CodeGenTarget &Target; + + /// Keep track of the equivalence between SDNodes and Instruction. + /// This is defined using 'GINodeEquiv' in the target description. + DenseMap<Record *, const CodeGenInstruction *> NodeEquivs; + + void gatherNodeEquivs(); + const CodeGenInstruction *findNodeEquiv(Record *N); + + struct SkipReason { + std::string Reason; + }; + + /// Analyze pattern \p P, possibly emitting matching code for it to \p OS. + /// Otherwise, return a reason why this pattern was skipped for emission. + Optional<SkipReason> runOnPattern(const PatternToMatch &P, + raw_ostream &OS); +}; + +} // end anonymous namespace + +//===- Helper functions ---------------------------------------------------===// + +/// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for +/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...). +static Optional<std::string> MVTToLLT(MVT::SimpleValueType SVT) { + std::string TyStr; + raw_string_ostream OS(TyStr); + MVT VT(SVT); + if (VT.isVector() && VT.getVectorNumElements() != 1) { + OS << "LLT::vector(" << VT.getVectorNumElements() << ", " + << VT.getScalarSizeInBits() << ")"; + } else if (VT.isInteger() || VT.isFloatingPoint()) { + OS << "LLT::scalar(" << VT.getSizeInBits() << ")"; + } else { + return None; + } + OS.flush(); + return TyStr; +} + +static bool isTrivialOperatorNode(const TreePatternNode *N) { + return !N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn(); +} + +//===- Matchers -----------------------------------------------------------===// + +struct Matcher { + virtual ~Matcher() {} + virtual void emit(raw_ostream &OS) const = 0; +}; + +raw_ostream &operator<<(raw_ostream &S, const Matcher &M) { + M.emit(S); + return S; +} + +struct MatchAction { + virtual ~MatchAction() {} + virtual void emit(raw_ostream &OS) const = 0; +}; + +raw_ostream &operator<<(raw_ostream &S, const MatchAction &A) { + A.emit(S); + return S; +} + +struct MatchOpcode : public Matcher { + MatchOpcode(const CodeGenInstruction *I) : I(I) {} + const CodeGenInstruction *I; + + virtual void emit(raw_ostream &OS) const { + OS << "I.getOpcode() == " << I->Namespace << "::" << I->TheDef->getName(); + } +}; + +struct MatchRegOpType : public Matcher { + MatchRegOpType(unsigned OpIdx, std::string Ty) + : OpIdx(OpIdx), Ty(Ty) {} + unsigned OpIdx; + std::string Ty; + + virtual void emit(raw_ostream &OS) const { + OS << "MRI.getType(I.getOperand(" << OpIdx << ").getReg()) == (" << Ty + << ")"; + } +}; + +struct MatchRegOpBank : public Matcher { + MatchRegOpBank(unsigned OpIdx, const CodeGenRegisterClass &RC) + : OpIdx(OpIdx), RC(RC) {} + unsigned OpIdx; + const CodeGenRegisterClass &RC; + + virtual void emit(raw_ostream &OS) const { + OS << "(&RBI.getRegBankFromRegClass(" << RC.getQualifiedName() + << "RegClass) == RBI.getRegBank(I.getOperand(" << OpIdx + << ").getReg(), MRI, TRI))"; + } +}; + +struct MatchMBBOp : public Matcher { + MatchMBBOp(unsigned OpIdx) : OpIdx(OpIdx) {} + unsigned OpIdx; + + virtual void emit(raw_ostream &OS) const { + OS << "I.getOperand(" << OpIdx << ").isMBB()"; + } +}; + +struct MutateOpcode : public MatchAction { + MutateOpcode(const CodeGenInstruction *I) : I(I) {} + const CodeGenInstruction *I; + + virtual void emit(raw_ostream &OS) const { + OS << "I.setDesc(TII.get(" << I->Namespace << "::" << I->TheDef->getName() + << "));"; + } +}; + +class MatcherEmitter { + const PatternToMatch &P; + +public: + std::vector<std::unique_ptr<Matcher>> Matchers; + std::vector<std::unique_ptr<MatchAction>> Actions; + + MatcherEmitter(const PatternToMatch &P) : P(P) {} + + void emit(raw_ostream &OS) { + if (Matchers.empty()) + llvm_unreachable("Unexpected empty matcher!"); + + OS << " // Src: " << *P.getSrcPattern() << "\n" + << " // Dst: " << *P.getDstPattern() << "\n"; + + OS << " if ((" << *Matchers.front() << ")"; + for (auto &MA : makeArrayRef(Matchers).drop_front()) + OS << " &&\n (" << *MA << ")"; + OS << ") {\n"; + + for (auto &MA : Actions) + OS << " " << *MA << "\n"; + + OS << " constrainSelectedInstRegOperands(I, TII, TRI, RBI);\n"; + OS << " return true;\n"; + OS << " }\n"; + } +}; + +//===- GlobalISelEmitter class --------------------------------------------===// + +void GlobalISelEmitter::gatherNodeEquivs() { + assert(NodeEquivs.empty()); + for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv")) + NodeEquivs[Equiv->getValueAsDef("Node")] = + &Target.getInstruction(Equiv->getValueAsDef("I")); +} + +const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) { + return NodeEquivs.lookup(N); +} + +GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK) + : RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {} + +//===- Emitter ------------------------------------------------------------===// + +Optional<GlobalISelEmitter::SkipReason> +GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { + + // Keep track of the matchers and actions to emit. + MatcherEmitter M(P); + + // First, analyze the whole pattern. + // If the entire pattern has a predicate (e.g., target features), ignore it. + if (!P.getPredicates()->getValues().empty()) + return SkipReason{"Pattern has a predicate"}; + + // Physreg imp-defs require additional logic. Ignore the pattern. + if (!P.getDstRegs().empty()) + return SkipReason{"Pattern defines a physical register"}; + + // Next, analyze the pattern operators. + TreePatternNode *Src = P.getSrcPattern(); + TreePatternNode *Dst = P.getDstPattern(); + + // If the root of either pattern isn't a simple operator, ignore it. + if (!isTrivialOperatorNode(Dst)) + return SkipReason{"Dst pattern root isn't a trivial operator"}; + if (!isTrivialOperatorNode(Src)) + return SkipReason{"Src pattern root isn't a trivial operator"}; + + Record *DstOp = Dst->getOperator(); + if (!DstOp->isSubClassOf("Instruction")) + return SkipReason{"Pattern operator isn't an instruction"}; + + auto &DstI = Target.getInstruction(DstOp); + + auto SrcGIOrNull = findNodeEquiv(Src->getOperator()); + if (!SrcGIOrNull) + return SkipReason{"Pattern operator lacks an equivalent Instruction"}; + auto &SrcGI = *SrcGIOrNull; + + // The operators look good: match the opcode and mutate it to the new one. + M.Matchers.emplace_back(new MatchOpcode(&SrcGI)); + M.Actions.emplace_back(new MutateOpcode(&DstI)); + + // Next, analyze the children, only accepting patterns that don't require + // any change to operands. + if (Src->getNumChildren() != Dst->getNumChildren()) + return SkipReason{"Src/dst patterns have a different # of children"}; + + unsigned OpIdx = 0; + + // Start with the defined operands (i.e., the results of the root operator). + if (DstI.Operands.NumDefs != Src->getExtTypes().size()) + return SkipReason{"Src pattern results and dst MI defs are different"}; + + for (const EEVT::TypeSet &Ty : Src->getExtTypes()) { + Record *DstIOpRec = DstI.Operands[OpIdx].Rec; + if (!DstIOpRec->isSubClassOf("RegisterClass")) + return SkipReason{"Dst MI def isn't a register class"}; + + auto OpTyOrNone = MVTToLLT(Ty.getConcrete()); + if (!OpTyOrNone) + return SkipReason{"Dst operand has an unsupported type"}; + + M.Matchers.emplace_back(new MatchRegOpType(OpIdx, *OpTyOrNone)); + M.Matchers.emplace_back( + new MatchRegOpBank(OpIdx, Target.getRegisterClass(DstIOpRec))); + ++OpIdx; + } + + // Finally match the used operands (i.e., the children of the root operator). + for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) { + auto *SrcChild = Src->getChild(i); + auto *DstChild = Dst->getChild(i); + + // Patterns can reorder operands. Ignore those for now. + if (SrcChild->getName() != DstChild->getName()) + return SkipReason{"Src/dst pattern children not in same order"}; + + // The only non-leaf child we accept is 'bb': it's an operator because + // BasicBlockSDNode isn't inline, but in MI it's just another operand. + if (!SrcChild->isLeaf()) { + if (DstChild->isLeaf() || + SrcChild->getOperator() != DstChild->getOperator()) + return SkipReason{"Src/dst pattern child operator mismatch"}; + + if (SrcChild->getOperator()->isSubClassOf("SDNode")) { + auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild->getOperator()); + if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") { + M.Matchers.emplace_back(new MatchMBBOp(OpIdx++)); + continue; + } + } + return SkipReason{"Src pattern child isn't a leaf node"}; + } + + if (SrcChild->getLeafValue() != DstChild->getLeafValue()) + return SkipReason{"Src/dst pattern child leaf mismatch"}; + + // Otherwise, we're looking for a bog-standard RegisterClass operand. + if (SrcChild->hasAnyPredicate()) + return SkipReason{"Src pattern child has predicate"}; + auto *ChildRec = cast<DefInit>(SrcChild->getLeafValue())->getDef(); + if (!ChildRec->isSubClassOf("RegisterClass")) + return SkipReason{"Src pattern child isn't a RegisterClass"}; + + ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes(); + if (ChildTypes.size() != 1) + return SkipReason{"Src pattern child has multiple results"}; + + auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete()); + if (!OpTyOrNone) + return SkipReason{"Src operand has an unsupported type"}; + + M.Matchers.emplace_back(new MatchRegOpType(OpIdx, *OpTyOrNone)); + M.Matchers.emplace_back( + new MatchRegOpBank(OpIdx, Target.getRegisterClass(ChildRec))); + ++OpIdx; + } + + // We're done with this pattern! Emit the processed result. + M.emit(OS); + ++NumPatternEmitted; + return None; +} + +void GlobalISelEmitter::run(raw_ostream &OS) { + // Track the GINodeEquiv definitions. + gatherNodeEquivs(); + + emitSourceFileHeader(("Global Instruction Selector for the " + + Target.getName() + " target").str(), OS); + OS << "bool " << Target.getName() + << "InstructionSelector::selectImpl" + "(MachineInstr &I) const {\n const MachineRegisterInfo &MRI = " + "I.getParent()->getParent()->getRegInfo();\n"; + + // Look through the SelectionDAG patterns we found, possibly emitting some. + for (const PatternToMatch &Pat : CGP.ptms()) { + ++NumPatternTotal; + if (auto SkipReason = runOnPattern(Pat, OS)) { + if (WarnOnSkippedPatterns) { + PrintWarning(Pat.getSrcRecord()->getLoc(), + "Skipped pattern: " + SkipReason->Reason); + } + ++NumPatternSkipped; + } + } + + OS << " return false;\n}\n"; +} + +//===----------------------------------------------------------------------===// + +namespace llvm { +void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS) { + GlobalISelEmitter(RK).run(OS); +} +} // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index 02461cc..ab7d964 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -13,22 +13,29 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" +#include "CodeGenInstruction.h" #include "CodeGenSchedule.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" #include "TableGenBackends.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include <algorithm> -#include <cstdio> +#include <cassert> +#include <cstdint> #include <map> +#include <string> +#include <utility> #include <vector> using namespace llvm; namespace { + class InstrInfoEmitter { RecordKeeper &Records; CodeGenDAGPatterns CDP; @@ -50,7 +57,7 @@ private: /// and instruction operand indices as their values. The values of this map /// are lists of instruction names. typedef std::map<std::map<unsigned, unsigned>, - std::vector<std::string> > OpNameMapTy; + std::vector<std::string>> OpNameMapTy; typedef std::map<std::string, unsigned>::iterator StrUintMapIter; void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, @@ -70,6 +77,7 @@ private: void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); }; + } // end anonymous namespace static void PrintDefList(const std::vector<Record*> &Uses, @@ -106,7 +114,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { OperandList.push_back(Op); - Record *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); + auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; } } @@ -202,7 +210,6 @@ void InstrInfoEmitter::initOperandMapData( const std::string &Namespace, std::map<std::string, unsigned> &Operands, OpNameMapTy &OperandMap) { - unsigned NumOperands = 0; for (const CodeGenInstruction *Inst : NumberedInstructions) { if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) @@ -217,7 +224,8 @@ void InstrInfoEmitter::initOperandMapData( } OpList[I->second] = Info.MIOperandNo; } - OperandMap[OpList].push_back(Namespace + "::" + Inst->TheDef->getName()); + OperandMap[OpList].push_back(Namespace + "::" + + Inst->TheDef->getName().str()); } } @@ -235,7 +243,6 @@ void InstrInfoEmitter::initOperandMapData( void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target, ArrayRef<const CodeGenInstruction*> NumberedInstructions) { - const std::string &Namespace = Target.getInstNamespace(); std::string OpNameNS = "OpName"; // Map of operand names to their enumeration value. This will be used to @@ -300,7 +307,6 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "} // end namespace " << Namespace << "\n"; OS << "} // end namespace llvm\n"; OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n"; - } /// Generate an enum for all the operand types for this target, under the @@ -429,7 +435,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "struct " << ClassName << " : public TargetInstrInfo {\n" << " explicit " << ClassName << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n" - << " ~" << ClassName << "() override {}\n" + << " ~" << ClassName << "() override = default;\n" << "};\n"; OS << "} // end llvm namespace\n"; @@ -482,6 +488,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)"; if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)"; if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)"; + if (Inst.isAdd) OS << "|(1ULL<<MCID::Add)"; if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)"; if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)"; if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)"; @@ -514,7 +521,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, PrintFatalError("no TSFlags?"); uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { - if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(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()); @@ -561,7 +568,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // emitEnums - Print out enum values for all of the instructions. void InstrInfoEmitter::emitEnums(raw_ostream &OS) { - OS << "#ifdef GET_INSTRINFO_ENUM\n"; OS << "#undef GET_INSTRINFO_ENUM\n"; diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index a676159..33256cc 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -213,10 +213,11 @@ enum IIT_Info { IIT_HALF_VEC_ARG = 30, IIT_SAME_VEC_WIDTH_ARG = 31, IIT_PTR_TO_ARG = 32, - IIT_VEC_OF_PTRS_TO_ELT = 33, - IIT_I128 = 34, - IIT_V512 = 35, - IIT_V1024 = 36 + IIT_PTR_TO_ELT = 33, + IIT_VEC_OF_PTRS_TO_ELT = 34, + IIT_I128 = 35, + IIT_V512 = 36, + IIT_V1024 = 37 }; @@ -251,7 +252,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, } #if defined(_MSC_VER) && !defined(__clang__) -#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function. +#pragma optimize("",off) // MSVC 2015 optimizer can't deal with this function. #endif static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, @@ -277,6 +278,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, Sig.push_back(IIT_PTR_TO_ARG); else if (R->isSubClassOf("LLVMVectorOfPointersToElt")) Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT); + else if (R->isSubClassOf("LLVMPointerToElt")) + Sig.push_back(IIT_PTR_TO_ELT); else Sig.push_back(IIT_ARG); return Sig.push_back((Number << 3) | ArgCodes[Number]); @@ -287,10 +290,10 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, unsigned Tmp = 0; switch (VT) { default: break; - case MVT::iPTRAny: ++Tmp; // FALL THROUGH. - case MVT::vAny: ++Tmp; // FALL THROUGH. - case MVT::fAny: ++Tmp; // FALL THROUGH. - case MVT::iAny: ++Tmp; // FALL THROUGH. + 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: { // If this is an "any" valuetype, then the type is the type of the next // type in the list specified to getIntrinsic(). @@ -643,6 +646,18 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << ","; OS << "Attribute::ReadOnly"; break; + case CodeGenIntrinsic::ReadInaccessibleMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadOnly,"; + OS << "Attribute::InaccessibleMemOnly"; + break; + case CodeGenIntrinsic::ReadInaccessibleMemOrArgMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadOnly,"; + OS << "Attribute::InaccessibleMemOrArgMemOnly"; + break; case CodeGenIntrinsic::WriteArgMem: if (addComma) OS << ","; @@ -654,11 +669,32 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << ","; OS << "Attribute::WriteOnly"; break; + case CodeGenIntrinsic::WriteInaccessibleMem: + if (addComma) + OS << ","; + OS << "Attribute::WriteOnly,"; + OS << "Attribute::InaccessibleMemOnly"; + break; + case CodeGenIntrinsic::WriteInaccessibleMemOrArgMem: + if (addComma) + OS << ","; + OS << "Attribute::WriteOnly,"; + OS << "Attribute::InaccessibleMemOrArgOnly"; + break; case CodeGenIntrinsic::ReadWriteArgMem: if (addComma) OS << ","; OS << "Attribute::ArgMemOnly"; break; + case CodeGenIntrinsic::ReadWriteInaccessibleMem: + if (addComma) + OS << ","; + OS << "Attribute::InaccessibleMemOnly"; + break; + case CodeGenIntrinsic::ReadWriteInaccessibleMemOrArgMem: + if (addComma) + OS << ","; + OS << "Attribute::InaccessibleMemOrArgMemOnly"; case CodeGenIntrinsic::ReadWriteMem: break; } @@ -714,11 +750,11 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap( if (TargetOnly) { OS << "static " << TargetPrefix << "Intrinsic::ID " << "getIntrinsicFor" << CompilerName << "Builtin(const char " - << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n"; } else { OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName << "Builtin(const char " - << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n"; } OS << " static const char BuiltinNames[] = {\n"; Table.EmitCharArray(OS); @@ -730,13 +766,11 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap( OS << " const char *getName() const {\n"; OS << " return &BuiltinNames[StrTabOffset];\n"; OS << " }\n"; - OS << " bool operator<(const char *RHS) const {\n"; - OS << " return strcmp(getName(), RHS) < 0;\n"; + OS << " bool operator<(StringRef RHS) const {\n"; + OS << " return strncmp(getName(), RHS.data(), RHS.size()) < 0;\n"; OS << " }\n"; OS << " };\n"; - - OS << " StringRef BuiltinName(BuiltinNameStr);\n"; OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; // Note: this could emit significantly better code if we cared. @@ -759,7 +793,7 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap( OS << " std::end(" << I->first << "Names),\n"; OS << " BuiltinNameStr);\n"; OS << " if (I != std::end(" << I->first << "Names) &&\n"; - OS << " strcmp(I->getName(), BuiltinNameStr) == 0)\n"; + OS << " I->getName() == BuiltinNameStr)\n"; OS << " return I->IntrinID;\n"; OS << " }\n"; } diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp index 01e41d1..63bdd36 100644 --- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -177,10 +177,10 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) continue; StringMap<unsigned>::iterator SourceOp = - SourceOperands.find(Dag->getArgName(i)); + SourceOperands.find(Dag->getArgNameStr(i)); if (SourceOp == SourceOperands.end()) PrintFatalError(Rec->getLoc(), - "Pseudo output operand '" + Dag->getArgName(i) + + "Pseudo output operand '" + Dag->getArgNameStr(i) + "' has no matching source operand."); // Map the source operand to the destination operand index for each // MachineInstr operand. diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 9bb988f..b75be13 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -15,6 +15,7 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" +#include "Types.h" #include "SequenceToOffsetTable.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -103,7 +104,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "namespace llvm {\n\n"; OS << "class MCRegisterClass;\n" - << "extern const MCRegisterClass " << Namespace + << "extern const MCRegisterClass " << Target.getName() << "MCRegisterClasses[];\n\n"; if (!Namespace.empty()) @@ -177,15 +178,6 @@ static void printInt(raw_ostream &OS, int Val) { OS << Val; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - void RegisterInfoEmitter:: EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName) { @@ -264,8 +256,9 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, OS << "// Get the register unit pressure limit for this dimension.\n" << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" - << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n" - << " static const " << getMinimalTypeForRange(MaxRegUnitWeight) + << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const " + "{\n" + << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32) << " PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); @@ -306,7 +299,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "/// Returns a -1 terminated array of pressure set IDs\n" << "const int* " << ClassName << "::\n" << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; - OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) << " RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { OS << PSetsSeqs.get(PSets[i]) << ","; @@ -322,7 +315,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "getRegUnitPressureSets(unsigned RegUnit) const {\n" << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() << " && \"invalid register unit\");\n"; - OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) << " RUSetStartTable[] = {\n "; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { @@ -585,7 +578,7 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { // 0 differential which means we can't encode repeated elements. typedef SmallVector<uint16_t, 4> DiffVec; -typedef SmallVector<unsigned, 4> MaskVec; +typedef SmallVector<LaneBitmask, 4> MaskVec; // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. @@ -618,8 +611,8 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) { OS << Val; } -static void printMask(raw_ostream &OS, unsigned Val) { - OS << format("0x%08X", Val); +static void printMask(raw_ostream &OS, LaneBitmask Val) { + OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')'; } // Try to combine Idx's compose map into Vec if it is compatible. @@ -683,15 +676,15 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, // Output the row map if there is multiple rows. if (Rows.size() > 1) { - OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap[" - << SubRegIndicesSize << "] = {\n "; + OS << " static const " << getMinimalTypeForRange(Rows.size(), 32) + << " RowMap[" << SubRegIndicesSize << "] = {\n "; for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) OS << RowMap[i] << ", "; OS << "\n };\n"; } // Output the rows. - OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1) + OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32) << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; for (unsigned r = 0, re = Rows.size(); r != re; ++r) { OS << " { "; @@ -746,7 +739,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, } OS << " struct MaskRolOp {\n" - " unsigned Mask;\n" + " LaneBitmask Mask;\n" " uint8_t RotateLeft;\n" " };\n" " static const MaskRolOp LaneMaskComposeSequences[] = {\n"; @@ -756,9 +749,10 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { const MaskRolPair &P = Sequence[p]; - OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft); + printMask(OS << "{ ", P.Mask); + OS << format(", %2u }, ", P.RotateLeft); } - OS << "{ 0, 0 }"; + OS << "{ LaneBitmask::getNone(), 0 }"; if (s+1 != se) OS << ", "; OS << " // Sequence " << Idx << "\n"; @@ -781,12 +775,13 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, " const {\n" " --IdxA; assert(IdxA < " << SubRegIndices.size() << " && \"Subregister index out of bounds\");\n" - " LaneBitmask Result = 0;\n" - " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)" - " {\n" - " LaneBitmask Masked = LaneMask & Ops->Mask;\n" - " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n" - " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n" + " LaneBitmask Result;\n" + " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n" + " LaneBitmask::Type M = LaneMask.getAsInteger() & Ops->Mask.getAsInteger();\n" + " if (unsigned S = Ops->RotateLeft)\n" + " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - S)));\n" + " else\n" + " Result |= LaneBitmask(M);\n" " }\n" " return Result;\n" "}\n\n"; @@ -797,12 +792,13 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, " LaneMask &= getSubRegIndexLaneMask(IdxA);\n" " --IdxA; assert(IdxA < " << SubRegIndices.size() << " && \"Subregister index out of bounds\");\n" - " LaneBitmask Result = 0;\n" - " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)" - " {\n" - " LaneBitmask Rotated = (LaneMask >> Ops->RotateLeft) |\n" - " ((LaneMask << ((32 - Ops->RotateLeft) & 0x1F)) & 0xFFFFFFFF);\n" - " Result |= Rotated & Ops->Mask;\n" + " LaneBitmask Result;\n" + " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n" + " LaneBitmask::Type M = LaneMask.getAsInteger();\n" + " if (unsigned S = Ops->RotateLeft)\n" + " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - S)));\n" + " else\n" + " Result |= LaneBitmask(M);\n" " }\n" " return Result;\n" "}\n\n"; @@ -901,8 +897,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end()); // Terminator mask should not be used inside of the list. #ifndef NDEBUG - for (unsigned M : LaneMaskVec) { - assert(M != ~0u && "terminator mask should not be part of the list"); + for (LaneBitmask M : LaneMaskVec) { + assert(!M.all() && "terminator mask should not be part of the list"); } #endif LaneMaskSeqs.add(LaneMaskVec); @@ -923,8 +919,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n\n"; // Emit the shared table of regunit lane mask sequences. - OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n"; - LaneMaskSeqs.emit(OS, printMask, "~0u"); + OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n"; + LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()"); OS << "};\n\n"; // Emit the table of sub-register indexes. @@ -1204,9 +1200,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\" };\n\n"; // Emit SubRegIndex lane masks, including 0. - OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; + OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n LaneBitmask::getAll(),\n"; for (const auto &Idx : SubRegIndices) { - OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n'; + printMask(OS << " ", Idx.LaneMask); + OS << ", // " << Idx.getName() << '\n'; } OS << " };\n\n"; @@ -1324,9 +1321,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " - << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n " - << format("0x%08x,\n ", RC.LaneMask) - << (unsigned)RC.AllocationPriority << ",\n " + << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "; + printMask(OS, RC.LaneMask); + OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " << (RC.HasDisjunctSubRegs?"true":"false") << ", /* HasDisjunctSubRegs */\n " << (RC.CoveredBySubRegs?"true":"false") @@ -1368,7 +1365,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n"; // End of register descriptors... - std::string ClassName = Target.getName() + "GenRegisterInfo"; + std::string ClassName = Target.getName().str() + "GenRegisterInfo"; auto SubRegIndicesSize = std::distance(SubRegIndices.begin(), SubRegIndices.end()); @@ -1415,7 +1412,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; - OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n"; + OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; @@ -1430,8 +1427,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x"; - OS.write_hex(RegBank.CoveringLanes); + << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, "; + printMask(OS, RegBank.CoveringLanes); OS << ") {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 << ", RA, PC,\n " << TargetName diff --git a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp index 8c1b880..80f0b0d 100644 --- a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -193,7 +193,7 @@ void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field, } else { // Make sure the result is null terminated because it's going via "char *". OS << " std::string CanonicalVal = " << Field << ".upper();\n"; - OS << " " << PairType << " Val = {CanonicalVal.data(), 0};\n"; + OS << " " << PairType << " Val = {CanonicalVal.c_str(), 0};\n"; } OS << " ArrayRef<" << PairType << "> Table(" << Name << "sBy" << Field @@ -206,7 +206,7 @@ void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field, OS << ",\n "; OS << "[](const " << PairType << " &LHS, const " << PairType << " &RHS) {\n"; - OS << " return StringRef(LHS.first) < StringRef(RHS.first);\n"; + OS << " return std::strcmp(LHS.first, RHS.first) < 0;\n"; OS << " });\n\n"; } diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index 2288821..bf7b392 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -14,7 +14,9 @@ #include "CodeGenTarget.h" #include "CodeGenSchedule.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/MCSchedule.h" #include "llvm/MC/SubtargetFeature.h" @@ -27,6 +29,7 @@ #include <algorithm> #include <cassert> #include <cstdint> +#include <iterator> #include <map> #include <string> #include <vector> @@ -42,7 +45,7 @@ class SubtargetEmitter { // The SchedClassDesc table indexes into a global write resource table, write // latency table, and read advance table. struct SchedClassTables { - std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses; + std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses; std::vector<MCWriteProcResEntry> WriteProcResources; std::vector<MCWriteLatencyEntry> WriteLatencies; std::vector<std::string> WriterNames; @@ -81,12 +84,12 @@ class SubtargetEmitter { Record *ItinData, std::string &ItinString, unsigned NOperandCycles); void EmitStageAndOperandCycleData(raw_ostream &OS, - std::vector<std::vector<InstrItinerary> > + std::vector<std::vector<InstrItinerary>> &ProcItinLists); void EmitItineraries(raw_ostream &OS, - std::vector<std::vector<InstrItinerary> > + std::vector<std::vector<InstrItinerary>> &ProcItinLists); - void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name, + void EmitProcessorProp(raw_ostream &OS, const Record *R, StringRef Name, char Separator); void EmitProcessorResources(const CodeGenProcModel &ProcModel, raw_ostream &OS); @@ -294,7 +297,7 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name, // For each unit for (unsigned j = 0, M = UnitList.size(); j < M;) { // Add name and bitwise or - ItinString += Name + "FU::" + UnitList[j]->getName(); + ItinString += Name + "FU::" + UnitList[j]->getName().str(); if (++j < M) ItinString += " | "; } @@ -341,7 +344,7 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, unsigned N = BypassList.size(); unsigned i = 0; for (; i < N;) { - ItinString += Name + "Bypass::" + BypassList[i]->getName(); + ItinString += Name + "Bypass::" + BypassList[i]->getName().str(); if (++i < NOperandCycles) ItinString += ", "; } for (; i < NOperandCycles;) { @@ -357,9 +360,8 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, // void SubtargetEmitter:: EmitStageAndOperandCycleData(raw_ostream &OS, - std::vector<std::vector<InstrItinerary> > + std::vector<std::vector<InstrItinerary>> &ProcItinLists) { - // Multiple processor models may share an itinerary record. Emit it once. SmallPtrSet<Record*, 8> ItinsDefSet; @@ -498,7 +500,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0; InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, FindOperandCycle, - FindOperandCycle + NOperandCycles}; + FindOperandCycle + NOperandCycles }; // Inject - empty slots will be 0, 0 ItinList[SchedClassIdx] = Intinerary; @@ -530,13 +532,12 @@ EmitStageAndOperandCycleData(raw_ostream &OS, // void SubtargetEmitter:: EmitItineraries(raw_ostream &OS, - std::vector<std::vector<InstrItinerary> > &ProcItinLists) { - + std::vector<std::vector<InstrItinerary>> &ProcItinLists) { // Multiple processor models may share an itinerary record. Emit it once. SmallPtrSet<Record*, 8> ItinsDefSet; // For each processor's machine model - std::vector<std::vector<InstrItinerary> >::iterator + std::vector<std::vector<InstrItinerary>>::iterator ProcItinListsIter = ProcItinLists.begin(); for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { @@ -587,7 +588,7 @@ EmitItineraries(raw_ostream &OS, // value defined in the C++ header. The Record is null if the processor does not // define a model. void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R, - const char *Name, char Separator) { + StringRef Name, char Separator) { OS << " "; int V = R ? R->getValueAsInt(Name) : -1; if (V >= 0) @@ -783,8 +784,7 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec, RecVec SuperResources = PR->getValueAsListOfDefs("Resources"); RecIter SubI = SubResources.begin(), SubE = SubResources.end(); for( ; SubI != SubE; ++SubI) { - if (std::find(SuperResources.begin(), SuperResources.end(), *SubI) - == SuperResources.end()) { + if (!is_contained(SuperResources, *SubI)) { break; } } @@ -827,9 +827,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, HasVariants = true; break; } - IdxIter PIPos = std::find(TI->ProcIndices.begin(), - TI->ProcIndices.end(), ProcModel.Index); - if (PIPos != TI->ProcIndices.end()) { + if (is_contained(TI->ProcIndices, ProcModel.Index)) { HasVariants = true; break; } @@ -844,9 +842,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, // If ProcIndices contains 0, this class applies to all processors. assert(!SC.ProcIndices.empty() && "expect at least one procidx"); if (SC.ProcIndices[0] != 0) { - IdxIter PIPos = std::find(SC.ProcIndices.begin(), - SC.ProcIndices.end(), ProcModel.Index); - if (PIPos == SC.ProcIndices.end()) + if (!is_contained(SC.ProcIndices, ProcModel.Index)) continue; } IdxVec Writes = SC.Writes; @@ -873,8 +869,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, // Check this processor's itinerary class resources. for (Record *I : ProcModel.ItinRWDefs) { RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses"); - if (std::find(Matched.begin(), Matched.end(), SC.ItinClassDef) - != Matched.end()) { + if (is_contained(Matched, SC.ItinClassDef)) { SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); break; @@ -1246,7 +1241,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { << "#endif\n"; if (SchedModels.hasItineraries()) { - std::vector<std::vector<InstrItinerary> > ProcItinLists; + std::vector<std::vector<InstrItinerary>> ProcItinLists; // Emit the stage data EmitStageAndOperandCycleData(OS, ProcItinLists); EmitItineraries(OS, ProcItinLists); @@ -1430,13 +1425,13 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; + OS << '\n'; OS.indent(22); if (SchedModels.hasItineraries()) { - OS << '\n'; OS.indent(22); OS << Target << "Stages, " << Target << "OperandCycles, " << Target << "ForwardingPaths"; } else - OS << "0, 0, 0"; + OS << "nullptr, nullptr, nullptr"; OS << ");\n}\n\n"; OS << "} // end namespace llvm\n\n"; @@ -1516,7 +1511,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "OperandCycles, " << Target << "ForwardingPaths"; } else - OS << "0, 0, 0"; + OS << "nullptr, nullptr, nullptr"; OS << ") {}\n\n"; EmitSchedModelHelpers(ClassName, OS); diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp new file mode 100644 index 0000000..7db8813 --- /dev/null +++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp @@ -0,0 +1,119 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#include "SubtargetFeatureInfo.h" + +#include "Types.h" +#include "llvm/TableGen/Record.h" + +#include <map> + +using namespace llvm; + +void SubtargetFeatureInfo::dump() const { + errs() << getEnumName() << " " << Index << "\n"; + TheDef->dump(); +} + +std::vector<std::pair<Record *, SubtargetFeatureInfo>> +SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { + std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatures; + std::vector<Record *> AllPredicates = + Records.getAllDerivedDefinitions("Predicate"); + for (Record *Pred : AllPredicates) { + // Ignore predicates that are not intended for the assembler. + // + // The "AssemblerMatcherPredicate" string should be promoted to an argument + // if we re-use the machinery for non-assembler purposes in future. + if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) + continue; + + if (Pred->getName().empty()) + PrintFatalError(Pred->getLoc(), "Predicate has no name!"); + + SubtargetFeatures.emplace_back( + Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())); + } + return SubtargetFeatures; +} + +void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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::emitNameTable( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { + OS << "static const char *SubtargetFeatureNames[] = {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " \"" << SFI.getEnumName() << "\",\n"; + } + // A small number of targets have no predicates. Null terminate the array to + // avoid a zero-length array. + OS << " nullptr\n" + << "};\n\n"; +} + +void SubtargetFeatureInfo::emitComputeAvailableFeatures( + StringRef TargetName, StringRef ClassName, StringRef FuncName, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { + OS << "uint64_t " << TargetName << ClassName << "::\n" + << FuncName << "(const FeatureBitset& FB) const {\n"; + OS << " uint64_t Features = 0;\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + + OS << " if ("; + std::string CondStorage = + SFI.TheDef->getValueAsString("AssemblerCondString"); + StringRef Conds = CondStorage; + std::pair<StringRef, StringRef> Comma = Conds.split(','); + bool First = true; + do { + if (!First) + OS << " && "; + + bool Neg = false; + StringRef Cond = Comma.first; + if (Cond[0] == '!') { + Neg = true; + Cond = Cond.substr(1); + } + + OS << "("; + if (Neg) + OS << "!"; + OS << "FB[" << TargetName << "::" << Cond << "])"; + + if (Comma.second.empty()) + break; + + First = false; + Comma = Comma.second.split(','); + } while (true); + + OS << ")\n"; + OS << " Features |= " << SFI.getEnumName() << ";\n"; + } + OS << " return Features;\n"; + OS << "}\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h new file mode 100644 index 0000000..99f380f --- /dev/null +++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h @@ -0,0 +1,72 @@ +//===- SubtargetFeatureInfo.h - 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H +#define LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H + +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +#include <map> +#include <string> +#include <vector> + +namespace llvm { +class Record; +class RecordKeeper; + +/// Helper class for storing information on a subtarget feature which +/// participates in instruction matching. +struct SubtargetFeatureInfo { + /// \brief The predicate record for this feature. + Record *TheDef; + + /// \brief An unique index assigned to represent this feature. + uint64_t Index; + + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} + + /// \brief The name of the enumerated constant identifying this feature. + std::string getEnumName() const { + return "Feature_" + TheDef->getName().str(); + } + + void dump() const; + static std::vector<std::pair<Record *, SubtargetFeatureInfo>> + getAll(const RecordKeeper &Records); + + /// Emit the subtarget feature flag definitions. + static void emitSubtargetFeatureFlagEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + &SubtargetFeatures, + raw_ostream &OS); + + static void emitNameTable(std::map<Record *, SubtargetFeatureInfo, + LessRecordByID> &SubtargetFeatures, + raw_ostream &OS); + + /// Emit the function to compute the list of available features given a + /// subtarget. + /// + /// \param TargetName The name of the target as used in class prefixes (e.g. + /// <TargetName>Subtarget) + /// \param ClassName The name of the class (without the <Target> prefix) + /// that will contain the generated functions. + /// \param FuncName The name of the function to emit. + /// \param SubtargetFeatures A map of TableGen records to the + /// SubtargetFeatureInfo equivalent. + static void emitComputeAvailableFeatures( + StringRef TargetName, StringRef ClassName, StringRef FuncName, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + &SubtargetFeatures, + raw_ostream &OS); +}; +} // end namespace llvm + +#endif // LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index 24dbe5d..79a7731 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -45,6 +45,7 @@ enum ActionType { GenCTags, GenAttributes, GenSearchableTables, + GenGlobalISel, }; namespace { @@ -92,7 +93,8 @@ namespace { "Generate attributes"), clEnumValN(GenSearchableTables, "gen-searchable-tables", "Generate generic binary-searchable table"), - clEnumValEnd)); + clEnumValN(GenGlobalISel, "gen-global-isel", + "Generate GlobalISel selector"))); cl::opt<std::string> Class("class", cl::desc("Print Enum list for this class"), @@ -178,6 +180,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenSearchableTables: EmitSearchableTables(Records, OS); break; + case GenGlobalISel: + EmitGlobalISel(Records, OS); + break; } return false; diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h index 51e017f..eb306d2 100644 --- a/contrib/llvm/utils/TableGen/TableGenBackends.h +++ b/contrib/llvm/utils/TableGen/TableGenBackends.h @@ -80,6 +80,7 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); void EmitAttributes(RecordKeeper &RK, raw_ostream &OS); void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS); +void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/Types.cpp b/contrib/llvm/utils/TableGen/Types.cpp new file mode 100644 index 0000000..3545829 --- /dev/null +++ b/contrib/llvm/utils/TableGen/Types.cpp @@ -0,0 +1,44 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#include "Types.h" + +// For LLVM_ATTRIBUTE_UNUSED +#include "llvm/Support/Compiler.h" + +#include <cassert> + +using namespace llvm; + +const char *llvm::getMinimalTypeForRange(uint64_t Range, unsigned MaxSize LLVM_ATTRIBUTE_UNUSED) { + // TODO: The original callers only used 32 and 64 so these are the only + // values permitted. Rather than widen the supported values we should + // allow 64 for the callers that currently use 32 and remove the + // argument altogether. + assert((MaxSize == 32 || MaxSize == 64) && "Unexpected size"); + assert(MaxSize <= 64 && "Unexpected size"); + assert(((MaxSize > 32) ? Range <= 0xFFFFFFFFFFFFFFFFULL + : Range <= 0xFFFFFFFFULL) && + "Enum too large"); + + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + +const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) { + uint64_t MaxIndex = Size; + if (MaxIndex > 0) + MaxIndex--; + return getMinimalTypeForRange(1ULL << MaxIndex); +} diff --git a/contrib/llvm/utils/TableGen/Types.h b/contrib/llvm/utils/TableGen/Types.h new file mode 100644 index 0000000..d511b7e --- /dev/null +++ b/contrib/llvm/utils/TableGen/Types.h @@ -0,0 +1,25 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTILS_TABLEGEN_TYPES_H +#define LLVM_UTILS_TABLEGEN_TYPES_H + +#include <cstdint> + +namespace llvm { +/// Returns the smallest unsigned integer type that can hold the given range. +/// MaxSize indicates the largest size of integer to consider (in bits) and only +/// supports values of at least 32. +const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64); + +/// Returns the smallest unsigned integer type that can hold the given bitfield. +const char *getMinimalTypeForEnumBitfield(uint64_t Size); +} + +#endif diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index ca937d0..4736c4e 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -23,96 +23,100 @@ using namespace llvm; #define MRM_MAPPING \ - MAP(C0, 32) \ - MAP(C1, 33) \ - MAP(C2, 34) \ - MAP(C3, 35) \ - MAP(C4, 36) \ - MAP(C5, 37) \ - MAP(C6, 38) \ - MAP(C7, 39) \ - MAP(C8, 40) \ - MAP(C9, 41) \ - MAP(CA, 42) \ - MAP(CB, 43) \ - MAP(CC, 44) \ - MAP(CD, 45) \ - MAP(CE, 46) \ - MAP(CF, 47) \ - MAP(D0, 48) \ - MAP(D1, 49) \ - MAP(D2, 50) \ - MAP(D3, 51) \ - MAP(D4, 52) \ - MAP(D5, 53) \ - MAP(D6, 54) \ - MAP(D7, 55) \ - MAP(D8, 56) \ - MAP(D9, 57) \ - MAP(DA, 58) \ - MAP(DB, 59) \ - MAP(DC, 60) \ - MAP(DD, 61) \ - MAP(DE, 62) \ - MAP(DF, 63) \ - MAP(E0, 64) \ - MAP(E1, 65) \ - MAP(E2, 66) \ - MAP(E3, 67) \ - MAP(E4, 68) \ - MAP(E5, 69) \ - MAP(E6, 70) \ - MAP(E7, 71) \ - MAP(E8, 72) \ - MAP(E9, 73) \ - MAP(EA, 74) \ - MAP(EB, 75) \ - MAP(EC, 76) \ - MAP(ED, 77) \ - MAP(EE, 78) \ - MAP(EF, 79) \ - MAP(F0, 80) \ - MAP(F1, 81) \ - MAP(F2, 82) \ - MAP(F3, 83) \ - MAP(F4, 84) \ - MAP(F5, 85) \ - MAP(F6, 86) \ - MAP(F7, 87) \ - MAP(F8, 88) \ - MAP(F9, 89) \ - MAP(FA, 90) \ - MAP(FB, 91) \ - MAP(FC, 92) \ - MAP(FD, 93) \ - MAP(FE, 94) \ - MAP(FF, 95) + MAP(C0, 64) \ + MAP(C1, 65) \ + MAP(C2, 66) \ + MAP(C3, 67) \ + MAP(C4, 68) \ + MAP(C5, 69) \ + MAP(C6, 70) \ + MAP(C7, 71) \ + MAP(C8, 72) \ + MAP(C9, 73) \ + MAP(CA, 74) \ + MAP(CB, 75) \ + MAP(CC, 76) \ + MAP(CD, 77) \ + MAP(CE, 78) \ + MAP(CF, 79) \ + MAP(D0, 80) \ + MAP(D1, 81) \ + MAP(D2, 82) \ + MAP(D3, 83) \ + MAP(D4, 84) \ + MAP(D5, 85) \ + MAP(D6, 86) \ + MAP(D7, 87) \ + MAP(D8, 88) \ + MAP(D9, 89) \ + MAP(DA, 90) \ + MAP(DB, 91) \ + MAP(DC, 92) \ + MAP(DD, 93) \ + MAP(DE, 94) \ + MAP(DF, 95) \ + MAP(E0, 96) \ + MAP(E1, 97) \ + MAP(E2, 98) \ + MAP(E3, 99) \ + MAP(E4, 100) \ + MAP(E5, 101) \ + MAP(E6, 102) \ + MAP(E7, 103) \ + MAP(E8, 104) \ + MAP(E9, 105) \ + MAP(EA, 106) \ + MAP(EB, 107) \ + MAP(EC, 108) \ + MAP(ED, 109) \ + MAP(EE, 110) \ + MAP(EF, 111) \ + MAP(F0, 112) \ + MAP(F1, 113) \ + MAP(F2, 114) \ + MAP(F3, 115) \ + MAP(F4, 116) \ + MAP(F5, 117) \ + MAP(F6, 118) \ + MAP(F7, 119) \ + MAP(F8, 120) \ + MAP(F9, 121) \ + MAP(FA, 122) \ + MAP(FB, 123) \ + MAP(FC, 124) \ + MAP(FD, 125) \ + MAP(FE, 126) \ + MAP(FF, 127) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { enum { - Pseudo = 0, - RawFrm = 1, - AddRegFrm = 2, - MRMDestReg = 3, - MRMDestMem = 4, - MRMSrcReg = 5, - MRMSrcMem = 6, - RawFrmMemOffs = 7, - RawFrmSrc = 8, - RawFrmDst = 9, - RawFrmDstSrc = 10, - RawFrmImm8 = 11, - RawFrmImm16 = 12, - MRMXr = 14, MRMXm = 15, - MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, - MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, - MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, - MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, + Pseudo = 0, + RawFrm = 1, + AddRegFrm = 2, + RawFrmMemOffs = 3, + RawFrmSrc = 4, + RawFrmDst = 5, + RawFrmDstSrc = 6, + RawFrmImm8 = 7, + RawFrmImm16 = 8, + MRMDestMem = 32, + MRMSrcMem = 33, + MRMSrcMem4VOp3 = 34, + MRMSrcMemOp4 = 35, + 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, + MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59, + MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63, #define MAP(from, to) MRM_##from = to, MRM_MAPPING #undef MAP - lastMRM }; enum { @@ -138,19 +142,6 @@ namespace X86Local { using namespace X86Disassembler; -/// isRegFormat - Indicates whether a particular form requires the Mod field of -/// the ModR/M byte to be 0b11. -/// -/// @param form - The form of the instruction. -/// @return - true if the form implies that Mod must be 0b11, false -/// otherwise. -static bool isRegFormat(uint8_t form) { - return (form == X86Local::MRMDestReg || - form == X86Local::MRMSrcReg || - form == X86Local::MRMXr || - (form >= X86Local::MRM0r && form <= X86Local::MRM7r)); -} - /// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit. /// Useful for switch statements and the like. /// @@ -212,9 +203,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, AdSize = byteFromRec(Rec, "AdSizeBits"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); HasVEX_4V = Rec->getValueAsBit("hasVEX_4V"); - HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3"); HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); - HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix"); IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2"); HasEVEX_K = Rec->getValueAsBit("hasEVEX_K"); @@ -565,7 +554,7 @@ void RecognizableInstr::emitInstructionSpecifier() { // Given the set of prefix bits, how many additional operands does the // instruction have? unsigned additionalOperands = 0; - if (HasVEX_4V || HasVEX_4VOp3) + if (HasVEX_4V) ++additionalOperands; if (HasEVEX_K) ++additionalOperands; @@ -666,19 +655,27 @@ void RecognizableInstr::emitInstructionSpecifier() { // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) - if (HasMemOp4Prefix) - HANDLE_OPERAND(immediate) - HANDLE_OPERAND(rmRegister) - - if (HasVEX_4VOp3) - HANDLE_OPERAND(vvvvRegister) - - if (!HasMemOp4Prefix) - HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMSrcReg4VOp3: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMSrcRegFrm"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(rmRegister) + HANDLE_OPERAND(vvvvRegister) + break; + case X86Local::MRMSrcRegOp4: + assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 && + "Unexpected number of operands for MRMSrcRegOp4Frm"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(vvvvRegister) + HANDLE_OPERAND(immediate) // Register in imm[7:4] + HANDLE_OPERAND(rmRegister) + HANDLE_OPTIONAL(immediate) + break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a memory operand (possibly SIB-extended) @@ -699,18 +696,26 @@ void RecognizableInstr::emitInstructionSpecifier() { // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) - if (HasMemOp4Prefix) - HANDLE_OPERAND(immediate) - HANDLE_OPERAND(memory) - - if (HasVEX_4VOp3) - HANDLE_OPERAND(vvvvRegister) - - if (!HasMemOp4Prefix) - HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 break; + case X86Local::MRMSrcMem4VOp3: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMSrcMemFrm"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(memory) + HANDLE_OPERAND(vvvvRegister) + break; + case X86Local::MRMSrcMemOp4: + assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 && + "Unexpected number of operands for MRMSrcMemOp4Frm"); + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(vvvvRegister) + HANDLE_OPERAND(immediate) // Register in imm[7:4] + HANDLE_OPERAND(memory) + HANDLE_OPTIONAL(immediate) + break; case X86Local::MRMXr: case X86Local::MRM0r: case X86Local::MRM1r: @@ -841,13 +846,31 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { } switch (Form) { - default: + default: llvm_unreachable("Invalid form!"); + case X86Local::Pseudo: llvm_unreachable("Pseudo should not be emitted!"); + case X86Local::RawFrm: + case X86Local::AddRegFrm: + case X86Local::RawFrmMemOffs: + case X86Local::RawFrmSrc: + case X86Local::RawFrmDst: + case X86Local::RawFrmDstSrc: + case X86Local::RawFrmImm8: + case X86Local::RawFrmImm16: filter = new DumbFilter(); break; - case X86Local::MRMDestReg: case X86Local::MRMDestMem: - case X86Local::MRMSrcReg: case X86Local::MRMSrcMem: - case X86Local::MRMXr: case X86Local::MRMXm: - filter = new ModFilter(isRegFormat(Form)); + case X86Local::MRMDestReg: + case X86Local::MRMSrcReg: + case X86Local::MRMSrcReg4VOp3: + case X86Local::MRMSrcRegOp4: + case X86Local::MRMXr: + filter = new ModFilter(true); + break; + case X86Local::MRMDestMem: + case X86Local::MRMSrcMem: + case X86Local::MRMSrcMem4VOp3: + case X86Local::MRMSrcMemOp4: + case X86Local::MRMXm: + filter = new ModFilter(false); break; case X86Local::MRM0r: case X86Local::MRM1r: case X86Local::MRM2r: case X86Local::MRM3r: diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h index f6f5006..2e61158 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -55,14 +55,10 @@ private: bool HasREX_WPrefix; /// The hasVEX_4V field from the record bool HasVEX_4V; - /// The hasVEX_4VOp3 field from the record - bool HasVEX_4VOp3; /// The hasVEX_WPrefix field from the record bool HasVEX_WPrefix; /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set bool HasVEX_LPrefix; - /// The hasMemOp4Prefix field from the record - bool HasMemOp4Prefix; /// The ignoreVEX_L field from the record bool IgnoresVEX_L; /// The hasEVEX_L2Prefix field from the record |