diff options
Diffstat (limited to 'utils/TableGen')
38 files changed, 656 insertions, 500 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1277086..891328f 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -448,7 +448,7 @@ struct MatchableInfo { void formTwoOperandAlias(StringRef Constraint); void initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix); /// validate - Return true if this matchable is a valid thing to match against @@ -565,9 +565,9 @@ struct SubtargetFeatureInfo { Record *TheDef; /// \brief An unique index assigned to represent this feature. - unsigned Index; + uint64_t Index; - SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} /// \brief The name of the enumerated constant identifying this feature. std::string getEnumName() const { @@ -644,7 +644,7 @@ private: /// buildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); + void buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters); /// buildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. @@ -766,7 +766,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } void MatchableInfo::initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix) { AsmVariantID = AsmVariantNo; AsmString = @@ -1075,7 +1075,7 @@ struct LessRegisterSet { }; void AsmMatcherInfo:: -buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { +buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) { const std::vector<CodeGenRegister*> &Registers = Target.getRegBank().getRegisters(); ArrayRef<CodeGenRegisterClass*> RegClassList = @@ -1093,7 +1093,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { (*it)->getOrder().begin(), (*it)->getOrder().end())); // Add any required singleton sets. - for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); @@ -1191,7 +1191,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; ClassInfo *CI = RegisterClasses[Rec]; @@ -1327,10 +1327,10 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - unsigned FeatureNo = SubtargetFeatures.size(); + uint64_t FeatureNo = SubtargetFeatures.size(); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 32 && "Too many subtarget features!"); + assert(FeatureNo < 64 && "Too many subtarget features!"); } // Parse the instructions; we need to do this first so that we can gather the @@ -2205,7 +2205,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, } static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; if (Range > 0xFFFF) return "uint32_t"; if (Range > 0xFF) @@ -2232,7 +2234,7 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2263,7 +2265,7 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap; @@ -2290,9 +2292,9 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; - OS << " unsigned Features = 0;\n"; + OS << " uint64_t Features = 0;\n"; for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { @@ -2446,7 +2448,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "unsigned Features, unsigned VariantID) {\n"; + "uint64_t Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2589,7 +2591,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n"; @@ -2691,7 +2693,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2703,7 +2705,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS.indent(27); OS << "const OperandVector &Operands,\n" << " MCInst &Inst,\n" - << " unsigned &ErrorInfo," + << " uint64_t &ErrorInfo," << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; @@ -2912,7 +2914,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "MatchInstructionImpl(const OperandVector" << " &Operands,\n"; OS << " MCInst &Inst,\n" - << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; + << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; @@ -2922,7 +2924,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() @@ -2938,7 +2940,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " unsigned MissingFeatures = ~0U;\n"; + OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0U;\n"; @@ -3014,10 +3016,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " + OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" - " CountPopulation_32(MissingFeatures))\n"; + OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" + " CountPopulation_64(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; @@ -3055,7 +3057,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; - OS << " Parser.Warning(Loc, Info, None);\n"; + OS << " getParser().Warning(Loc, Info, None);\n"; OS << " }\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index c7fe9df..7ef70d3 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -424,7 +424,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Emit the string itself. - O << " const char AsmStrs[] = {\n"; + O << " static const char AsmStrs[] = {\n"; StringTable.emit(O, printChar); O << " };\n\n"; diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 4cee352..fd77982 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMWRITER_INST_H -#define ASMWRITER_INST_H +#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H +#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H #include <string> #include <vector> diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 5d6d6da..bbed92a 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -69,19 +69,15 @@ SMLoc CTagsEmitter::locate(const Record *R) { } void CTagsEmitter::run(raw_ostream &OS) { - const std::map<std::string, Record *> &Classes = Records.getClasses(); - const std::map<std::string, Record *> &Defs = Records.getDefs(); + const auto &Classes = Records.getClasses(); + const auto &Defs = Records.getDefs(); std::vector<Tag> Tags; // Collect tags. Tags.reserve(Classes.size() + Defs.size()); - for (std::map<std::string, Record *>::const_iterator I = Classes.begin(), - E = Classes.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); - for (std::map<std::string, Record *>::const_iterator I = Defs.begin(), - E = Defs.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); + for (const auto &C : Classes) + Tags.push_back(Tag(C.first, locate(C.second.get()))); + for (const auto &D : Defs) + Tags.push_back(Tag(D.first, locate(D.second.get()))); // Emit tags. std::sort(Tags.begin(), Tags.end()); OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 6d43e8e..6a65e5e 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -35,23 +35,26 @@ private: } // End anonymous namespace void CallingConvEmitter::run(raw_ostream &O) { - std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); - - // Emit prototypes for all of the CC's so that they can forward ref each - // other. + + // Emit prototypes for all of the non-custom CC's so that they can forward ref + // each other. + for (unsigned i = 0, e = CCs.size(); i != e; ++i) { + if (!CCs[i]->getValueAsBit("Custom")) { + O << "static bool " << CCs[i]->getName() + << "(unsigned ValNo, MVT ValVT,\n" + << std::string(CCs[i]->getName().size() + 13, ' ') + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(CCs[i]->getName().size() + 13, ' ') + << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; + } + } + + // Emit each non-custom calling convention description in full. for (unsigned i = 0, e = CCs.size(); i != e; ++i) { - O << "static bool " << CCs[i]->getName() - << "(unsigned ValNo, MVT ValVT,\n" - << std::string(CCs[i]->getName().size()+13, ' ') - << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" - << std::string(CCs[i]->getName().size()+13, ' ') - << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; + if (!CCs[i]->getValueAsBit("Custom")) + EmitCallingConv(CCs[i], O); } - - // Emit each calling convention description in full. - for (unsigned i = 0, e = CCs.size(); i != e; ++i) - EmitCallingConv(CCs[i], O); } @@ -178,13 +181,17 @@ void CallingConvEmitter::EmitAction(Record *Action, if (Size) O << Size << ", "; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," + " "; if (Align) O << Align; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" + "))"; O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; @@ -227,6 +234,21 @@ void CallingConvEmitter::EmitAction(Record *Action, << IndentStr << "else\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; } + } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + MVT::SimpleValueType DestVT = getValueType(DestTy); + O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; + if (MVT(DestVT).isFloatingPoint()) { + PrintFatalError("CCPromoteToUpperBitsInType does not handle floating " + "point"); + } else { + O << IndentStr << "if (ArgFlags.isSExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n" + << IndentStr << "else if (ArgFlags.isZExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n" + << IndentStr << "else\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n"; + } } else if (Action->isSubClassOf("CCBitConvertToType")) { Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 4d0c0ca..11911b6 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -24,14 +24,6 @@ #include <vector> using namespace llvm; -// FIXME: Somewhat hackish to use a command line option for this. There should -// be a CodeEmitter class in the Target.td that controls this sort of thing -// instead. -static cl::opt<bool> -MCEmitter("mc-emitter", - cl::desc("Generate CodeEmitter for use with the MC library."), - cl::init(false)); - namespace { class CodeEmitterGen { @@ -134,15 +126,13 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, if (SO.second == 0) { Case += " // op: " + VarName + "\n" + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } } else { Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } @@ -223,8 +213,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); if (!PostEmitter.empty()) { Case += " Value = " + PostEmitter + "(MI, Value"; - if (MCEmitter) - Case += ", STI"; + Case += ", STI"; Case += ");\n"; } @@ -243,12 +232,9 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit function declaration o << "uint64_t " << Target.getName(); - if (MCEmitter) - o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" - << " SmallVectorImpl<MCFixup> &Fixups,\n" - << " const MCSubtargetInfo &STI) const {\n"; - else - o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl<MCFixup> &Fixups,\n" + << " const MCSubtargetInfo &STI) const {\n"; // Emit instruction base values o << " static const uint64_t InstBits[] = {\n"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 2602bbc..a750aa9 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -771,7 +771,7 @@ static unsigned getPatternSize(const TreePatternNode *P, /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. -unsigned PatternToMatch:: +int PatternToMatch:: getPatternComplexity(const CodeGenDAGPatterns &CGP) const { return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); } @@ -1387,7 +1387,7 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, if (R->isSubClassOf("SubRegIndex")) { assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); - return EEVT::TypeSet(); + return EEVT::TypeSet(MVT::i32, TP); } if (R->isSubClassOf("ValueType")) { @@ -1529,7 +1529,16 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { return false; } +static bool isOperandClass(const TreePatternNode *N, StringRef Class) { + if (!N->isLeaf()) + return N->getOperator()->isSubClassOf(Class); + DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf(Class)) + return true; + + return false; +} /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, flag an error. @@ -1689,6 +1698,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } else if (getOperator()->getName() == "REG_SEQUENCE") { + // We need to do extra, custom typechecking for REG_SEQUENCE since it is + // variadic. + + unsigned NChild = getNumChildren(); + if (NChild < 3) { + TP.error("REG_SEQUENCE requires at least 3 operands!"); + return false; + } + + if (NChild % 2 == 0) { + TP.error("REG_SEQUENCE requires an odd number of operands!"); + return false; + } + + if (!isOperandClass(getChild(0), "RegisterClass")) { + TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); + return false; + } + + for (unsigned I = 1; I < NChild; I += 2) { + TreePatternNode *SubIdxChild = getChild(I + 1); + if (!isOperandClass(SubIdxChild, "SubRegIndex")) { + TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + + itostr(I + 1) + "!"); + return false; + } + } } unsigned ChildNo = 0; @@ -1749,7 +1786,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } - if (ChildNo != getNumChildren()) { + if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { TP.error("Instruction '" + getOperator()->getName() + "' was provided too many operands!"); return false; @@ -1871,7 +1908,7 @@ TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) { +void TreePattern::error(const Twine &Msg) { if (HasError) return; dump(); @@ -2226,13 +2263,6 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : VerifyInstructionFlags(); } -CodeGenDAGPatterns::~CodeGenDAGPatterns() { - for (pf_iterator I = PatternFragments.begin(), - E = PatternFragments.end(); I != E; ++I) - delete I->second; -} - - Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); if (!N || !N->isSubClassOf("SDNode")) { @@ -2294,9 +2324,9 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); TreePattern *P = - new TreePattern(Fragments[i], Tree, - !Fragments[i]->isSubClassOf("OutPatFrag"), *this); - PatternFragments[Fragments[i]] = P; + (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>( + Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"), + *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. std::vector<std::string> &Args = P->getArgList(); @@ -2354,16 +2384,16 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) continue; - TreePattern *ThePat = PatternFragments[Fragments[i]]; - ThePat->InlinePatternFragments(); + TreePattern &ThePat = *PatternFragments[Fragments[i]]; + ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - ThePat->InferAllTypes(); - ThePat->resetError(); + ThePat.InferAllTypes(); + ThePat.resetError(); // If debugging, print out the pattern fragment result. - DEBUG(ThePat->dump()); + DEBUG(ThePat.dump()); } } @@ -3274,14 +3304,14 @@ void CodeGenDAGPatterns::ParsePatterns() { if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + TreePattern Result(CurPattern, LI, false, *this); // Inline pattern fragments into it. - Result->InlinePatternFragments(); + Result.InlinePatternFragments(); - if (Result->getNumTrees() != 1) - Result->error("Cannot handle instructions producing instructions " - "with temporaries yet!"); + if (Result.getNumTrees() != 1) + Result.error("Cannot handle instructions producing instructions " + "with temporaries yet!"); bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; @@ -3294,7 +3324,7 @@ void CodeGenDAGPatterns::ParsePatterns() { // Infer as many types as possible. If we cannot infer all of them, we // can never do anything with this pattern: report it to the user. InferredAllResultTypes = - Result->InferAllTypes(&Pattern->getNamedNodesMap()); + Result.InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; @@ -3302,13 +3332,13 @@ void CodeGenDAGPatterns::ParsePatterns() { // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), Pattern->getTree(0)->getNumTypes()); i != e; ++i) { - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + IterateInference = Pattern->getTree(0)->UpdateNodeType( + i, Result.getTree(0)->getExtType(i), Result); + IterateInference |= Result.getTree(0)->UpdateNodeType( + i, Pattern->getTree(0)->getExtType(i), Result); } // If our iteration has converged and the input pattern's types are fully @@ -3322,8 +3352,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // arbitrary types to the result pattern's nodes. if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) - IterateInference = ForceArbitraryInstResultType(Result->getTree(0), - *Result); + IterateInference = + ForceArbitraryInstResultType(Result.getTree(0), Result); } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -3332,7 +3362,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->error("Could not infer all types in pattern!"); if (!InferredAllResultTypes) { Pattern->dump(); - Result->error("Could not infer all types in pattern result!"); + Result.error("Could not infer all types in pattern result!"); } // Validate that the input pattern is correct. @@ -3345,7 +3375,7 @@ void CodeGenDAGPatterns::ParsePatterns() { InstImpResults); // Promote the xform function to be an explicit node if set. - TreePatternNode *DstPattern = Result->getOnlyTree(); + TreePatternNode *DstPattern = Result.getOnlyTree(); std::vector<TreePatternNode*> ResultNodeOperands; for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); @@ -3357,16 +3387,16 @@ void CodeGenDAGPatterns::ParsePatterns() { } ResultNodeOperands.push_back(OpNode); } - DstPattern = Result->getOnlyTree(); + DstPattern = Result.getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) - DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); - TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index fb30cdd..c0812cf 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_DAGPATTERNS_H -#define CODEGEN_DAGPATTERNS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H +#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" @@ -597,7 +597,7 @@ public: /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. - void error(const std::string &Msg); + void error(const Twine &Msg); bool hasError() const { return HasError; } @@ -667,7 +667,7 @@ public: PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, TreePatternNode *dst, const std::vector<Record*> &dstregs, - unsigned complexity, unsigned uid) + int complexity, unsigned uid) : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} @@ -676,7 +676,7 @@ public: TreePatternNode *SrcPattern; // Source pattern to match. TreePatternNode *DstPattern; // Resulting pattern. std::vector<Record*> Dstregs; // Physical register defs being matched. - unsigned AddedComplexity; // Add to matching pattern complexity. + int AddedComplexity; // Add to matching pattern complexity. unsigned ID; // Unique ID for the record. Record *getSrcRecord() const { return SrcRecord; } @@ -684,13 +684,13 @@ public: TreePatternNode *getSrcPattern() const { return SrcPattern; } TreePatternNode *getDstPattern() const { return DstPattern; } const std::vector<Record*> &getDstRegs() const { return Dstregs; } - unsigned getAddedComplexity() const { return AddedComplexity; } + int getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. - unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; + int getPatternComplexity(const CodeGenDAGPatterns &CGP) const; }; class CodeGenDAGPatterns { @@ -702,7 +702,8 @@ class CodeGenDAGPatterns { std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes; std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms; std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns; - std::map<Record*, TreePattern*, LessRecordByID> PatternFragments; + std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID> + PatternFragments; std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands; std::map<Record*, DAGInstruction, LessRecordByID> Instructions; @@ -716,7 +717,6 @@ class CodeGenDAGPatterns { std::vector<PatternToMatch> PatternsToMatch; public: CodeGenDAGPatterns(RecordKeeper &R); - ~CodeGenDAGPatterns(); CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } @@ -778,15 +778,16 @@ public: // Pattern Fragment information. TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); - return PatternFragments.find(R)->second; + return PatternFragments.find(R)->second.get(); } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return nullptr; - return PatternFragments.find(R)->second; + if (!PatternFragments.count(R)) + return nullptr; + return PatternFragments.find(R)->second.get(); } - typedef std::map<Record*, TreePattern*, LessRecordByID>::const_iterator - pf_iterator; + typedef std::map<Record *, std::unique_ptr<TreePattern>, + LessRecordByID>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } pf_iterator pf_end() const { return PatternFragments.end(); } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 2577ad4..d567dde 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -314,6 +314,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R) hasPostISelHook = R->getValueAsBit("hasPostISelHook"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + isRegSequence = R->getValueAsBit("isRegSequence"); + isExtractSubreg = R->getValueAsBit("isExtractSubreg"); + isInsertSubreg = R->getValueAsBit("isInsertSubreg"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); @@ -520,6 +523,21 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // Bits<n> (also used for 0bxx literals) + if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + if (!BI->isComplete()) + return false; + // Convert the bits init to an integer and use that for the result. + IntInit *II = + dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get())); + if (!II) + return false; + ResOp = ResultOperand(II->getValue()); + return true; + } + // If both are Operands with the same MVT, allow the conversion. It's // up to the user to make sure the values are appropriate, just like // for isel Pat's. diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index f143875..92aac5f 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INSTRUCTION_H -#define CODEGEN_INSTRUCTION_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H +#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" @@ -253,6 +253,9 @@ namespace llvm { bool hasExtraDefRegAllocReq : 1; bool isCodeGenOnly : 1; bool isPseudo : 1; + bool isRegSequence : 1; + bool isExtractSubreg : 1; + bool isInsertSubreg : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index a9ece01..1f1adf1 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INTRINSIC_H -#define CODEGEN_INTRINSIC_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H +#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H #include "llvm/CodeGen/MachineValueType.h" #include <string> diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 8099f13..678222f 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -901,9 +901,8 @@ CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, FindI = SuperRegClasses.find(SubIdx); if (FindI == SuperRegClasses.end()) return; - for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I = - FindI->second.begin(), E = FindI->second.end(); I != E; ++I) - Out.set((*I)->EnumValue); + for (CodeGenRegisterClass *RC : FindI->second) + Out.set(RC->EnumValue); } // Populate a unique sorted list of units from a register set. @@ -967,9 +966,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Compute register name map. for (unsigned i = 0, e = Registers.size(); i != e; ++i) - RegistersByName.GetOrCreateValue( - Registers[i]->TheDef->getValueAsString("AsmName"), - Registers[i]); + // FIXME: This could just be RegistersByName[name] = register, except that + // causes some failures in MIPS - perhaps they have duplicate register name + // entries? (or maybe there's a reason for it - I don't know much about this + // code, just drive-by refactoring) + RegistersByName.insert(std::make_pair( + Registers[i]->TheDef->getValueAsString("AsmName"), Registers[i])); // Precompute all sub-register maps. // This will create Composite entries for all inferred sub-register indices. @@ -1533,7 +1535,7 @@ void CodeGenRegBank::computeRegUnitSets() { assert(RegUnitSets.empty() && "dirty RegUnitSets"); // Compute a unique RegUnitSet for each RegClass. - const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses(); + ArrayRef<CodeGenRegisterClass*> RegClasses = getRegClasses(); unsigned NumRegClasses = RegClasses.size(); for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { if (!RegClasses[RCIdx]->Allocatable) diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 278315b..c1e37fa 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_REGISTERS_H -#define CODEGEN_REGISTERS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H +#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 79d60ac..4cf7b5f 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -182,7 +182,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) { // Recursively find all reachable SchedReadWrite records. static void scanSchedRW(Record *RWDef, RecVec &RWDefs, SmallPtrSet<Record*, 16> &RWSet) { - if (!RWSet.insert(RWDef)) + if (!RWSet.insert(RWDef).second) return; RWDefs.push_back(RWDef); // Reads don't current have sequence records, but it can be added later. @@ -751,7 +751,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { for (ArrayRef<Record*>::const_iterator II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) { unsigned OldSCIdx = InstrClassMap[*II]; - if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) { + if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) { for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 3fef8ad..e5241b9 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_SCHEDULE_H -#define CODEGEN_SCHEDULE_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H +#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index d1b5711..597da68 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -301,7 +301,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", - "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; + "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", + nullptr}; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 5414310..f4e1b6a 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_TARGET_H -#define CODEGEN_TARGET_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H +#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H #include "CodeGenInstruction.h" #include "CodeGenRegisters.h" diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 82682cd..e2e6ab1 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -94,8 +94,8 @@ struct PatternSortingPredicate { // Otherwise, if the patterns might both match, sort based on complexity, // which means that we prefer to match patterns that cover more nodes in the // input over nodes that cover fewer. - unsigned LHSSize = LHS->getPatternComplexity(CGP); - unsigned RHSSize = RHS->getPatternComplexity(CGP); + int LHSSize = LHS->getPatternComplexity(CGP); + int RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index f8f6c54..b9cb267 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -1,4 +1,4 @@ -//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===// +//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_DAGISELMATCHER_H -#define TBLGEN_DAGISELMATCHER_H +#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H +#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 0059570..302f27b 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -630,7 +630,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); I != E; ++I) - PFsByName[I->first->getName()] = I->second; + PFsByName[I->first->getName()] = I->second.get(); if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node,\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 97e37ba..4a73b00 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -718,7 +718,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); - // If we can, get the pattern for the instruction we're generating. We derive + // If we can, get the pattern for the instruction we're generating. We derive // a variety of information from this pattern, such as whether it has a chain. // // FIXME2: This is extremely dubious for several reasons, not the least of @@ -755,16 +755,21 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // the "outs" list. unsigned NumResults = Inst.getNumResults(); - // Loop over all of the operands of the instruction pattern, emitting code - // to fill them all in. The node 'N' usually has number children equal to - // the number of input operands of the instruction. However, in cases - // where there are predicate operands for an instruction, we need to fill - // in the 'execute always' values. Match up the node operands to the - // instruction operands to do this. + // Number of operands we know the output instruction must have. If it is + // variadic, we could have more operands. + unsigned NumFixedOperands = II.Operands.size(); + SmallVector<unsigned, 8> InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); - InstOpNo != e; ++InstOpNo) { + // Loop over all of the fixed operands of the instruction pattern, emitting + // code to fill them all in. The node 'N' usually has number children equal to + // the number of input operands of the instruction. However, in cases where + // there are predicate operands for an instruction, we need to fill in the + // 'execute always' values. Match up the node operands to the instruction + // operands to do this. + unsigned ChildNo = 0; + for (unsigned InstOpNo = NumResults, e = NumFixedOperands; + InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; if (OperandNode->isSubClassOf("OperandWithDefaultOps") && @@ -807,6 +812,16 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, } } + // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't + // expand suboperands, use default operands, or other features determined from + // the CodeGenInstruction after the fixed operands, which were handled + // above. Emit the remaining instructions implicitly added by the use for + // variable_ops. + if (II.Operands.isVariadic) { + for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I) + EmitResultOperand(N->getChild(I), InstOps); + } + // If this node has input glue or explicitly specified input physregs, we // need to add chained and glued copyfromreg nodes and materialize the glue // input. @@ -852,7 +867,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // gets the excess operands from the input DAG. int NumFixedArityOperands = -1; if (isRoot && - (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) + Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); // If this is the root node and multiple matched nodes in the input pattern diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 0b117eb..7a22764 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -185,7 +185,7 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, /// Conceptually, we'd like to sink these predicates all the way to the last /// matcher predicate in the series. However, it turns out that some /// ComplexPatterns have side effects on the graph, so we really don't want to -/// run a the complex pattern if the pattern predicate will fail. For this +/// run a complex pattern if the pattern predicate will fail. For this /// reason, we refuse to sink the pattern predicate past a ComplexPattern. /// static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) { @@ -400,7 +400,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { } if (NewOptionsToMatch.empty()) { - MatcherPtr.reset(nullptr); + MatcherPtr.reset(); return; } @@ -454,7 +454,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]); - assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + assert(Opcodes.insert(COM->getOpcode().getEnumName()).second && "Duplicate opcodes not factored?"); Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 154f96d..748c923 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -19,6 +19,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" @@ -36,6 +37,7 @@ struct InstructionMemo { const CodeGenRegisterClass *RC; std::string SubRegNo; std::vector<std::string>* PhysRegs; + std::string PredicateCheck; }; } // End anonymous namespace @@ -347,7 +349,7 @@ struct OperandsSignature { // Implicit physical register operand. e.g. Instruction::Mul expect to // select to a binary op. On x86, mul may take a single operand with // the other operand being implicit. We must emit something that looks - // like a binary instruction except for the very inner FastEmitInst_* + // like a binary instruction except for the very inner fastEmitInst_* // call. continue; Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); @@ -364,7 +366,9 @@ struct OperandsSignature { namespace { class FastISelMap { - typedef std::map<std::string, InstructionMemo> PredMap; + // A multimap is needed instead of a "plain" map because the key is + // the instruction's complexity (an int) and they are not unique. + typedef std::multimap<int, InstructionMemo> PredMap; typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap; typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap; typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap; @@ -373,6 +377,16 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + // This is used to check that there are no duplicate predicates + typedef std::multimap<std::string, bool> PredCheckMap; + typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap; + typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap; + typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap; + typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap> + OperandsOpcodeTypeRetPredCheckMap; + + OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck; + std::map<OperandsSignature, std::vector<OperandsSignature> > SignaturesWithConstantForms; @@ -384,6 +398,11 @@ public: void collectPatterns(CodeGenDAGPatterns &CGP); void printImmediatePredicates(raw_ostream &OS); void printFunctionDefinitions(raw_ostream &OS); +private: + void emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName); }; } // End anonymous namespace @@ -541,6 +560,17 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { continue; } + // Check if the operands match one of the patterns handled by FastISel. + std::string ManglingSuffix; + raw_string_ostream SuffixOS(ManglingSuffix); + Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true); + SuffixOS.flush(); + if (!StringSwitch<bool>(ManglingSuffix) + .Cases("", "r", "rr", "ri", "rf", true) + .Cases("rri", "i", "f", true) + .Default(false)) + continue; + // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -549,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { Pattern.getDstPattern()->getOperator()->getName(), DstRC, SubRegNo, - PhysRegInputs + PhysRegInputs, + PredicateCheck }; + + int complexity = Pattern.getPatternComplexity(CGP); - if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + if (SimplePatternsCheck[Operands][OpcodeName][VT] + [RetVT].count(PredicateCheck)) { PrintFatalError(Pattern.getSrcRecord()->getLoc(), - "Duplicate record in FastISel table!"); + "Duplicate predicate in FastISel table!"); + } + SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(PredicateCheck, true)); - SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + // Note: Instructions with the same complexity will appear in the order + // that they are encountered. + SimplePatterns[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(complexity, Memo)); // If any of the operands were immediates with predicates on them, strip // them down to a signature that doesn't have predicates so that we can @@ -582,6 +622,72 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) { OS << "\n\n"; } +void FastISelMap::emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName) { + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. A reverse iterator + // is used to produce the ones with highest complexity first. + + bool OneHadNoPredicate = false; + for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend(); + PI != PE; ++PI) { + const InstructionMemo &Memo = PI->second; + std::string PredicateCheck = Memo.PredicateCheck; + + if (PredicateCheck.empty()) { + assert(!OneHadNoPredicate && + "Multiple instructions match and more than one had " + "no predicate!"); + OneHadNoPredicate = true; + } else { + if (OneHadNoPredicate) { + // FIXME: This should be a PrintError once the x86 target + // fixes PR21575. + PrintWarning("Multiple instructions match and one with no " + "predicate came before one with a predicate! " + "name:" + Memo.Name + " predicate: " + + PredicateCheck); + } + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return fastEmitInst_"; + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(" << RetVTName + << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; + } + + if (!PredicateCheck.empty()) { + OS << " }\n"; + } + } + // Return 0 if all of the possibilities had predicates but none + // were satisfied. + if (!OneHadNoPredicate) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; +} + void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. @@ -608,9 +714,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; const PredMap &PM = RI->second; - bool HasPred = false; - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; @@ -619,58 +724,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { Operands.PrintParameters(OS); OS << ") {\n"; - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); - PI != PE; ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; - } - - if (HasPred) - OS << " }\n"; - - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, getName(RetVT)); } // Emit one function for the type that demultiplexes on return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -682,7 +740,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; - OS << " case " << getName(RetVT) << ": return FastEmit_" + OS << " case " << getName(RetVT) << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -694,7 +752,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { } else { // Non-variadic return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -708,63 +766,13 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { << ")\n return 0;\n"; const PredMap &PM = RM.begin()->second; - bool HasPred = false; - - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; - ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(RetVT, Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; - } - - if (HasPred) - OS << " }\n"; - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, "RetVT"); } } // Emit one function for the opcode that demultiplexes based on the type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; @@ -777,7 +785,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { TI != TE; ++TI) { MVT::SimpleValueType VT = TI->first; std::string TypeName = getName(VT); - OS << " case " << TypeName << ": return FastEmit_" + OS << " case " << TypeName << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; @@ -797,13 +805,16 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. - OS << "unsigned FastEmit_"; + OS << "unsigned fastEmit_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); - OS << ") {\n"; + OS << ") "; + if (!Operands.hasAnyImmediateCodes()) + OS << "override "; + OS << "{\n"; // If there are any forms of this signature available that operate on // constrained forms of the immediate (e.g., 32-bit sext immediate in a @@ -823,7 +834,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { OS << " if ("; MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); - OS << ")\n if (unsigned Reg = FastEmit_"; + OS << ")\n if (unsigned Reg = fastEmit_"; MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT, Opcode"; if (!MI->second[i].empty()) @@ -841,7 +852,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { I != E; ++I) { const std::string &Opcode = I->first; - OS << " case " << Opcode << ": return FastEmit_" + OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 42639cc..bd83b6c 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -230,7 +230,7 @@ protected: std::vector<unsigned> VariableInstructions; // Map of well-known segment value to its delegate. - std::map<unsigned, const FilterChooser*> FilterChooserMap; + std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -252,7 +252,7 @@ public: return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(const Filter &f); + Filter(Filter &&f); Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); ~Filter(); @@ -333,13 +333,9 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; + FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; + void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; public: - FilterChooser(const FilterChooser &FC) - : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), - Operands(FC.Operands), Filters(FC.Filters), - FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), - BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), - Emitter(FC.Emitter) { } FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs, @@ -347,10 +343,8 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { - for (unsigned i = 0; i < BitWidth; ++i) - FilterBitValues.push_back(BIT_UNFILTERED); - + FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), + BitWidth(BW), Emitter(E) { doFilter(); } @@ -490,11 +484,11 @@ public: // // /////////////////////////// -Filter::Filter(const Filter &f) +Filter::Filter(Filter &&f) : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + FilteredInstructions(std::move(f.FilteredInstructions)), + VariableInstructions(std::move(f.VariableInstructions)), + FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) { } @@ -534,12 +528,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map<unsigned, const FilterChooser*>::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } } // Divides the decoding task into sub tasks and delegates them to the @@ -561,14 +549,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert( + std::make_pair(-1U, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, VariableInstructions, + Owner->Operands, BitValueArray, *Owner))); } // No need to recurse for a singleton filtered instruction. @@ -594,14 +578,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert(std::make_pair( + mapIterator->first, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, mapIterator->second, + Owner->Operands, BitValueArray, *Owner))); } } @@ -636,7 +616,8 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // A new filter entry begins a new scope for fixup resolution. TableInfo.FixupStack.push_back(FixupList()); - std::map<unsigned, const FilterChooser*>::const_iterator filterIterator; + std::map<unsigned, + std::unique_ptr<const FilterChooser>>::const_iterator filterIterator; DecoderTable &Table = TableInfo.Table; @@ -1066,19 +1047,17 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, const OperandInfo &OpInfo) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() == 1) { - OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << "tmp = fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; - } else { + if (OpInfo.numFields() != 1) o.indent(Indentation) << "tmp = 0;\n"; - for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); - OI != OE; ++OI) { - o.indent(Indentation) << "tmp |= (fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ") << " << OI->Offset << ");\n"; - } + + for (const EncodingField &EF : OpInfo) { + o.indent(Indentation) << "tmp "; + if (OpInfo.numFields() != 1) o << '|'; + o << "= fieldFromInstruction" + << "(insn, " << EF.Base << ", " << EF.Width << ')'; + if (OpInfo.numFields() != 1 || EF.Offset != 0) + o << " << " << EF.Offset; + o << ";\n"; } if (Decoder != "") @@ -1384,8 +1363,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, bool mixed) { Filters.clear(); - Filter F(*this, startBit, numBit, true); - Filters.push_back(F); + Filters.push_back(Filter(*this, startBit, numBit, true)); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 76f05ce..6fdf22d 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -266,6 +266,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; OS << "namespace llvm {"; OS << "namespace " << Namespace << " {\n"; + OS << "LLVM_READONLY\n"; OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; if (!Operands.empty()) { OS << " static const int16_t OperandMap [][" << Operands.size() @@ -504,6 +505,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; + if (Inst.isRegSequence) OS << "|(1<<MCID::RegSequence)"; + if (Inst.isExtractSubreg) OS << "|(1<<MCID::ExtractSubreg)"; + if (Inst.isInsertSubreg) OS << "|(1<<MCID::InsertSubreg)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 430ef32..37f6de0 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -129,8 +129,9 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, for (unsigned i = 0, e = Ints.size(); i != e; ++i) { OS << " " << Ints[i].EnumName; OS << ((i != e-1) ? ", " : " "); - OS << std::string(40-Ints[i].EnumName.size(), ' ') - << "// " << Ints[i].Name << "\n"; + if (Ints[i].EnumName.size() < 40) + OS << std::string(40-Ints[i].EnumName.size(), ' '); + OS << " // " << Ints[i].Name << "\n"; } OS << "#endif\n\n"; } @@ -243,19 +244,20 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29 }; @@ -355,6 +357,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case 8: Sig.push_back(IIT_V8); break; case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; + case 64: Sig.push_back(IIT_V64); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -679,8 +682,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " - "NumAttrs));\n"; + OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index c5fd7ee..9262d7c 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -221,9 +221,11 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { // The containing option group (if any). OS << ", "; - if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) + const ListInit *GroupFlags = nullptr; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { + GroupFlags = DI->getDef()->getValueAsListInit("Flags"); OS << getOptionName(*DI->getDef()); - else + } else OS << "INVALID"; // The option alias (if any). @@ -249,17 +251,19 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { } // The option flags. + OS << ", "; + int NumFlags = 0; const ListInit *LI = R.getValueAsListInit("Flags"); - if (LI->empty()) { - OS << ", 0"; - } else { - OS << ", "; - for (unsigned i = 0, e = LI->size(); i != e; ++i) { - if (i) - OS << " | "; - OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); - } + for (Init *I : *LI) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); + if (GroupFlags) { + for (Init *I : *GroupFlags) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); } + if (NumFlags == 0) + OS << '0'; // The option parameter field. OS << ", " << R.getValueAsInt("NumArgs"); diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 3b74ac4..ebb43f0 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -277,11 +277,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) { assert(InstructionClass && "Instruction class definition missing!"); std::vector<Record*> Insts; - for (std::map<std::string, Record*>::const_iterator I = - Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { - if (I->second->isSubClassOf(ExpansionClass) && - I->second->isSubClassOf(InstructionClass)) - Insts.push_back(I->second); + for (const auto &D : Records.getDefs()) { + if (D.second->isSubClassOf(ExpansionClass) && + D.second->isSubClassOf(InstructionClass)) + Insts.push_back(D.second.get()); } // Process the pseudo expansion definitions, validating them as we do so. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 573c37f..79d08a9 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -379,9 +379,9 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; if (!isCtor) - OS << " = sizeof(" << Namespace + OS << " = array_lengthof(" << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + << "Dwarf2L);\n\n"; else OS << ";\n\n"; } @@ -427,9 +427,8 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; if (!isCtor) - OS << " = sizeof(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + OS << " = array_lengthof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; else OS << ";\n\n"; } @@ -848,6 +847,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; + SequenceToOffsetTable<std::string> RegClassStrings; + // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; @@ -856,6 +857,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); + RegClassStrings.add(Name); + // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const MCPhysReg " << Name @@ -880,6 +883,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + RegClassStrings.layout(); + OS << "extern const char " << TargetName << "RegClassStrings[] = {\n"; + RegClassStrings.emit(OS, printChar); + OS << "};\n\n"; + OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; @@ -892,8 +900,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); - OS << " { " << '\"' << RC.getName() << "\", " - << RC.getName() << ", " << RC.getName() << "Bits, " + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " @@ -934,10 +942,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " << (SubRegIndices.size() + 1) << ",\n" << TargetName << "SubRegIdxRanges, " - << " " << TargetName << "RegEncodingTable);\n\n"; + << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); @@ -1267,6 +1276,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; + OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " @@ -1289,6 +1299,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" << " " << TargetName << "RegStrings,\n" + << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" << " " << SubRegIndices.size() + 1 << ",\n" << " " << TargetName << "SubRegIdxRanges,\n" diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index e6ab664..b58de4c 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H -#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H +#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H #include "llvm/Support/raw_ostream.h" #include <algorithm> diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 06f8694..9f2fc92 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -386,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), PE = SchedModels.procModelEnd(); PI != PE; ++PI) { - if (!ItinsDefSet.insert(PI->ItinsDef)) + if (!ItinsDefSet.insert(PI->ItinsDef).second) continue; std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); @@ -565,7 +565,7 @@ EmitItineraries(raw_ostream &OS, PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { Record *ItinsDef = PI->ItinsDef; - if (!ItinsDefSet.insert(ItinsDef)) + if (!ItinsDefSet.insert(ItinsDef).second) continue; // Get processor itinerary name @@ -575,12 +575,13 @@ EmitItineraries(raw_ostream &OS, assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); std::vector<InstrItinerary> &ItinList = *ProcItinListsIter; + // Empty itineraries aren't referenced anywhere in the tablegen output + // so don't emit them. + if (ItinList.empty()) + continue; + OS << "\n"; OS << "static const llvm::InstrItinerary "; - if (ItinList.empty()) { - OS << '*' << Name << " = nullptr;\n"; - continue; - } // Begin processor itinerary table OS << Name << "[] = {\n"; @@ -1192,7 +1193,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { // Begin processor itinerary properties OS << "\n"; - OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; + OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); @@ -1201,6 +1202,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); OS << " " << (bool)(PI->ModelDef ? + PI->ModelDef->getValueAsBit("PostRAScheduler") : 0) + << ", // " << "PostRAScheduler\n"; + + OS << " " << (bool)(PI->ModelDef ? PI->ModelDef->getValueAsBit("CompleteModel") : 0) << ", // " << "CompleteModel\n"; @@ -1213,10 +1218,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraries()) - OS << " " << PI->ItinsDef->getName() << ");\n"; + if (PI->hasItineraries()) + OS << " " << PI->ItinsDef->getName() << "};\n"; else - OS << " 0); // No Itinerary\n"; + OS << " nullptr}; // No Itinerary\n"; } } diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 28b626e..2dc03ce 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -13,6 +13,8 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H +#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H // A TableGen backend is a function that looks like // @@ -78,3 +80,5 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace + +#endif diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 9e79b9c..5895277 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERSHARED_H -#define X86DISASSEMBLERSHARED_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H #include <string.h> #include <string> diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index fbcc6f2..d7e981c 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -171,12 +171,17 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_OPSIZE: return inheritsFrom(child, IC_EVEX_W_OPSIZE) || inheritsFrom(child, IC_EVEX_L_W_OPSIZE); + case IC_EVEX_B: + return false; case IC_EVEX_W: case IC_EVEX_W_XS: case IC_EVEX_W_XD: case IC_EVEX_W_OPSIZE: return false; case IC_EVEX_L: + case IC_EVEX_L_K_B: + case IC_EVEX_L_KZ_B: + case IC_EVEX_L_B: case IC_EVEX_L_XS: case IC_EVEX_L_XD: case IC_EVEX_L_OPSIZE: @@ -205,38 +210,59 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_XD_K: return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_K_B: + case IC_EVEX_KZ: + return false; + case IC_EVEX_XS_KZ: + return inheritsFrom(child, IC_EVEX_W_XS_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XS_KZ); + case IC_EVEX_XD_KZ: + return inheritsFrom(child, IC_EVEX_W_XD_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XD_KZ); + case IC_EVEX_KZ_B: case IC_EVEX_OPSIZE_K: case IC_EVEX_OPSIZE_B: + case IC_EVEX_OPSIZE_K_B: + case IC_EVEX_OPSIZE_KZ: + case IC_EVEX_OPSIZE_KZ_B: return false; case IC_EVEX_W_K: case IC_EVEX_W_XS_K: case IC_EVEX_W_XD_K: case IC_EVEX_W_OPSIZE_K: case IC_EVEX_W_OPSIZE_B: + case IC_EVEX_W_OPSIZE_K_B: return false; case IC_EVEX_L_K: case IC_EVEX_L_XS_K: case IC_EVEX_L_XD_K: case IC_EVEX_L_OPSIZE_K: + case IC_EVEX_L_OPSIZE_B: + case IC_EVEX_L_OPSIZE_K_B: return false; case IC_EVEX_W_KZ: case IC_EVEX_W_XS_KZ: case IC_EVEX_W_XD_KZ: case IC_EVEX_W_OPSIZE_KZ: + case IC_EVEX_W_OPSIZE_KZ_B: return false; case IC_EVEX_L_KZ: case IC_EVEX_L_XS_KZ: case IC_EVEX_L_XD_KZ: case IC_EVEX_L_OPSIZE_KZ: + case IC_EVEX_L_OPSIZE_KZ_B: return false; case IC_EVEX_L_W_K: case IC_EVEX_L_W_XS_K: case IC_EVEX_L_W_XD_K: case IC_EVEX_L_W_OPSIZE_K: + case IC_EVEX_L_W_OPSIZE_B: + case IC_EVEX_L_W_OPSIZE_K_B: case IC_EVEX_L_W_KZ: case IC_EVEX_L_W_XS_KZ: case IC_EVEX_L_W_XD_KZ: case IC_EVEX_L_W_OPSIZE_KZ: + case IC_EVEX_L_W_OPSIZE_KZ_B: return false; case IC_EVEX_L2_K: case IC_EVEX_L2_B: diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index 1327375..d86b926 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERTABLES_H -#define X86DISASSEMBLERTABLES_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #include "X86DisassemblerShared.h" #include "X86ModRMFilters.h" diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index fac3838..d919c58 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86MODRMFILTERS_H -#define X86MODRMFILTERS_H +#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H +#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H #include "llvm/Support/DataTypes.h" diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index ead419e..9b8092f 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -32,48 +32,50 @@ using namespace llvm; MAP(C9, 38) \ MAP(CA, 39) \ MAP(CB, 40) \ - MAP(D0, 41) \ - MAP(D1, 42) \ - MAP(D4, 43) \ - MAP(D5, 44) \ - MAP(D6, 45) \ - MAP(D8, 46) \ - MAP(D9, 47) \ - MAP(DA, 48) \ - MAP(DB, 49) \ - MAP(DC, 50) \ - MAP(DD, 51) \ - MAP(DE, 52) \ - MAP(DF, 53) \ - MAP(E0, 54) \ - MAP(E1, 55) \ - MAP(E2, 56) \ - MAP(E3, 57) \ - MAP(E4, 58) \ - MAP(E5, 59) \ - MAP(E8, 60) \ - MAP(E9, 61) \ - MAP(EA, 62) \ - MAP(EB, 63) \ - MAP(EC, 64) \ - MAP(ED, 65) \ - MAP(EE, 66) \ - MAP(F0, 67) \ - MAP(F1, 68) \ - MAP(F2, 69) \ - MAP(F3, 70) \ - MAP(F4, 71) \ - MAP(F5, 72) \ - MAP(F6, 73) \ - MAP(F7, 74) \ - MAP(F8, 75) \ - MAP(F9, 76) \ - MAP(FA, 77) \ - MAP(FB, 78) \ - MAP(FC, 79) \ - MAP(FD, 80) \ - MAP(FE, 81) \ - MAP(FF, 82) + MAP(CF, 41) \ + MAP(D0, 42) \ + MAP(D1, 43) \ + MAP(D4, 44) \ + MAP(D5, 45) \ + MAP(D6, 46) \ + MAP(D7, 47) \ + MAP(D8, 48) \ + MAP(D9, 49) \ + MAP(DA, 50) \ + MAP(DB, 51) \ + MAP(DC, 52) \ + MAP(DD, 53) \ + MAP(DE, 54) \ + MAP(DF, 55) \ + MAP(E0, 56) \ + MAP(E1, 57) \ + MAP(E2, 58) \ + MAP(E3, 59) \ + MAP(E4, 60) \ + MAP(E5, 61) \ + MAP(E8, 62) \ + MAP(E9, 63) \ + MAP(EA, 64) \ + MAP(EB, 65) \ + MAP(EC, 66) \ + MAP(ED, 67) \ + MAP(EE, 68) \ + MAP(F0, 69) \ + MAP(F1, 70) \ + MAP(F2, 71) \ + MAP(F3, 72) \ + MAP(F4, 73) \ + MAP(F5, 74) \ + MAP(F6, 75) \ + MAP(F7, 76) \ + MAP(F8, 77) \ + MAP(F9, 78) \ + MAP(FA, 79) \ + MAP(FB, 80) \ + MAP(FC, 81) \ + MAP(FD, 82) \ + MAP(FE, 83) \ + MAP(FF, 84) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -205,6 +207,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasEVEX_B = Rec->getValueAsBit("hasEVEX_B"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); ForceDisassemble = Rec->getValueAsBit("ForceDisassemble"); + CD8_Scale = byteFromRec(Rec, "CD8_Scale"); Name = Rec->getName(); AsmString = Rec->getValueAsString("AsmString"); @@ -441,6 +444,16 @@ InstructionContext RecognizableInstr::insnContext() const { return insnContext; } +void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) { + // The scaling factor for AVX512 compressed displacement encoding is an + // instruction attribute. Adjust the ModRM encoding type to include the + // scale for compressed displacement. + if (encoding != ENCODING_RM || CD8_Scale == 0) + return; + encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale)); + assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling"); +} + void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, unsigned &physicalOperandIndex, unsigned &numPhysicalOperands, @@ -464,8 +477,10 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); - Spec->operands[operandIndex].encoding = encodingFromString(typeName, - OpSize); + OperandEncoding encoding = encodingFromString(typeName, OpSize); + // Adjust the encoding type for an operand based on the instruction. + adjustOperandEncoding(encoding); + Spec->operands[operandIndex].encoding = encoding; Spec->operands[operandIndex].type = typeFromString(typeName, HasREX_WPrefix, OpSize); @@ -526,6 +541,14 @@ void RecognizableInstr::emitInstructionSpecifier() { // physicalOperandIndex should always be < numPhysicalOperands unsigned physicalOperandIndex = 0; + // Given the set of prefix bits, how many additional operands does the + // instruction have? + unsigned additionalOperands = 0; + if (HasVEX_4V || HasVEX_4VOp3) + ++additionalOperands; + if (HasEVEX_K) + ++additionalOperands; + switch (Form) { default: llvm_unreachable("Unhandled form"); case X86Local::RawFrmSrc: @@ -560,17 +583,17 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. + // - In AVX512 there may be a mask operand here - // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestRegFrm"); HANDLE_OPERAND(rmRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded @@ -585,12 +608,10 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); + HANDLE_OPERAND(memory) if (HasEVEX_K) @@ -611,12 +632,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 3 (optional) is an immediate. // Operand 4 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMSrcRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) @@ -647,12 +665,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) @@ -685,15 +700,13 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5r: case X86Local::MRM6r: case X86Local::MRM7r: - { - // Operand 1 is a register operand in the R/M field. - // Operand 2 (optional) is an immediate or relocation. - // Operand 3 (optional) is an immediate. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands > 3 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnr"); - } + // Operand 1 is a register operand in the R/M field. + // Operand 2 (optional) is an immediate or relocation. + // Operand 3 (optional) is an immediate. + assert(numPhysicalOperands >= 0 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMnr"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) @@ -712,15 +725,12 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5m: case X86Local::MRM6m: case X86Local::MRM7m: - { - // Operand 1 is a memory operand (possibly SIB-extended) - // Operand 2 (optional) is an immediate or relocation. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands < 1 + kOp + Op4v || - numPhysicalOperands > 2 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnm"); - } + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 (optional) is an immediate or relocation. + assert(numPhysicalOperands >= 1 + additionalOperands && + numPhysicalOperands <= 2 + additionalOperands && + "Unexpected number of operands for MRMnm"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) @@ -756,20 +766,21 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2: case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8: case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB: - case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4: - case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8: - case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB: - case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE: - case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1: - case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4: - case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9: - case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC: - case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0: - case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3: - case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6: - case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA: - case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD: - case X86Local::MRM_FE: case X86Local::MRM_FF: + case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1: + case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6: + case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9: + case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC: + case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF: + case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2: + case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5: + case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA: + case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED: + case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1: + case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4: + case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7: + case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB: + case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE: + case X86Local::MRM_FF: // Ignored. break; } @@ -896,7 +907,6 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) - TYPE("u32u8imm", TYPE_IMM32) TYPE("GR32", TYPE_R32) TYPE("GR32orGR64", TYPE_R32) TYPE("i64mem", TYPE_Mv) @@ -962,10 +972,18 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("VR512", TYPE_XMM512) TYPE("VK1", TYPE_VK1) TYPE("VK1WM", TYPE_VK1) + TYPE("VK2", TYPE_VK2) + TYPE("VK2WM", TYPE_VK2) + TYPE("VK4", TYPE_VK4) + TYPE("VK4WM", TYPE_VK4) TYPE("VK8", TYPE_VK8) TYPE("VK8WM", TYPE_VK8) TYPE("VK16", TYPE_VK16) TYPE("VK16WM", TYPE_VK16) + TYPE("VK32", TYPE_VK32) + TYPE("VK32WM", TYPE_VK32) + TYPE("VK64", TYPE_VK64) + TYPE("VK64WM", TYPE_VK64) TYPE("GR16_NOAX", TYPE_Rv) TYPE("GR32_NOAX", TYPE_Rv) TYPE("GR64_NOAX", TYPE_R64) @@ -991,7 +1009,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) - ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) @@ -1038,6 +1055,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VK1", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) + ENCODING("VK32", ENCODING_RM) + ENCODING("VK64", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -1064,8 +1083,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("FR32X", ENCODING_REG) ENCODING("VR512", ENCODING_REG) ENCODING("VK1", ENCODING_REG) + ENCODING("VK2", ENCODING_REG) + ENCODING("VK4", ENCODING_REG) ENCODING("VK8", ENCODING_REG) ENCODING("VK16", ENCODING_REG) + ENCODING("VK32", ENCODING_REG) + ENCODING("VK64", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) @@ -1088,8 +1111,12 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("VR256X", ENCODING_VVVV) ENCODING("VR512", ENCODING_VVVV) ENCODING("VK1", ENCODING_VVVV) + ENCODING("VK2", ENCODING_VVVV) + ENCODING("VK4", ENCODING_VVVV) ENCODING("VK8", ENCODING_VVVV) ENCODING("VK16", ENCODING_VVVV) + ENCODING("VK32", ENCODING_VVVV) + ENCODING("VK64", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } @@ -1098,8 +1125,12 @@ OperandEncoding RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s, uint8_t OpSize) { ENCODING("VK1WM", ENCODING_WRITEMASK) + ENCODING("VK2WM", ENCODING_WRITEMASK) + ENCODING("VK4WM", ENCODING_WRITEMASK) ENCODING("VK8WM", ENCODING_WRITEMASK) ENCODING("VK16WM", ENCODING_WRITEMASK) + ENCODING("VK32WM", ENCODING_WRITEMASK) + ENCODING("VK64WM", ENCODING_WRITEMASK) errs() << "Unhandled mask register encoding " << s << "\n"; llvm_unreachable("Unhandled mask register encoding"); } diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 77286bc..95d7a40 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86RECOGNIZABLEINSTR_H -#define X86RECOGNIZABLEINSTR_H +#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H +#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H #include "CodeGenTarget.h" #include "X86DisassemblerTables.h" @@ -78,6 +78,8 @@ private: bool IsCodeGenOnly; /// The ForceDisassemble field from the record bool ForceDisassemble; + // The CD8_Scale field from the record + uint8_t CD8_Scale; // Whether the instruction has the predicate "In64BitMode" bool Is64Bit; // Whether the instruction has the predicate "In32BitMode" @@ -153,6 +155,9 @@ private: static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s, uint8_t OpSize); + /// \brief Adjust the encoding type for an operand based on the instruction. + void adjustOperandEncoding(OperandEncoding &encoding); + /// handleOperand - Converts a single operand from the LLVM table format to /// the emitted table format, handling any duplicate operands it encounters /// and then one non-duplicate. |