diff options
Diffstat (limited to 'contrib/llvm/utils')
41 files changed, 1247 insertions, 1496 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index ee83311..6faf819 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -100,9 +100,9 @@ #include "StringToOffsetTable.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -958,8 +958,12 @@ static std::string getEnumNameForToken(StringRef Str) { case ':': Res += "_COLON_"; break; case '!': Res += "_EXCLAIM_"; break; case '.': Res += "_DOT_"; break; + case '<': Res += "_LT_"; break; + case '>': Res += "_GT_"; break; default: - if (isalnum(*it)) + if ((*it >= 'A' && *it <= 'Z') || + (*it >= 'a' && *it <= 'z') || + (*it >= '0' && *it <= '9')) Res += *it; else Res += "_" + utostr((unsigned) *it) + "_"; @@ -1723,7 +1727,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, << " default: llvm_unreachable(\"invalid conversion entry!\");\n" << " case CVT_Reg:\n" << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" + << " Operands[*(p + 1)]->setConstraint(\"r\");\n" << " ++NumMCOperands;\n" << " break;\n" << " case CVT_Tied:\n" @@ -1754,7 +1758,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Remember this converter for the kind enum. unsigned KindID = OperandConversionKinds.size(); - OperandConversionKinds.insert("CVT_" + AsmMatchConverter); + OperandConversionKinds.insert("CVT_" + + getEnumNameForToken(AsmMatchConverter)); // Add the converter row for this instruction. ConversionTable.push_back(std::vector<uint8_t>()); @@ -1762,7 +1767,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, ConversionTable.back().push_back(CVT_Done); // Add the handler to the conversion driver function. - CvtOS << " case CVT_" << AsmMatchConverter << ":\n" + CvtOS << " case CVT_" + << getEnumNameForToken(AsmMatchConverter) << ":\n" << " " << AsmMatchConverter << "(Inst, Operands);\n" << " break;\n"; @@ -1800,6 +1806,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // the index of its entry in the vector). std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" : Op.Class->RenderMethod); + Name = getEnumNameForToken(Name); bool IsNewConverter = false; unsigned ID = getConverterOperandID(Name, OperandConversionKinds, @@ -1823,9 +1830,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Add a handler for the operand number lookup. OpOS << " case " << Name << ":\n" - << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" - << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" + << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"; + + if (Op.Class->isRegisterClass()) + OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n"; + else + OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n"; + OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" << " break;\n"; break; } @@ -2867,6 +2878,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "(MatchClassKind)it->Classes[i]);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; + OS << " // If the generic handler indicates an invalid operand\n"; + OS << " // failure, check for a special case.\n"; + OS << " if (Diag == Match_InvalidOperand) {\n"; + OS << " Diag = validateTargetOperandClass(Operands[i+1],\n"; + OS.indent(43); + OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " if (Diag == Match_Success)\n"; + OS << " continue;\n"; + OS << " }\n"; OS << " // If this operand is broken for all of the instances of this\n"; OS << " // mnemonic, keep track of it so we can report loc info.\n"; OS << " // If we already had a match that only failed due to a\n"; diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index a4114d9..ac8d896 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -842,8 +842,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!IAP->isOpMapped(ROName)) { IAP->addOperand(ROName, i); + Record *R = CGA->ResultOperands[i].getRecord(); + if (R->isSubClassOf("RegisterOperand")) + R = R->getValueAsDef("RegClass"); Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + - CGA->ResultOperands[i].getRecord()->getName() + "RegClassID)" + R->getName() + "RegClassID)" ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; IAP->addCond(Cond); } else { @@ -863,12 +866,18 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; } - case CodeGenInstAlias::ResultOperand::K_Imm: - Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getImm() == " + - llvm::utostr(CGA->ResultOperands[i].getImm()); + case CodeGenInstAlias::ResultOperand::K_Imm: { + std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")"; + + // Just because the alias has an immediate result, doesn't mean the + // MCInst will. An MCExpr could be present, for example. + IAP->addCond(Op + ".isImm()"); + + Cond = Op + ".getImm() == " + + llvm::utostr(CGA->ResultOperands[i].getImm()); IAP->addCond(Cond); break; + } case CodeGenInstAlias::ResultOperand::K_Reg: // If this is zero_reg, something's playing tricks we're not // equipped to handle. diff --git a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp new file mode 100644 index 0000000..8bf7778 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp @@ -0,0 +1,99 @@ +//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits an index of definitions in ctags(1) format. +// A helper script, utils/TableGen/tdtags, provides an easier-to-use +// interface; run 'tdtags -H' for documentation. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ctags-emitter" + +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <algorithm> +#include <string> +#include <vector> +using namespace llvm; + +namespace llvm { extern SourceMgr SrcMgr; } + +namespace { + +class Tag { +private: + const std::string *Id; + SMLoc Loc; +public: + Tag(const std::string &Name, const SMLoc Location) + : Id(&Name), Loc(Location) {} + int operator<(const Tag &B) const { return *Id < *B.Id; } + void emit(raw_ostream &OS) const { + int BufferID = SrcMgr.FindBufferContainingLoc(Loc); + MemoryBuffer *CurMB = SrcMgr.getBufferInfo(BufferID).Buffer; + const char *BufferName = CurMB->getBufferIdentifier(); + std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); + OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; + } +}; + +class CTagsEmitter { +private: + RecordKeeper &Records; +public: + CTagsEmitter(RecordKeeper &R) : Records(R) {} + + void run(raw_ostream &OS); + +private: + static SMLoc locate(const Record *R); +}; + +} // End anonymous namespace. + +SMLoc CTagsEmitter::locate(const Record *R) { + ArrayRef<SMLoc> Locs = R->getLoc(); + if (Locs.empty()) { + SMLoc NullLoc; + return NullLoc; + } + return Locs.front(); +} + +void CTagsEmitter::run(raw_ostream &OS) { + const std::map<std::string, Record *> &Classes = Records.getClasses(); + const std::map<std::string, Record *> &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))); + // Emit tags. + std::sort(Tags.begin(), Tags.end()); + OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; + OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n"; + for (std::vector<Tag>::const_iterator I = Tags.begin(), E = Tags.end(); + I != E; ++I) + I->emit(OS); +} + +namespace llvm { + +void EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); } + +} // End llvm namespace. diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 3e4f626..c94d384 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -14,10 +14,10 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" -#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <map> #include <string> diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index d5b581b..8e5bb77 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -13,13 +13,13 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include <algorithm> #include <cstdio> #include <set> @@ -57,7 +57,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { } -EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) { +EEVT::TypeSet::TypeSet(ArrayRef<MVT::SimpleValueType> VTList) { assert(!VTList.empty() && "empty list?"); TypeVec.append(VTList.begin(), VTList.end()); @@ -76,7 +76,7 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, bool (*Pred)(MVT::SimpleValueType), const char *PredicateName) { assert(isCompletelyUnknown()); - const std::vector<MVT::SimpleValueType> &LegalTypes = + ArrayRef<MVT::SimpleValueType> LegalTypes = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); if (TP.hasError()) @@ -956,6 +956,40 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, llvm_unreachable("Invalid ConstraintType!"); } +// Update the node type to match an instruction operand or result as specified +// in the ins or outs lists on the instruction definition. Return true if the +// type was actually changed. +bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, + Record *Operand, + TreePattern &TP) { + // The 'unknown' operand indicates that types should be inferred from the + // context. + if (Operand->isSubClassOf("unknown_class")) + return false; + + // The Operand class specifies a type directly. + if (Operand->isSubClassOf("Operand")) + return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")), + TP); + + // PointerLikeRegClass has a type that is determined at runtime. + if (Operand->isSubClassOf("PointerLikeRegClass")) + return UpdateNodeType(ResNo, MVT::iPTR, TP); + + // Both RegisterClass and RegisterOperand operands derive their types from a + // register class def. + Record *RC = 0; + if (Operand->isSubClassOf("RegisterClass")) + RC = Operand; + else if (Operand->isSubClassOf("RegisterOperand")) + RC = Operand->getValueAsDef("RegClass"); + + assert(RC && "Unknown operand type"); + CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo(); + return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP); +} + + //===----------------------------------------------------------------------===// // SDNodeInfo implementation // @@ -1287,8 +1321,18 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// type which should be applied to it. This will infer the type of register /// references from the register file information, for example. /// +/// When Unnamed is set, return the type of a DAG operand with no name, such as +/// the F8RC register class argument in: +/// +/// (COPY_TO_REGCLASS GPR:$src, F8RC) +/// +/// When Unnamed is false, return the type of a named DAG operand such as the +/// GPR:$src operand above. +/// static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, - bool NotRegisters, TreePattern &TP) { + bool NotRegisters, + bool Unnamed, + TreePattern &TP) { // Check to see if this is a register operand. if (R->isSubClassOf("RegisterOperand")) { assert(ResNo == 0 && "Regoperand ref only has one result!"); @@ -1302,6 +1346,13 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { assert(ResNo == 0 && "Regclass ref only has one result!"); + // An unnamed register class represents itself as an i32 immediate, for + // example on a COPY_TO_REGCLASS instruction. + if (Unnamed) + return EEVT::TypeSet(MVT::i32, TP); + + // In a named operand, the register class provides the possible set of + // types. if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); @@ -1327,9 +1378,27 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, return EEVT::TypeSet(); } - if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + if (R->isSubClassOf("ValueType")) { assert(ResNo == 0 && "This node only has one result!"); - // Using a VTSDNode or CondCodeSDNode. + // An unnamed VTSDNode represents itself as an MVT::Other immediate. + // + // (sext_inreg GPR:$src, i16) + // ~~~ + if (Unnamed) + return EEVT::TypeSet(MVT::Other, TP); + // With a name, the ValueType simply provides the type of the named + // variable. + // + // (sext_inreg i32:$src, i16) + // ~~~~~~~~ + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + return EEVT::TypeSet(getValueType(R), TP); + } + + if (R->isSubClassOf("CondCode")) { + assert(ResNo == 0 && "This node only has one result!"); + // Using a CondCodeSDNode. return EEVT::TypeSet(MVT::Other, TP); } @@ -1435,7 +1504,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = false; for (unsigned i = 0, e = Types.size(); i != e; ++i) MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, - NotRegisters, TP), TP); + NotRegisters, + !hasName(), TP), TP); return MadeChange; } @@ -1498,25 +1568,6 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; } - if (getOperator()->getName() == "COPY_TO_REGCLASS") { - bool MadeChange = false; - MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); - - assert(getChild(0)->getNumTypes() == 1 && - getChild(1)->getNumTypes() == 1 && "Unhandled case"); - - // child #1 of COPY_TO_REGCLASS should be a register class. We don't care - // what type it gets, so if it didn't get a concrete type just give it the - // first viable type from the reg class. - if (!getChild(1)->hasTypeSet(0) && - !getChild(1)->getExtType(0).isCompletelyUnknown()) { - MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0]; - MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP); - } - return MadeChange; - } - if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { bool MadeChange = false; @@ -1575,26 +1626,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // (outs) list of the instruction. // FIXME: Cap at one result so far. unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; - for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { - Record *ResultNode = Inst.getResult(ResNo); - - if (ResultNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); - } else if (ResultNode->isSubClassOf("RegisterOperand")) { - Record *RegClass = ResultNode->getValueAsDef("RegClass"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(RegClass); - MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); - } else if (ResultNode->isSubClassOf("unknown_class")) { - // Nothing to do. - } else { - assert(ResultNode->isSubClassOf("RegisterClass") && - "Operands should be register classes!"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(ResultNode); - MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); - } - } + for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) + MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); // If the instruction has implicit defs, we apply the first one as a result. // FIXME: This sucks, it should apply all implicit defs. @@ -1636,30 +1669,44 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return false; } - MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); unsigned ChildResNo = 0; // Instructions always use res #0 of their op. - if (OperandNode->isSubClassOf("RegisterClass")) { - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(OperandNode); - MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); - } else if (OperandNode->isSubClassOf("RegisterOperand")) { - Record *RegClass = OperandNode->getValueAsDef("RegClass"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(RegClass); - MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); - } else if (OperandNode->isSubClassOf("Operand")) { - VT = getValueType(OperandNode->getValueAsDef("Type")); - MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP); - } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP); - } else if (OperandNode->isSubClassOf("unknown_class")) { - // Nothing to do. - } else - llvm_unreachable("Unknown operand type!"); + // If the operand has sub-operands, they may be provided by distinct + // child patterns, so attempt to match each sub-operand separately. + if (OperandNode->isSubClassOf("Operand")) { + DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); + if (unsigned NumArgs = MIOpInfo->getNumArgs()) { + // But don't do that if the whole operand is being provided by + // a single ComplexPattern. + const ComplexPattern *AM = Child->getComplexPatternInfo(CDP); + if (!AM || AM->getNumOperands() < NumArgs) { + // Match first sub-operand against the child we already have. + Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); + MadeChange |= + Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); + + // And the remaining sub-operands against subsequent children. + for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { + if (ChildNo >= getNumChildren()) { + TP.error("Instruction '" + getOperator()->getName() + + "' expects more operands than were provided."); + return false; + } + Child = getChild(ChildNo++); + + SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef(); + MadeChange |= + Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); + } + continue; + } + } + } - MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); + // If we didn't match by pieces above, attempt to match the whole + // operand now. + MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } if (ChildNo != getNumChildren()) { @@ -1668,6 +1715,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return false; } + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); return MadeChange; } @@ -1817,6 +1866,16 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ return Res; } + // ?:$name or just $name. + if (TheInit == UnsetInit::get()) { + if (OpName.empty()) + error("'?' argument requires a name to match with operand list"); + TreePatternNode *Res = new TreePatternNode(TheInit, 1); + Args.push_back(OpName); + Res->setName(OpName); + return Res; + } + if (IntInit *II = dyn_cast<IntInit>(TheInit)) { if (!OpName.empty()) error("Constant int argument should not have a name!"); @@ -2383,6 +2442,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); if (Val->getDef()->isSubClassOf("RegisterClass") || + Val->getDef()->isSubClassOf("ValueType") || Val->getDef()->isSubClassOf("RegisterOperand") || Val->getDef()->isSubClassOf("PointerLikeRegClass")) { if (Dest->getName().empty()) @@ -2599,6 +2659,25 @@ getInstructionsInTree(TreePatternNode *Tree, SmallVectorImpl<Record*> &Instrs) { getInstructionsInTree(Tree->getChild(i), Instrs); } +/// Check the class of a pattern leaf node against the instruction operand it +/// represents. +static bool checkOperandClass(CGIOperandList::OperandInfo &OI, + Record *Leaf) { + if (OI.Rec == Leaf) + return true; + + // Allow direct value types to be used in instruction set patterns. + // The type will be checked later. + if (Leaf->isSubClassOf("ValueType")) + return true; + + // Patterns can also be ComplexPattern instances. + if (Leaf->isSubClassOf("ComplexPattern")) + return true; + + return false; +} + /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully /// resolved instructions. @@ -2708,7 +2787,7 @@ void CodeGenDAGPatterns::ParseInstructions() { I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); - if (CGI.Operands[i].Rec != R) + if (!checkOperandClass(CGI.Operands[i], R)) I->error("Operand $" + OpName + " class mismatch!"); // Remember the return type. @@ -2747,7 +2826,7 @@ void CodeGenDAGPatterns::ParseInstructions() { if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); - if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern")) + if (!checkOperandClass(Op, InRec)) I->error("Operand $" + OpName + "'s register class disagrees" " between the operand and pattern"); } diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index 9be763f..7c2fa36 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -15,15 +15,15 @@ #ifndef CODEGEN_DAGPATTERNS_H #define CODEGEN_DAGPATTERNS_H -#include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" +#include "CodeGenTarget.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" -#include <set> #include <algorithm> -#include <vector> #include <map> +#include <set> +#include <vector> namespace llvm { class Record; @@ -59,7 +59,7 @@ namespace EEVT { public: TypeSet() {} TypeSet(MVT::SimpleValueType VT, TreePattern &TP); - TypeSet(const std::vector<MVT::SimpleValueType> &VTList); + TypeSet(ArrayRef<MVT::SimpleValueType> VTList); bool isCompletelyUnknown() const { return TypeVec.empty(); } @@ -334,6 +334,7 @@ public: } ~TreePatternNode(); + bool hasName() const { return !Name.empty(); } const std::string &getName() const { return Name; } void setName(StringRef N) { Name.assign(N.begin(), N.end()); } @@ -463,6 +464,11 @@ public: // Higher level manipulation routines. return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); } + // Update node type with types inferred from an instruction operand or result + // def from the ins/outs lists. + // Return true if the type changed. + bool UpdateNodeTypeFromInst(unsigned ResNo, Record *Operand, TreePattern &TP); + /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index 0a8684d..3673204 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -13,11 +13,11 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include <set> using namespace llvm; diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h index 55d4439..d1e1153 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h @@ -14,12 +14,12 @@ #ifndef CODEGEN_INSTRUCTION_H #define CODEGEN_INSTRUCTION_H -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/SourceMgr.h" #include <string> -#include <vector> #include <utility> +#include <vector> namespace llvm { class Record; diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h index 6efe952..f0570f9 100644 --- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -14,9 +14,9 @@ #ifndef CODEGEN_INTRINSIC_H #define CODEGEN_INTRINSIC_H +#include "llvm/CodeGen/ValueTypes.h" #include <string> #include <vector> -#include "llvm/CodeGen/ValueTypes.h" namespace llvm { class Record; diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp index 1653d67..ee32aa1 100644 --- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp @@ -533,12 +533,11 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end(); II != IE; II++) { std::vector<Init*> FieldValues = (*II).second; - unsigned FieldSize = FieldValues.size(); // Delete duplicate entries from ColFieldValueMap - for (unsigned i = 0; i < FieldSize - 1; i++) { + for (unsigned i = 0; i < FieldValues.size() - 1; i++) { Init *CurVal = FieldValues[i]; - for (unsigned j = i+1; j < FieldSize; j++) { + for (unsigned j = i+1; j < FieldValues.size(); j++) { if (CurVal == FieldValues[j]) { FieldValues.erase(FieldValues.begin()+j); } @@ -547,9 +546,9 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { // Emit enumerated values for the column fields. OS << "enum " << (*II).first << " {\n"; - for (unsigned i = 0; i < FieldSize; i++) { + for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString(); - if (i != FieldValues.size() - 1) + if (i != endFV - 1) OS << ",\n"; else OS << "\n};\n\n"; diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index 580e319..993b8db 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -14,12 +14,12 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" -#include "llvm/TableGen/Error.h" #include "llvm/ADT/IntEqClasses.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/TableGen/Error.h" using namespace llvm; @@ -636,8 +636,10 @@ struct TupleExpander : SetTheory::Expander { Elts.insert(NewReg); // Copy Proto super-classes. - for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i) - NewReg->addSuperClass(Proto->getSuperClasses()[i]); + ArrayRef<Record *> Supers = Proto->getSuperClasses(); + ArrayRef<SMRange> Ranges = Proto->getSuperClassRanges(); + for (unsigned i = 0, e = Supers.size(); i != e; ++i) + NewReg->addSuperClass(Supers[i], Ranges[i]); // Copy Proto fields. for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { @@ -701,7 +703,9 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; - R->setName("AnonRegClass_"+utostr(AnonCounter++)); + R->setName("AnonRegClass_" + utostr(AnonCounter)); + // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr. + ++AnonCounter; } std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); @@ -1196,6 +1200,12 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { if (Idx->getComposites().empty()) { Idx->LaneMask = 1u << Bit; // Share bit 31 in the unlikely case there are more than 32 leafs. + // + // Sharing bits is harmless; it allows graceful degradation in targets + // with more than 32 vector lanes. They simply get a limited resolution + // view of lanes beyond the 32nd. + // + // See also the comment for getSubRegIndexLaneMask(). if (Bit < 31) ++Bit; } else { Idx->LaneMask = 0; @@ -1589,6 +1599,35 @@ void CodeGenRegBank::computeRegUnitSets() { } assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass"); } + + // For each register unit, ensure that we have the list of UnitSets that + // contain the unit. Normally, this matches an existing list of UnitSets for a + // register class. If not, we create a new entry in RegClassUnitSets as a + // "fake" register class. + for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits; + UnitIdx < UnitEnd; ++UnitIdx) { + std::vector<unsigned> RUSets; + for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) { + RegUnitSet &RUSet = RegUnitSets[i]; + if (std::find(RUSet.Units.begin(), RUSet.Units.end(), UnitIdx) + == RUSet.Units.end()) + continue; + RUSets.push_back(i); + } + unsigned RCUnitSetsIdx = 0; + for (unsigned e = RegClassUnitSets.size(); + RCUnitSetsIdx != e; ++RCUnitSetsIdx) { + if (RegClassUnitSets[RCUnitSetsIdx] == RUSets) { + break; + } + } + RegUnits[UnitIdx].RegClassUnitSetsIdx = RCUnitSetsIdx; + if (RCUnitSetsIdx == RegClassUnitSets.size()) { + // Create a new list of UnitSets as a "fake" register class. + RegClassUnitSets.resize(RCUnitSetsIdx + 1); + RegClassUnitSets[RCUnitSetsIdx].swap(RUSets); + } + } } void CodeGenRegBank::computeDerivedInfo() { diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index e411074..4f2cc28 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -16,17 +16,17 @@ #define CODEGEN_REGISTERS_H #include "SetTheory.h" -#include "llvm/TableGen/Record.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Record.h" #include <cstdlib> #include <map> -#include <string> #include <set> +#include <string> #include <vector> namespace llvm { @@ -261,7 +261,7 @@ namespace llvm { public: unsigned EnumValue; std::string Namespace; - std::vector<MVT::SimpleValueType> VTs; + SmallVector<MVT::SimpleValueType, 4> VTs; unsigned SpillSize; unsigned SpillAlignment; int CopyCost; @@ -274,7 +274,7 @@ namespace llvm { const std::string &getName() const { return Name; } std::string getQualifiedName() const; - const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;} + ArrayRef<MVT::SimpleValueType> getValueTypes() const {return VTs;} unsigned getNumValueTypes() const { return VTs.size(); } MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const { @@ -403,7 +403,11 @@ namespace llvm { // these two registers and their super-registers. const CodeGenRegister *Roots[2]; - RegUnit() : Weight(0) { Roots[0] = Roots[1] = 0; } + // Index into RegClassUnitSets where we can find the list of UnitSets that + // contain this unit. + unsigned RegClassUnitSetsIdx; + + RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { Roots[0] = Roots[1] = 0; } ArrayRef<const CodeGenRegister*> getRoots() const { assert(!(Roots[1] && !Roots[0]) && "Invalid roots array"); @@ -462,6 +466,10 @@ namespace llvm { // Map RegisterClass index to the index of the RegUnitSet that contains the // class's units and any inferred RegUnit supersets. + // + // NOTE: This could grow beyond the number of register classes when we map + // register units to lists of unit sets. If the list of unit sets does not + // already exist for a register class, we create a new entry in this vector. std::vector<std::vector<unsigned> > RegClassUnitSets; // Add RC to *2RC maps. @@ -615,6 +623,13 @@ namespace llvm { return RegUnitSets[Idx]; } + // The number of pressure set lists may be larget than the number of + // register classes if some register units appeared in a list of sets that + // did not correspond to an existing register class. + unsigned getNumRegClassPressureSetLists() const { + return RegClassUnitSets.size(); + } + // Get a list of pressure set IDs for a register class. Liveness of a // register in this class impacts each pressure set in this list by the // weight of the register. An exact solution requires all registers in a diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp index 63cc97a..c02f084 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -16,10 +16,10 @@ #include "CodeGenSchedule.h" #include "CodeGenTarget.h" -#include "llvm/TableGen/Error.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Regex.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/TableGen/Error.h" using namespace llvm; @@ -88,7 +88,7 @@ struct InstRegexOp : public SetTheory::Operator { /// CodeGenModels ctor interprets machine model records and populates maps. CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK, const CodeGenTarget &TGT): - Records(RK), Target(TGT), NumItineraryClasses(0) { + Records(RK), Target(TGT) { Sets.addFieldExpander("InstRW", "Instrs"); @@ -217,7 +217,7 @@ void CodeGenSchedModels::collectSchedRW() { for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { Record *SchedDef = (*I)->TheDef; - if (!SchedDef->isSubClassOf("Sched")) + if (SchedDef->isValueUnset("SchedRW")) continue; RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW"); for (RecIter RWI = RWs.begin(), RWE = RWs.end(); RWI != RWE; ++RWI) { @@ -502,40 +502,25 @@ void CodeGenSchedModels::collectSchedClasses() { // NoItinerary is always the first class at Idx=0 SchedClasses.resize(1); - SchedClasses.back().Name = "NoItinerary"; + SchedClasses.back().Index = 0; + SchedClasses.back().Name = "NoInstrModel"; + SchedClasses.back().ItinClassDef = Records.getDef("NoItinerary"); SchedClasses.back().ProcIndices.push_back(0); - SchedClassIdxMap[SchedClasses.back().Name] = 0; - // Gather and sort all itinerary classes used by instruction descriptions. - RecVec ItinClassList; + // Create a SchedClass for each unique combination of itinerary class and + // SchedRW list. for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary"); - // Map a new SchedClass with no index. - if (!SchedClassIdxMap.count(ItinDef->getName())) { - SchedClassIdxMap[ItinDef->getName()] = 0; - ItinClassList.push_back(ItinDef); - } - } - // Assign each itinerary class unique number, skipping NoItinerary==0 - NumItineraryClasses = ItinClassList.size(); - std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); - for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) { - Record *ItinDef = ItinClassList[i]; - SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size(); - SchedClasses.push_back(CodeGenSchedClass(ItinDef)); - } - // Infer classes from SchedReadWrite resources listed for each - // instruction definition that inherits from class Sched. - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - if (!(*I)->TheDef->isSubClassOf("Sched")) - continue; IdxVec Writes, Reads; - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + if (!(*I)->TheDef->isValueUnset("SchedRW")) + findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + // ProcIdx == 0 indicates the class applies to all processors. IdxVec ProcIndices(1, 0); - addSchedClass(Writes, Reads, ProcIndices); + + unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices); + InstrClassMap[(*I)->TheDef] = SCIdx; } // Create classes for InstRW defs. RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW"); @@ -549,68 +534,70 @@ void CodeGenSchedModels::collectSchedClasses() { DEBUG(EnableDump = true); if (!EnableDump) return; + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { - Record *SchedDef = (*I)->TheDef; + std::string InstName = (*I)->TheDef->getName(); - if (SchedDef->isSubClassOf("Sched")) { + unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); + if (!SCIdx) { + dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + continue; + } + CodeGenSchedClass &SC = getSchedClass(SCIdx); + if (SC.ProcIndices[0] != 0) + PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class " + "must not be subtarget specific."); + + IdxVec ProcIndices; + if (SC.ItinClassDef->getName() != "NoItinerary") { + ProcIndices.push_back(0); + dbgs() << "Itinerary for " << InstName << ": " + << SC.ItinClassDef->getName() << '\n'; + } + if (!SC.Writes.empty()) { + ProcIndices.push_back(0); + dbgs() << "SchedRW machine model for " << InstName; + for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; ++WI) + dbgs() << " " << SchedWrites[*WI].Name; + for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI) + dbgs() << " " << SchedReads[*RI].Name; + dbgs() << '\n'; + } + const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs; + for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); + RWI != RWE; ++RWI) { + const CodeGenProcModel &ProcModel = + getProcModel((*RWI)->getValueAsDef("SchedModel")); + ProcIndices.push_back(ProcModel.Index); + dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName; IdxVec Writes; IdxVec Reads; - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); - dbgs() << "SchedRW machine model for " << InstName; + findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) dbgs() << " " << SchedWrites[*WI].Name; for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) dbgs() << " " << SchedReads[*RI].Name; dbgs() << '\n'; } - unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); - if (SCIdx) { - const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs; - for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); - RWI != RWE; ++RWI) { - const CodeGenProcModel &ProcModel = - getProcModel((*RWI)->getValueAsDef("SchedModel")); - dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName; - IdxVec Writes; - IdxVec Reads; - findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), - Writes, Reads); - for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) - dbgs() << " " << SchedWrites[*WI].Name; - for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) - dbgs() << " " << SchedReads[*RI].Name; - dbgs() << '\n'; - } - continue; - } - if (!SchedDef->isSubClassOf("Sched") - && (SchedDef->getValueAsDef("Itinerary")->getName() == "NoItinerary")) { - dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), + PE = ProcModels.end(); PI != PE; ++PI) { + if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) + dbgs() << "No machine model for " << (*I)->TheDef->getName() + << " on processor " << PI->ModelName << '\n'; } } } -unsigned CodeGenSchedModels::getSchedClassIdx( - const RecVec &RWDefs) const { - - IdxVec Writes, Reads; - findRWs(RWDefs, Writes, Reads); - return findSchedClassIdx(Writes, Reads); -} - /// Find an SchedClass that has been inferred from a per-operand list of /// SchedWrites and SchedReads. -unsigned CodeGenSchedModels::findSchedClassIdx(const IdxVec &Writes, +unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef, + const IdxVec &Writes, const IdxVec &Reads) const { for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) { - // Classes with InstRWs may have the same Writes/Reads as a class originally - // produced by a SchedRW definition. We need to be able to recover the - // original class index for processors that don't match any InstRWs. - if (I->ItinClassDef || !I->InstRWs.empty()) - continue; - - if (I->Writes == Writes && I->Reads == Reads) { + if (I->ItinClassDef == ItinClassDef + && I->Writes == Writes && I->Reads == Reads) { return I - schedClassBegin(); } } @@ -621,29 +608,17 @@ unsigned CodeGenSchedModels::findSchedClassIdx(const IdxVec &Writes, unsigned CodeGenSchedModels::getSchedClassIdx( const CodeGenInstruction &Inst) const { - unsigned SCIdx = InstrClassMap.lookup(Inst.TheDef); - if (SCIdx) - return SCIdx; - - // If this opcode isn't mapped by the subtarget fallback to the instruction - // definition's SchedRW or ItinDef values. - if (Inst.TheDef->isSubClassOf("Sched")) { - RecVec RWs = Inst.TheDef->getValueAsListOfDefs("SchedRW"); - return getSchedClassIdx(RWs); - } - Record *ItinDef = Inst.TheDef->getValueAsDef("Itinerary"); - assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass"); - unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName()); - assert(Idx <= NumItineraryClasses && "bad ItinClass index"); - return Idx; + return InstrClassMap.lookup(Inst.TheDef); } std::string CodeGenSchedModels::createSchedClassName( - const IdxVec &OperWrites, const IdxVec &OperReads) { + Record *ItinClassDef, const IdxVec &OperWrites, const IdxVec &OperReads) { std::string Name; + if (ItinClassDef && ItinClassDef->getName() != "NoItinerary") + Name = ItinClassDef->getName(); for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) { - if (WI != OperWrites.begin()) + if (!Name.empty()) Name += '_'; Name += SchedWrites[*WI].Name; } @@ -665,17 +640,18 @@ std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) { return Name; } -/// Add an inferred sched class from a per-operand list of SchedWrites and -/// SchedReads. ProcIndices contains the set of IDs of processors that may -/// utilize this class. -unsigned CodeGenSchedModels::addSchedClass(const IdxVec &OperWrites, +/// Add an inferred sched class from an itinerary class and per-operand list of +/// SchedWrites and SchedReads. ProcIndices contains the set of IDs of +/// processors that may utilize this class. +unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef, + const IdxVec &OperWrites, const IdxVec &OperReads, const IdxVec &ProcIndices) { assert(!ProcIndices.empty() && "expect at least one ProcIdx"); - unsigned Idx = findSchedClassIdx(OperWrites, OperReads); - if (Idx) { + unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads); + if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) { IdxVec PI; std::set_union(SchedClasses[Idx].ProcIndices.begin(), SchedClasses[Idx].ProcIndices.end(), @@ -687,7 +663,9 @@ unsigned CodeGenSchedModels::addSchedClass(const IdxVec &OperWrites, Idx = SchedClasses.size(); SchedClasses.resize(Idx+1); CodeGenSchedClass &SC = SchedClasses.back(); - SC.Name = createSchedClassName(OperWrites, OperReads); + SC.Index = Idx; + SC.Name = createSchedClassName(ItinClassDef, OperWrites, OperReads); + SC.ItinClassDef = ItinClassDef; SC.Writes = OperWrites; SC.Reads = OperReads; SC.ProcIndices = ProcIndices; @@ -709,19 +687,10 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes"); for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) { - unsigned SCIdx = 0; InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I); - if (Pos != InstrClassMap.end()) - SCIdx = Pos->second; - else { - // This instruction has not been mapped yet. Get the original class. All - // instructions in the same InstrRW class must be from the same original - // class because that is the fall-back class for other processors. - Record *ItinDef = (*I)->getValueAsDef("Itinerary"); - SCIdx = SchedClassIdxMap.lookup(ItinDef->getName()); - if (!SCIdx && (*I)->isSubClassOf("Sched")) - SCIdx = getSchedClassIdx((*I)->getValueAsListOfDefs("SchedRW")); - } + if (Pos == InstrClassMap.end()) + PrintFatalError((*I)->getLoc(), "No sched class for instruction."); + unsigned SCIdx = Pos->second; unsigned CIdx = 0, CEnd = ClassInstrs.size(); for (; CIdx != CEnd; ++CIdx) { if (ClassInstrs[CIdx].first == SCIdx) @@ -741,7 +710,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second; // If the all instrs in the current class are accounted for, then leave // them mapped to their old class. - if (SchedClasses[OldSCIdx].InstRWs.size() == InstDefs.size()) { + if (OldSCIdx && SchedClasses[OldSCIdx].InstRWs.size() == InstDefs.size()) { assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 && "expected a generic SchedClass"); continue; @@ -749,6 +718,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { unsigned SCIdx = SchedClasses.size(); SchedClasses.resize(SCIdx+1); CodeGenSchedClass &SC = SchedClasses.back(); + SC.Index = SCIdx; SC.Name = createSchedClassName(InstDefs); // Preserve ItinDef and Writes/Reads for processors without an InstRW entry. SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef; @@ -780,32 +750,48 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { } } +// True if collectProcItins found anything. +bool CodeGenSchedModels::hasItineraries() const { + for (CodeGenSchedModels::ProcIter PI = procModelBegin(), PE = procModelEnd(); + PI != PE; ++PI) { + if (PI->hasItineraries()) + return true; + } + return false; +} + // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), PE = ProcModels.end(); PI != PE; ++PI) { CodeGenProcModel &ProcModel = *PI; - RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID"); - // Skip empty itinerary. - if (ItinRecords.empty()) + if (!ProcModel.hasItineraries()) continue; - ProcModel.ItinDefList.resize(NumItineraryClasses+1); + RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID"); + assert(!ItinRecords.empty() && "ProcModel.hasItineraries is incorrect"); + + // Populate ItinDefList with Itinerary records. + ProcModel.ItinDefList.resize(NumInstrSchedClasses); // Insert each itinerary data record in the correct position within // the processor model's ItinDefList. for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) { Record *ItinData = ItinRecords[i]; Record *ItinDef = ItinData->getValueAsDef("TheClass"); - if (!SchedClassIdxMap.count(ItinDef->getName())) { + bool FoundClass = false; + for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd(); + SCI != SCE; ++SCI) { + // Multiple SchedClasses may share an itinerary. Update all of them. + if (SCI->ItinClassDef == ItinDef) { + ProcModel.ItinDefList[SCI->Index] = ItinData; + FoundClass = true; + } + } + if (!FoundClass) { DEBUG(dbgs() << ProcModel.ItinsDef->getName() - << " has unused itinerary class " << ItinDef->getName() << '\n'); - continue; + << " missing class for itinerary " << ItinDef->getName() << '\n'); } - assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass"); - unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName()); - assert(Idx <= NumItineraryClasses && "bad ItinClass index"); - ProcModel.ItinDefList[Idx] = ItinData; } // Check for missing itinerary entries. assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec"); @@ -839,13 +825,17 @@ void CodeGenSchedModels::collectProcItinRW() { /// Infer new classes from existing classes. In the process, this may create new /// SchedWrites from sequences of existing SchedWrites. void CodeGenSchedModels::inferSchedClasses() { + DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n"); + // Visit all existing classes and newly created classes. for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) { + assert(SchedClasses[Idx].Index == Idx && "bad SCIdx"); + if (SchedClasses[Idx].ItinClassDef) inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx); - else if (!SchedClasses[Idx].InstRWs.empty()) + if (!SchedClasses[Idx].InstRWs.empty()) inferFromInstRWs(Idx); - else { + if (!SchedClasses[Idx].Writes.empty()) { inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads, Idx, SchedClasses[Idx].ProcIndices); } @@ -1042,11 +1032,13 @@ static bool hasVariant(ArrayRef<PredTransition> Transitions, // Populate IntersectingVariants with any variants or aliased sequences of the // given SchedRW whose processor indices and predicates are not mutually -// exclusive with the given transition, +// exclusive with the given transition. void PredTransitions::getIntersectingVariants( const CodeGenSchedRW &SchedRW, unsigned TransIdx, std::vector<TransVariant> &IntersectingVariants) { + bool GenericRW = false; + std::vector<TransVariant> Variants; if (SchedRW.HasVariants) { unsigned VarProcIdx = 0; @@ -1058,6 +1050,8 @@ void PredTransitions::getIntersectingVariants( const RecVec VarDefs = SchedRW.TheDef->getValueAsListOfDefs("Variants"); for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI) Variants.push_back(TransVariant(*RI, SchedRW.Index, VarProcIdx, 0)); + if (VarProcIdx == 0) + GenericRW = true; } for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end(); AI != AE; ++AI) { @@ -1081,6 +1075,8 @@ void PredTransitions::getIntersectingVariants( Variants.push_back( TransVariant(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0)); } + if (AliasProcIdx == 0) + GenericRW = true; } for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) { TransVariant &Variant = Variants[VIdx]; @@ -1118,6 +1114,10 @@ void PredTransitions::getIntersectingVariants( TransVec.push_back(TransVec[TransIdx]); } } + if (GenericRW && IntersectingVariants.empty()) { + PrintFatalError(SchedRW.TheDef->getLoc(), "No variant of this type has " + "a matching predicate on any processor"); + } } // Push the Reads/Writes selected by this variant onto the PredTransition @@ -1215,10 +1215,6 @@ void PredTransitions::substituteVariantOperand( // This will push a copies of TransVec[TransIdx] on the back of TransVec. std::vector<TransVariant> IntersectingVariants; getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants); - if (IntersectingVariants.empty()) - PrintFatalError(SchedRW.TheDef->getLoc(), - "No variant of this type has " - "a matching predicate on any processor"); // Now expand each variant on top of its copy of the transition. for (std::vector<TransVariant>::const_iterator IVI = IntersectingVariants.begin(), @@ -1295,8 +1291,8 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end()); CodeGenSchedTransition SCTrans; SCTrans.ToClassIdx = - SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant, - ProcIndices); + SchedModels.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant, + OperReadsVariant, ProcIndices); SCTrans.ProcIndices = ProcIndices; // The final PredTerm is unique set of predicates guarding the transition. RecVec Preds; @@ -1318,7 +1314,7 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads, unsigned FromClassIdx, const IdxVec &ProcIndices) { - DEBUG(dbgs() << "INFER RW: "); + DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") "); // Create a seed transition with an empty PredTerm and the expanded sequences // of SchedWrites for the current SchedClass. @@ -1380,8 +1376,22 @@ void CodeGenSchedModels::collectProcResources() { SCI != SCE; ++SCI) { if (SCI->ItinClassDef) collectItinProcResources(SCI->ItinClassDef); - else + else { + // This class may have a default ReadWrite list which can be overriden by + // InstRW definitions. + if (!SCI->InstRWs.empty()) { + for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); + RWI != RWE; ++RWI) { + Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); + IdxVec ProcIndices(1, getProcModel(RWModelDef).Index); + IdxVec Writes, Reads; + findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); + collectRWResources(Writes, Reads, ProcIndices); + } + } collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices); + } } // Add resources separately defined by each subtarget. RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes"); @@ -1528,6 +1538,20 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, ProcUnitDef = *RI; } } + RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup"); + for (RecIter RI = ProcResGroups.begin(), RE = ProcResGroups.end(); + RI != RE; ++RI) { + + if (*RI == ProcResKind + && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) { + if (ProcUnitDef) { + PrintFatalError((*RI)->getLoc(), + "Multiple ProcessorResourceUnits associated with " + + ProcResKind->getName()); + } + ProcUnitDef = *RI; + } + } if (!ProcUnitDef) { PrintFatalError(ProcResKind->getLoc(), "No ProcessorResources associated with " @@ -1549,6 +1573,9 @@ void CodeGenSchedModels::addProcResource(Record *ProcResKind, return; PM.ProcResourceDefs.push_back(ProcResUnits); + if (ProcResUnits->isSubClassOf("ProcResGroup")) + return; + if (!ProcResUnits->getValueInit("Super")->isComplete()) return; @@ -1611,7 +1638,7 @@ void CodeGenSchedRW::dump() const { } void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const { - dbgs() << "SCHEDCLASS " << Name << '\n' + dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n' << " Writes: "; for (unsigned i = 0, N = Writes.size(); i < N; ++i) { SchedModels->getSchedWrite(Writes[i]).dump(); @@ -1629,6 +1656,13 @@ void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const { } } dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n'; + if (!Transitions.empty()) { + dbgs() << "\n Transitions for Proc "; + for (std::vector<CodeGenSchedTransition>::const_iterator + TI = Transitions.begin(), TE = Transitions.end(); TI != TE; ++TI) { + dumpIdxVec(TI->ProcIndices); + } + } } void PredTransitions::dump() const { diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.h b/contrib/llvm/utils/TableGen/CodeGenSchedule.h index eed0589..e5b9118 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.h +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.h @@ -16,10 +16,10 @@ #define CODEGEN_SCHEDULE_H #include "SetTheory.h" -#include "llvm/TableGen/Record.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Record.h" namespace llvm { @@ -55,10 +55,11 @@ struct CodeGenSchedRW { IdxVec Sequence; RecVec Aliases; - CodeGenSchedRW(): Index(0), TheDef(0), IsAlias(false), HasVariants(false), - IsVariadic(false), IsSequence(false) {} - CodeGenSchedRW(unsigned Idx, Record *Def): Index(Idx), TheDef(Def), - IsAlias(false), IsVariadic(false) { + CodeGenSchedRW() + : Index(0), TheDef(0), IsRead(false), IsAlias(false), + HasVariants(false), IsVariadic(false), IsSequence(false) {} + CodeGenSchedRW(unsigned Idx, Record *Def) + : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) { Name = Def->getName(); IsRead = Def->isSubClassOf("SchedRead"); HasVariants = Def->isSubClassOf("SchedVariant"); @@ -72,9 +73,9 @@ struct CodeGenSchedRW { } CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq, - const std::string &Name): - Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), - HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { + const std::string &Name) + : Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), + HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); } @@ -124,6 +125,7 @@ struct CodeGenSchedTransition { /// itinerary class. Each inherits the processor index from the ItinRW record /// that mapped the itinerary class to the variant Writes or Reads. struct CodeGenSchedClass { + unsigned Index; std::string Name; Record *ItinClassDef; @@ -140,12 +142,16 @@ struct CodeGenSchedClass { // off to join another inferred class. RecVec InstRWs; - CodeGenSchedClass(): ItinClassDef(0) {} - CodeGenSchedClass(Record *rec): ItinClassDef(rec) { - Name = rec->getName(); - ProcIndices.push_back(0); + CodeGenSchedClass(): Index(0), ItinClassDef(0) {} + + bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) { + return ItinClassDef == IC && Writes == W && Reads == R; } + // Is this class generated from a variants if existing classes? Instructions + // are never mapped directly to inferred scheduling classes. + bool isInferred() const { return !ItinClassDef; } + #ifndef NDEBUG void dump(const CodeGenSchedModels *SchedModels) const; #endif @@ -188,11 +194,16 @@ struct CodeGenProcModel { // Per-operand machine model resources associated with this processor. RecVec ProcResourceDefs; + RecVec ProcResGroupDefs; CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef, Record *IDef) : Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {} + bool hasItineraries() const { + return !ItinsDef->getValueAsListOfDefs("IID").empty(); + } + bool hasInstrSchedModel() const { return !WriteResDefs.empty() || !ItinRWDefs.empty(); } @@ -226,24 +237,11 @@ class CodeGenSchedModels { // List of unique SchedClasses. std::vector<CodeGenSchedClass> SchedClasses; - // Map SchedClass name to itinerary index. - // These are either explicit itinerary classes or classes implied by - // instruction definitions with SchedReadWrite lists. - StringMap<unsigned> SchedClassIdxMap; - - // SchedClass indices 1 up to and including NumItineraryClasses identify - // itinerary classes that are explicitly used for this target's instruction - // definitions. NoItinerary always has index 0 regardless of whether it is - // explicitly referenced. - // - // Any implied SchedClass has an index greater than NumItineraryClasses. - unsigned NumItineraryClasses; - // Any inferred SchedClass has an index greater than NumInstrSchedClassses. unsigned NumInstrSchedClasses; - // Map Instruction to SchedClass index. Only for Instructions mentioned in - // InstRW records. + // Map each instruction to its unique SchedClass index considering the + // combination of it's itinerary class, SchedRW list, and InstRW records. typedef DenseMap<Record*, unsigned> InstClassMapTy; InstClassMapTy InstrClassMap; @@ -279,6 +277,9 @@ public: ProcIter procModelBegin() const { return ProcModels.begin(); } ProcIter procModelEnd() const { return ProcModels.end(); } + // Return true if any processors have itineraries. + bool hasItineraries() const; + // Get a SchedWrite from its index. const CodeGenSchedRW &getSchedWrite(unsigned Idx) const { assert(Idx < SchedWrites.size() && "bad SchedWrite index"); @@ -310,16 +311,6 @@ public: // Return true if the given write record is referenced by a ReadAdvance. bool hasReadOfWrite(Record *WriteDef) const; - // Check if any instructions are assigned to an explicit itinerary class other - // than NoItinerary. - bool hasItineraryClasses() const { return NumItineraryClasses > 0; } - - // Return the number of itinerary classes in use by this target's instruction - // descriptions, not including "NoItinerary". - unsigned numItineraryClasses() const { - return NumItineraryClasses; - } - // Get a SchedClass from its index. CodeGenSchedClass &getSchedClass(unsigned Idx) { assert(Idx < SchedClasses.size() && "bad SchedClass index"); @@ -335,28 +326,26 @@ public: // for NoItinerary. unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const; - unsigned getSchedClassIdx(const RecVec &RWDefs) const; - - unsigned getSchedClassIdxForItin(const Record *ItinDef) { - return SchedClassIdxMap[ItinDef->getName()]; - } - typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter; SchedClassIter schedClassBegin() const { return SchedClasses.begin(); } SchedClassIter schedClassEnd() const { return SchedClasses.end(); } + unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; } + void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const; void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const; void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const; void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead, const CodeGenProcModel &ProcModel) const; - unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads, - const IdxVec &ProcIndices); + unsigned addSchedClass(Record *ItinDef, const IdxVec &OperWrites, + const IdxVec &OperReads, const IdxVec &ProcIndices); unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead); - unsigned findSchedClassIdx(const IdxVec &Writes, const IdxVec &Reads) const; + unsigned findSchedClassIdx(Record *ItinClassDef, + const IdxVec &Writes, + const IdxVec &Reads) const; Record *findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM) const; @@ -374,7 +363,8 @@ private: void collectSchedClasses(); - std::string createSchedClassName(const IdxVec &OperWrites, + std::string createSchedClassName(Record *ItinClassDef, + const IdxVec &OperWrites, const IdxVec &OperReads); std::string createSchedClassName(const RecVec &InstDefs); void createInstRWClass(Record *InstRWDef); diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index c9992eb..8b292b9 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -17,11 +17,11 @@ #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" #include "CodeGenSchedule.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include <algorithm> using namespace llvm; @@ -73,16 +73,20 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v4i1: return "MVT::v4i1"; case MVT::v8i1: return "MVT::v8i1"; case MVT::v16i1: return "MVT::v16i1"; + case MVT::v32i1: return "MVT::v32i1"; + case MVT::v64i1: return "MVT::v64i1"; case MVT::v2i8: return "MVT::v2i8"; case MVT::v4i8: return "MVT::v4i8"; case MVT::v8i8: return "MVT::v8i8"; case MVT::v16i8: return "MVT::v16i8"; case MVT::v32i8: return "MVT::v32i8"; + case MVT::v64i8: return "MVT::v64i8"; case MVT::v1i16: return "MVT::v1i16"; case MVT::v2i16: return "MVT::v2i16"; case MVT::v4i16: return "MVT::v4i16"; case MVT::v8i16: return "MVT::v8i16"; case MVT::v16i16: return "MVT::v16i16"; + case MVT::v32i16: return "MVT::v32i16"; case MVT::v1i32: return "MVT::v1i32"; case MVT::v2i32: return "MVT::v2i32"; case MVT::v4i32: return "MVT::v4i32"; @@ -97,8 +101,10 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v2f32: return "MVT::v2f32"; case MVT::v4f32: return "MVT::v4f32"; case MVT::v8f32: return "MVT::v8f32"; + case MVT::v16f32: return "MVT::v16f32"; case MVT::v2f64: return "MVT::v2f64"; case MVT::v4f64: return "MVT::v4f64"; + case MVT::v8f64: return "MVT::v8f64"; case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; @@ -223,7 +229,7 @@ getRegisterVTs(Record *R) const { for (unsigned i = 0, e = RCs.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RCs[i]; if (RC.contains(Reg)) { - const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); + ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes(); Result.insert(Result.end(), InVTs.begin(), InVTs.end()); } } diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index ddeecee..6271443 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -17,10 +17,10 @@ #ifndef CODEGEN_TARGET_H #define CODEGEN_TARGET_H -#include "CodeGenRegisters.h" #include "CodeGenInstruction.h" -#include "llvm/TableGen/Record.h" +#include "CodeGenRegisters.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" #include <algorithm> namespace llvm { @@ -68,7 +68,7 @@ class CodeGenTarget { mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; mutable CodeGenRegBank *RegBank; mutable std::vector<Record*> RegAltNameIndices; - mutable std::vector<MVT::SimpleValueType> LegalValueTypes; + mutable SmallVector<MVT::SimpleValueType, 8> LegalValueTypes; void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; @@ -129,7 +129,7 @@ public: /// specified physical register. std::vector<MVT::SimpleValueType> getRegisterVTs(Record *R) const; - const std::vector<MVT::SimpleValueType> &getLegalValueTypes() const { + ArrayRef<MVT::SimpleValueType> getLegalValueTypes() const { if (LegalValueTypes.empty()) ReadLegalValueTypes(); return LegalValueTypes; } @@ -137,7 +137,7 @@ public: /// isLegalValueType - Return true if the specified value type is natively /// supported by the target (i.e. there are registers that directly hold it). bool isLegalValueType(MVT::SimpleValueType VT) const { - const std::vector<MVT::SimpleValueType> &LegalVTs = getLegalValueTypes(); + ArrayRef<MVT::SimpleValueType> LegalVTs = getLegalValueTypes(); for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i) if (LegalVTs[i] == VT) return true; return false; diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp index bd77907..d173cf0 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -10,9 +10,9 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenTarget.h" -#include "llvm/TableGen/Record.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" using namespace llvm; void Matcher::anchor() { } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h index 7c6ce3b..f978188 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.h +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h @@ -10,10 +10,10 @@ #ifndef TBLGEN_DAGISELMATCHER_H #define TBLGEN_DAGISELMATCHER_H -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/Casting.h" namespace llvm { diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 713f174..93f84ce 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -13,12 +13,12 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" -#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/TableGen/Record.h" using namespace llvm; enum { @@ -132,7 +132,7 @@ static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) { return NumBytes+1; } -/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return +/// EmitMatcher - Emit bytes for the specified matcher and return /// the number of bytes emitted. unsigned MatcherTableEmitter:: EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 573f558..ed41631 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -10,11 +10,11 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenRegisters.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include <utility> using namespace llvm; @@ -211,6 +211,12 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { return AddMatcher(new CheckIntegerMatcher(II->getValue())); } + // An UnsetInit represents a named node without any constraints. + if (N->getLeafValue() == UnsetInit::get()) { + assert(N->hasName() && "Unnamed ? leaf"); + return; + } + DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); if (DI == 0) { errs() << "Unknown leaf kind: " << *N << "\n"; @@ -218,6 +224,17 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { } Record *LeafRec = DI->getDef(); + + // A ValueType leaf node can represent a register when named, or itself when + // unnamed. + if (LeafRec->isSubClassOf("ValueType")) { + // A named ValueType leaf always matches: (add i32:$a, i32:$b). + if (N->hasName()) + return; + // An unnamed ValueType as in (sext_inreg GPR:$foo, i8). + return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName())); + } + if (// Handle register references. Nothing to do here, they always match. LeafRec->isSubClassOf("RegisterClass") || LeafRec->isSubClassOf("RegisterOperand") || @@ -236,9 +253,6 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { return; } - if (LeafRec->isSubClassOf("ValueType")) - return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName())); - if (LeafRec->isSubClassOf("CondCode")) return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName())); @@ -734,20 +748,33 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, continue; } - const TreePatternNode *Child = N->getChild(ChildNo); - // Otherwise this is a normal operand or a predicate operand without // 'execute always'; emit it. - unsigned BeforeAddingNumOps = InstOps.size(); - EmitResultOperand(Child, InstOps); - assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); - // If the operand is an instruction and it produced multiple results, just - // take the first one. - if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) - InstOps.resize(BeforeAddingNumOps+1); + // For operands with multiple sub-operands we may need to emit + // multiple child patterns to cover them all. However, ComplexPattern + // children may themselves emit multiple MI operands. + unsigned NumSubOps = 1; + if (OperandNode->isSubClassOf("Operand")) { + DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); + if (unsigned NumArgs = MIOpInfo->getNumArgs()) + NumSubOps = NumArgs; + } + + unsigned FinalNumOps = InstOps.size() + NumSubOps; + while (InstOps.size() < FinalNumOps) { + const TreePatternNode *Child = N->getChild(ChildNo); + unsigned BeforeAddingNumOps = InstOps.size(); + EmitResultOperand(Child, InstOps); + assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); - ++ChildNo; + // If the operand is an instruction and it produced multiple results, just + // take the first one. + if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) + InstOps.resize(BeforeAddingNumOps+1); + + ++ChildNo; + } } // If this node has input glue or explicitly specified input physregs, we diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp index 0ad25a5..2549c47 100644 --- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -279,6 +279,7 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): // // void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { + static const std::string SentinelEntry = "{-1, -1}"; DFA::StateSet::iterator SI = states.begin(); // This table provides a map to the beginning of the transitions for State s // in DFAStateInputTable. @@ -305,12 +306,17 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // If there are no valid transitions from this stage, we need a sentinel // transition. if (ValidTransitions == StateEntry[i]) { - OS << "{-1, -1},"; + OS << SentinelEntry << ","; ++ValidTransitions; } OS << "\n"; } + + // Print out a sentinel entry at the end of the StateInputTable. This is + // needed to iterate over StateInputTable in DFAPacketizer::ReadTable() + OS << SentinelEntry << "\n"; + OS << "};\n\n"; OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n"; @@ -319,6 +325,9 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { for (unsigned i = 0; i < states.size(); ++i) OS << StateEntry[i] << ", "; + // Print out the index to the sentinel entry in StateInputTable + OS << ValidTransitions << ", "; + OS << "\n};\n"; OS << "} // namespace\n"; diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index 2d11d24..5a2a41b 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -127,8 +127,9 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses. if (Target.getName() == "ARM" || - Target.getName() == "Thumb") { - EmitFixedLenDecoder(Records, OS, "ARM", + Target.getName() == "Thumb" || + Target.getName() == "AArch64") { + EmitFixedLenDecoder(Records, OS, Target.getName() == "AArch64" ? "AArch64" : "ARM", "if (!Check(S, ", ")) return MCDisassembler::Fail;", "S", "MCDisassembler::Fail", " MCDisassembler::DecodeStatus S = " diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp deleted file mode 100644 index ea25450..0000000 --- a/contrib/llvm/utils/TableGen/EDEmitter.cpp +++ /dev/null @@ -1,1011 +0,0 @@ -//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tablegen backend is responsible for emitting a description of each -// instruction in a format that the enhanced disassembler can use to tokenize -// and parse instructions. -// -//===----------------------------------------------------------------------===// - -#include "AsmWriterInst.h" -#include "CodeGenTarget.h" -#include "llvm/MC/EDInstInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" -#include <string> -#include <vector> - -using namespace llvm; - -// TODO: There's a suspiciously large amount of "table" data in this -// backend which should probably be in the TableGen file itself. - -/////////////////////////////////////////////////////////// -// Support classes for emitting nested C data structures // -/////////////////////////////////////////////////////////// - -// TODO: These classes are probably generally useful to other backends; -// add them to TableGen's "helper" API's. - -namespace { -class EnumEmitter { -private: - std::string Name; - std::vector<std::string> Entries; -public: - EnumEmitter(const char *N) : Name(N) { - } - int addEntry(const char *e) { - Entries.push_back(std::string(e)); - return Entries.size() - 1; - } - void emit(raw_ostream &o, unsigned int &i) { - o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; - i += 2; - - unsigned int index = 0; - unsigned int numEntries = Entries.size(); - for (index = 0; index < numEntries; ++index) { - o.indent(i) << Entries[index]; - if (index < (numEntries - 1)) - o << ","; - o << "\n"; - } - - i -= 2; - o.indent(i) << "};" << "\n"; - } - - void emitAsFlags(raw_ostream &o, unsigned int &i) { - o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; - i += 2; - - unsigned int index = 0; - unsigned int numEntries = Entries.size(); - unsigned int flag = 1; - for (index = 0; index < numEntries; ++index) { - o.indent(i) << Entries[index] << " = " << format("0x%x", flag); - if (index < (numEntries - 1)) - o << ","; - o << "\n"; - flag <<= 1; - } - - i -= 2; - o.indent(i) << "};" << "\n"; - } -}; -} // End anonymous namespace - -namespace { -class ConstantEmitter { -public: - virtual ~ConstantEmitter() { } - virtual void emit(raw_ostream &o, unsigned int &i) = 0; -}; -} // End anonymous namespace - -namespace { -class LiteralConstantEmitter : public ConstantEmitter { -private: - bool IsNumber; - union { - int Number; - const char* String; - }; -public: - LiteralConstantEmitter(int number = 0) : - IsNumber(true), - Number(number) { - } - void set(const char *string) { - IsNumber = false; - Number = 0; - String = string; - } - bool is(const char *string) { - return !strcmp(String, string); - } - void emit(raw_ostream &o, unsigned int &i) { - if (IsNumber) - o << Number; - else - o << String; - } -}; -} // End anonymous namespace - -namespace { -class CompoundConstantEmitter : public ConstantEmitter { -private: - unsigned int Padding; - std::vector<ConstantEmitter *> Entries; -public: - CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) { - } - CompoundConstantEmitter &addEntry(ConstantEmitter *e) { - Entries.push_back(e); - - return *this; - } - ~CompoundConstantEmitter() { - while (Entries.size()) { - ConstantEmitter *entry = Entries.back(); - Entries.pop_back(); - delete entry; - } - } - void emit(raw_ostream &o, unsigned int &i) { - o << "{" << "\n"; - i += 2; - - unsigned int index; - unsigned int numEntries = Entries.size(); - - unsigned int numToPrint; - - if (Padding) { - if (numEntries > Padding) { - fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); - llvm_unreachable("More entries than padding"); - } - numToPrint = Padding; - } else { - numToPrint = numEntries; - } - - for (index = 0; index < numToPrint; ++index) { - o.indent(i); - if (index < numEntries) - Entries[index]->emit(o, i); - else - o << "-1"; - - if (index < (numToPrint - 1)) - o << ","; - o << "\n"; - } - - i -= 2; - o.indent(i) << "}"; - } -}; -} // End anonymous namespace - -namespace { -class FlagsConstantEmitter : public ConstantEmitter { -private: - std::vector<std::string> Flags; -public: - FlagsConstantEmitter() { - } - FlagsConstantEmitter &addEntry(const char *f) { - Flags.push_back(std::string(f)); - return *this; - } - void emit(raw_ostream &o, unsigned int &i) { - unsigned int index; - unsigned int numFlags = Flags.size(); - if (numFlags == 0) - o << "0"; - - for (index = 0; index < numFlags; ++index) { - o << Flags[index].c_str(); - if (index < (numFlags - 1)) - o << " | "; - } - } -}; -} // End anonymous namespace - -/// populateOperandOrder - Accepts a CodeGenInstruction and generates its -/// AsmWriterInst for the desired assembly syntax, giving an ordered list of -/// operands in the order they appear in the printed instruction. Then, for -/// each entry in that list, determines the index of the same operand in the -/// CodeGenInstruction, and emits the resulting mapping into an array, filling -/// in unused slots with -1. -/// -/// @arg operandOrder - The array that will be populated with the operand -/// mapping. Each entry will contain -1 (invalid index -/// into the operands present in the AsmString) or a number -/// representing an index in the operand descriptor array. -/// @arg inst - The instruction to use when looking up the operands -/// @arg syntax - The syntax to use, according to LLVM's enumeration -static void populateOperandOrder(CompoundConstantEmitter *operandOrder, - const CodeGenInstruction &inst, - unsigned syntax) { - unsigned int numArgs = 0; - - AsmWriterInst awInst(inst, syntax, -1, -1); - - std::vector<AsmWriterOperand>::iterator operandIterator; - - for (operandIterator = awInst.Operands.begin(); - operandIterator != awInst.Operands.end(); - ++operandIterator) { - if (operandIterator->OperandType == - AsmWriterOperand::isMachineInstrOperand) { - operandOrder->addEntry( - new LiteralConstantEmitter(operandIterator->CGIOpNo)); - numArgs++; - } - } -} - -///////////////////////////////////////////////////// -// Support functions for handling X86 instructions // -///////////////////////////////////////////////////// - -#define SET(flag) { type->set(flag); return 0; } - -#define REG(str) if (name == str) SET("kOperandTypeRegister"); -#define MEM(str) if (name == str) SET("kOperandTypeX86Memory"); -#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress"); -#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); -#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative"); - -/// X86TypeFromOpName - Processes the name of a single X86 operand (which is -/// actually its type) and translates it into an operand type -/// -/// @arg flags - The type object to set -/// @arg name - The name of the operand -static int X86TypeFromOpName(LiteralConstantEmitter *type, - const std::string &name) { - REG("GR8"); - REG("GR8_NOREX"); - REG("GR16"); - REG("GR16_NOAX"); - REG("GR32"); - REG("GR32_NOAX"); - REG("GR32_NOREX"); - REG("GR32_TC"); - REG("FR32"); - REG("RFP32"); - REG("GR64"); - REG("GR64_NOAX"); - REG("GR64_TC"); - REG("FR64"); - REG("VR64"); - REG("RFP64"); - REG("RFP80"); - REG("VR128"); - REG("VR256"); - REG("RST"); - REG("SEGMENT_REG"); - REG("DEBUG_REG"); - REG("CONTROL_REG"); - - IMM("i8imm"); - IMM("i16imm"); - IMM("i16i8imm"); - IMM("i32imm"); - IMM("i32i8imm"); - IMM("u32u8imm"); - IMM("i64imm"); - IMM("i64i8imm"); - IMM("i64i32imm"); - IMM("SSECC"); - IMM("AVXCC"); - - // all R, I, R, I, R - MEM("i8mem"); - MEM("i8mem_NOREX"); - MEM("i16mem"); - MEM("i32mem"); - MEM("i32mem_TC"); - MEM("f32mem"); - MEM("ssmem"); - MEM("opaque32mem"); - MEM("opaque48mem"); - MEM("i64mem"); - MEM("i64mem_TC"); - MEM("f64mem"); - MEM("sdmem"); - MEM("f80mem"); - MEM("opaque80mem"); - MEM("i128mem"); - MEM("i256mem"); - MEM("f128mem"); - MEM("f256mem"); - MEM("opaque512mem"); - // Gather - MEM("vx32mem") - MEM("vy32mem") - MEM("vx64mem") - MEM("vy64mem") - - // all R, I, R, I - LEA("lea32mem"); - LEA("lea64_32mem"); - LEA("lea64mem"); - - // all I - PCR("i16imm_pcrel"); - PCR("i32imm_pcrel"); - PCR("i64i32imm_pcrel"); - PCR("brtarget8"); - PCR("offset8"); - PCR("offset16"); - PCR("offset32"); - PCR("offset64"); - PCR("brtarget"); - PCR("uncondbrtarget"); - PCR("bltarget"); - - // all I, ARM mode only, conditional/unconditional - PCR("br_target"); - PCR("bl_target"); - return 1; -} - -#undef REG -#undef MEM -#undef LEA -#undef IMM -#undef PCR - -#undef SET - -/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding -/// the appropriate flags to their descriptors -/// -/// \param operandTypes A reference the array of operand type objects -/// \param inst The instruction to use as a source of information -static void X86PopulateOperands( - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - if (!inst.TheDef->isSubClassOf("X86Inst")) - return; - - unsigned int index; - unsigned int numOperands = inst.Operands.size(); - - for (index = 0; index < numOperands; ++index) { - const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; - Record &rec = *operandInfo.Rec; - - if (X86TypeFromOpName(operandTypes[index], rec.getName()) && - !rec.isSubClassOf("PointerLikeRegClass")) { - errs() << "Operand type: " << rec.getName().c_str() << "\n"; - errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; - errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n"; - llvm_unreachable("Unhandled type"); - } - } -} - -/// decorate1 - Decorates a named operand with a new flag -/// -/// \param operandFlags The array of operand flag objects, which don't have -/// names -/// \param inst The CodeGenInstruction, which provides a way to -// translate between names and operand indices -/// \param opName The name of the operand -/// \param opFlag The name of the flag to add -static inline void decorate1( - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst, - const char *opName, - const char *opFlag) { - unsigned opIndex; - - opIndex = inst.Operands.getOperandNamed(std::string(opName)); - - operandFlags[opIndex]->addEntry(opFlag); -} - -#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) - -#define MOV(source, target) { \ - instType.set("kInstructionTypeMove"); \ - DECORATE1(source, "kOperandFlagSource"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define BRANCH(target) { \ - instType.set("kInstructionTypeBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define PUSH(source) { \ - instType.set("kInstructionTypePush"); \ - DECORATE1(source, "kOperandFlagSource"); \ -} - -#define POP(target) { \ - instType.set("kInstructionTypePop"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define CALL(target) { \ - instType.set("kInstructionTypeCall"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define RETURN() { \ - instType.set("kInstructionTypeReturn"); \ -} - -/// X86ExtractSemantics - Performs various checks on the name of an X86 -/// instruction to determine what sort of an instruction it is and then adds -/// the appropriate flags to the instruction and its operands -/// -/// \param instType A reference to the type for the instruction as a whole -/// \param operandFlags A reference to the array of operand flag object pointers -/// \param inst A reference to the original instruction -static void X86ExtractSemantics( - LiteralConstantEmitter &instType, - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - const std::string &name = inst.TheDef->getName(); - - if (name.find("MOV") != name.npos) { - if (name.find("MOV_V") != name.npos) { - // ignore (this is a pseudoinstruction) - } else if (name.find("MASK") != name.npos) { - // ignore (this is a masking move) - } else if (name.find("r0") != name.npos) { - // ignore (this is a pseudoinstruction) - } else if (name.find("PS") != name.npos || - name.find("PD") != name.npos) { - // ignore (this is a shuffling move) - } else if (name.find("MOVS") != name.npos) { - // ignore (this is a string move) - } else if (name.find("_F") != name.npos) { - // TODO handle _F moves to ST(0) - } else if (name.find("a") != name.npos) { - // TODO handle moves to/from %ax - } else if (name.find("CMOV") != name.npos) { - MOV("src2", "dst"); - } else if (name.find("PC") != name.npos) { - MOV("label", "reg") - } else { - MOV("src", "dst"); - } - } - - if (name.find("JMP") != name.npos || - name.find("J") == 0) { - if (name.find("FAR") != name.npos && name.find("i") != name.npos) { - BRANCH("off"); - } else { - BRANCH("dst"); - } - } - - if (name.find("PUSH") != name.npos) { - if (name.find("CS") != name.npos || - name.find("DS") != name.npos || - name.find("ES") != name.npos || - name.find("FS") != name.npos || - name.find("GS") != name.npos || - name.find("SS") != name.npos) { - instType.set("kInstructionTypePush"); - // TODO add support for fixed operands - } else if (name.find("F") != name.npos) { - // ignore (this pushes onto the FP stack) - } else if (name.find("A") != name.npos) { - // ignore (pushes all GP registoers onto the stack) - } else if (name[name.length() - 1] == 'm') { - PUSH("src"); - } else if (name.find("i") != name.npos) { - PUSH("imm"); - } else { - PUSH("reg"); - } - } - - if (name.find("POP") != name.npos) { - if (name.find("POPCNT") != name.npos) { - // ignore (not a real pop) - } else if (name.find("CS") != name.npos || - name.find("DS") != name.npos || - name.find("ES") != name.npos || - name.find("FS") != name.npos || - name.find("GS") != name.npos || - name.find("SS") != name.npos) { - instType.set("kInstructionTypePop"); - // TODO add support for fixed operands - } else if (name.find("F") != name.npos) { - // ignore (this pops from the FP stack) - } else if (name.find("A") != name.npos) { - // ignore (pushes all GP registoers onto the stack) - } else if (name[name.length() - 1] == 'm') { - POP("dst"); - } else { - POP("reg"); - } - } - - if (name.find("CALL") != name.npos) { - if (name.find("ADJ") != name.npos) { - // ignore (not a call) - } else if (name.find("SYSCALL") != name.npos) { - // ignore (doesn't go anywhere we know about) - } else if (name.find("VMCALL") != name.npos) { - // ignore (rather different semantics than a regular call) - } else if (name.find("VMMCALL") != name.npos) { - // ignore (rather different semantics than a regular call) - } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { - CALL("off"); - } else { - CALL("dst"); - } - } - - if (name.find("RET") != name.npos) { - RETURN(); - } -} - -#undef MOV -#undef BRANCH -#undef PUSH -#undef POP -#undef CALL -#undef RETURN - -///////////////////////////////////////////////////// -// Support functions for handling ARM instructions // -///////////////////////////////////////////////////// - -#define SET(flag) { type->set(flag); return 0; } - -#define REG(str) if (name == str) SET("kOperandTypeRegister"); -#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); - -#define MISC(str, type) if (name == str) SET(type); - -/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is -/// actually its type) and translates it into an operand type -/// -/// \param type The type object to set -/// \param name The name of the operand -static int ARMFlagFromOpName(LiteralConstantEmitter *type, - const std::string &name) { - REG("GPR"); - REG("rGPR"); - REG("GPRnopc"); - REG("GPRsp"); - REG("tcGPR"); - REG("cc_out"); - REG("s_cc_out"); - REG("tGPR"); - REG("DPR"); - REG("DPR_VFP2"); - REG("DPR_8"); - REG("DPair"); - REG("SPR"); - REG("QPR"); - REG("QQPR"); - REG("QQQQPR"); - REG("VecListOneD"); - REG("VecListDPair"); - REG("VecListDPairSpaced"); - REG("VecListThreeD"); - REG("VecListFourD"); - REG("VecListOneDAllLanes"); - REG("VecListDPairAllLanes"); - REG("VecListDPairSpacedAllLanes"); - - IMM("i32imm"); - IMM("fbits16"); - IMM("fbits32"); - IMM("i32imm_hilo16"); - IMM("bf_inv_mask_imm"); - IMM("lsb_pos_imm"); - IMM("width_imm"); - IMM("jtblock_operand"); - IMM("nohash_imm"); - IMM("p_imm"); - IMM("pf_imm"); - IMM("c_imm"); - IMM("coproc_option_imm"); - IMM("imod_op"); - IMM("iflags_op"); - IMM("cpinst_operand"); - IMM("setend_op"); - IMM("cps_opt"); - IMM("vfp_f64imm"); - IMM("vfp_f32imm"); - IMM("memb_opt"); - IMM("msr_mask"); - IMM("neg_zero"); - IMM("imm0_31"); - IMM("imm0_31_m1"); - IMM("imm1_16"); - IMM("imm1_32"); - IMM("nModImm"); - IMM("nImmSplatI8"); - IMM("nImmSplatI16"); - IMM("nImmSplatI32"); - IMM("nImmSplatI64"); - IMM("nImmVMOVI32"); - IMM("nImmVMOVF32"); - IMM("imm8"); - IMM("imm16"); - IMM("imm32"); - IMM("imm1_7"); - IMM("imm1_15"); - IMM("imm1_31"); - IMM("imm0_1"); - IMM("imm0_3"); - IMM("imm0_7"); - IMM("imm0_15"); - IMM("imm0_255"); - IMM("imm0_4095"); - IMM("imm0_65535"); - IMM("imm0_65535_expr"); - IMM("imm24b"); - IMM("pkh_lsl_amt"); - IMM("pkh_asr_amt"); - IMM("jt2block_operand"); - IMM("t_imm0_1020s4"); - IMM("t_imm0_508s4"); - IMM("pclabel"); - IMM("adrlabel"); - IMM("t_adrlabel"); - IMM("t2adrlabel"); - IMM("shift_imm"); - IMM("t2_shift_imm"); - IMM("neon_vcvt_imm32"); - IMM("shr_imm8"); - IMM("shr_imm16"); - IMM("shr_imm32"); - IMM("shr_imm64"); - IMM("t2ldrlabel"); - IMM("postidx_imm8"); - IMM("postidx_imm8s4"); - IMM("imm_sr"); - IMM("imm1_31"); - IMM("VectorIndex8"); - IMM("VectorIndex16"); - IMM("VectorIndex32"); - - MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("bltarget", "kOperandTypeARMBranchTarget"); // ? - - MISC("br_target", "kOperandTypeARMBranchTarget"); // ? - MISC("bl_target", "kOperandTypeARMBranchTarget"); // ? - MISC("blx_target", "kOperandTypeARMBranchTarget"); // ? - - MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I - MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I - MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I - MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I - MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I - MISC("so_imm", "kOperandTypeARMSoImm"); // I - MISC("rot_imm", "kOperandTypeARMRotImm"); // I - MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I - MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I - MISC("pred", "kOperandTypeARMPredicate"); // I, R - MISC("it_pred", "kOperandTypeARMPredicate"); // I - MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I - MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I - MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I - MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I - MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I - MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I - MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I - MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I - MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I - MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I - MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I - MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I - MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R - MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... - MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ... - MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ... - MISC("it_mask", "kOperandTypeThumbITMask"); // I - MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R - MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I - MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I - MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I - MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I - MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I - MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); - // R, I - MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I - MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R - MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R - MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R - MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I - MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I - MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I - MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R - MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I - MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I - MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R - MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R - - return 1; -} - -#undef REG -#undef MEM -#undef MISC - -#undef SET - -/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding -/// the appropriate flags to their descriptors -/// -/// \param operandTypes A reference the array of operand type objects -/// \param inst The instruction to use as a source of information -static void ARMPopulateOperands( - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - if (!inst.TheDef->isSubClassOf("InstARM") && - !inst.TheDef->isSubClassOf("InstThumb")) - return; - - unsigned int index; - unsigned int numOperands = inst.Operands.size(); - - if (numOperands > EDIS_MAX_OPERANDS) { - errs() << "numOperands == " << numOperands << " > " << - EDIS_MAX_OPERANDS << '\n'; - llvm_unreachable("Too many operands"); - } - - for (index = 0; index < numOperands; ++index) { - const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; - Record &rec = *operandInfo.Rec; - - if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { - errs() << "Operand type: " << rec.getName() << '\n'; - errs() << "Operand name: " << operandInfo.Name << '\n'; - errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; - PrintFatalError("Unhandled type in EDEmitter"); - } - } -} - -#define BRANCH(target) { \ - instType.set("kInstructionTypeBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -/// ARMExtractSemantics - Performs various checks on the name of an ARM -/// instruction to determine what sort of an instruction it is and then adds -/// the appropriate flags to the instruction and its operands -/// -/// \param instType A reference to the type for the instruction as a whole -/// \param operandTypes A reference to the array of operand type object pointers -/// \param operandFlags A reference to the array of operand flag object pointers -/// \param inst A reference to the original instruction -static void ARMExtractSemantics( - LiteralConstantEmitter &instType, - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - const std::string &name = inst.TheDef->getName(); - - if (name == "tBcc" || - name == "tB" || - name == "t2Bcc" || - name == "Bcc" || - name == "tCBZ" || - name == "tCBNZ") { - BRANCH("target"); - } - - if (name == "tBLr9" || - name == "BLr9_pred" || - name == "tBLXi_r9" || - name == "tBLXr_r9" || - name == "BLXr9" || - name == "t2BXJ" || - name == "BXJ") { - BRANCH("func"); - - unsigned opIndex; - opIndex = inst.Operands.getOperandNamed("func"); - if (operandTypes[opIndex]->is("kOperandTypeImmediate")) - operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); - } -} - -#undef BRANCH - -/// populateInstInfo - Fills an array of InstInfos with information about each -/// instruction in a target -/// -/// \param infoArray The array of InstInfo objects to populate -/// \param target The CodeGenTarget to use as a source of instructions -static void populateInstInfo(CompoundConstantEmitter &infoArray, - CodeGenTarget &target) { - const std::vector<const CodeGenInstruction*> &numberedInstructions = - target.getInstructionsByEnumValue(); - - unsigned int index; - unsigned int numInstructions = numberedInstructions.size(); - - for (index = 0; index < numInstructions; ++index) { - const CodeGenInstruction& inst = *numberedInstructions[index]; - - CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; - infoArray.addEntry(infoStruct); - - LiteralConstantEmitter *instType = new LiteralConstantEmitter; - infoStruct->addEntry(instType); - - LiteralConstantEmitter *numOperandsEmitter = - new LiteralConstantEmitter(inst.Operands.size()); - infoStruct->addEntry(numOperandsEmitter); - - CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; - infoStruct->addEntry(operandTypeArray); - - LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; - - CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; - infoStruct->addEntry(operandFlagArray); - - FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; - - for (unsigned operandIndex = 0; - operandIndex < EDIS_MAX_OPERANDS; - ++operandIndex) { - operandTypes[operandIndex] = new LiteralConstantEmitter; - operandTypeArray->addEntry(operandTypes[operandIndex]); - - operandFlags[operandIndex] = new FlagsConstantEmitter; - operandFlagArray->addEntry(operandFlags[operandIndex]); - } - - unsigned numSyntaxes = 0; - - // We don't need to do anything for pseudo-instructions, as we'll never - // see them here. We'll only see real instructions. - // We still need to emit null initializers for everything. - if (!inst.isPseudo) { - if (target.getName() == "X86") { - X86PopulateOperands(operandTypes, inst); - X86ExtractSemantics(*instType, operandFlags, inst); - numSyntaxes = 2; - } - else if (target.getName() == "ARM") { - ARMPopulateOperands(operandTypes, inst); - ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); - numSyntaxes = 1; - } - } - - CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; - - infoStruct->addEntry(operandOrderArray); - - for (unsigned syntaxIndex = 0; - syntaxIndex < EDIS_MAX_SYNTAXES; - ++syntaxIndex) { - CompoundConstantEmitter *operandOrder = - new CompoundConstantEmitter(EDIS_MAX_OPERANDS); - - operandOrderArray->addEntry(operandOrder); - - if (syntaxIndex < numSyntaxes) { - populateOperandOrder(operandOrder, inst, syntaxIndex); - } - } - - infoStruct = NULL; - } -} - -static void emitCommonEnums(raw_ostream &o, unsigned int &i) { - EnumEmitter operandTypes("OperandTypes"); - operandTypes.addEntry("kOperandTypeNone"); - operandTypes.addEntry("kOperandTypeImmediate"); - operandTypes.addEntry("kOperandTypeRegister"); - operandTypes.addEntry("kOperandTypeX86Memory"); - operandTypes.addEntry("kOperandTypeX86EffectiveAddress"); - operandTypes.addEntry("kOperandTypeX86PCRelative"); - operandTypes.addEntry("kOperandTypeARMBranchTarget"); - operandTypes.addEntry("kOperandTypeARMSoRegReg"); - operandTypes.addEntry("kOperandTypeARMSoRegImm"); - operandTypes.addEntry("kOperandTypeARMSoImm"); - operandTypes.addEntry("kOperandTypeARMRotImm"); - operandTypes.addEntry("kOperandTypeARMSoImm2Part"); - operandTypes.addEntry("kOperandTypeARMPredicate"); - operandTypes.addEntry("kOperandTypeAddrModeImm12"); - operandTypes.addEntry("kOperandTypeLdStSOReg"); - operandTypes.addEntry("kOperandTypeARMAddrMode2"); - operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); - operandTypes.addEntry("kOperandTypeARMAddrMode3"); - operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); - operandTypes.addEntry("kOperandTypeARMLdStmMode"); - operandTypes.addEntry("kOperandTypeARMAddrMode5"); - operandTypes.addEntry("kOperandTypeARMAddrMode6"); - operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); - operandTypes.addEntry("kOperandTypeARMAddrMode7"); - operandTypes.addEntry("kOperandTypeARMAddrModePC"); - operandTypes.addEntry("kOperandTypeARMRegisterList"); - operandTypes.addEntry("kOperandTypeARMDPRRegisterList"); - operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); - operandTypes.addEntry("kOperandTypeARMTBAddrMode"); - operandTypes.addEntry("kOperandTypeThumbITMask"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); - operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); - operandTypes.addEntry("kOperandTypeThumbAddrModePC"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeReg"); - operandTypes.addEntry("kOperandTypeThumb2SoReg"); - operandTypes.addEntry("kOperandTypeThumb2SoImm"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); - operandTypes.emit(o, i); - - o << "\n"; - - EnumEmitter operandFlags("OperandFlags"); - operandFlags.addEntry("kOperandFlagSource"); - operandFlags.addEntry("kOperandFlagTarget"); - operandFlags.emitAsFlags(o, i); - - o << "\n"; - - EnumEmitter instructionTypes("InstructionTypes"); - instructionTypes.addEntry("kInstructionTypeNone"); - instructionTypes.addEntry("kInstructionTypeMove"); - instructionTypes.addEntry("kInstructionTypeBranch"); - instructionTypes.addEntry("kInstructionTypePush"); - instructionTypes.addEntry("kInstructionTypePop"); - instructionTypes.addEntry("kInstructionTypeCall"); - instructionTypes.addEntry("kInstructionTypeReturn"); - instructionTypes.emit(o, i); - - o << "\n"; -} - -namespace llvm { - -void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS) { - emitSourceFileHeader("Enhanced Disassembler Info", OS); - unsigned int i = 0; - - CompoundConstantEmitter infoArray; - CodeGenTarget target(RK); - - populateInstInfo(infoArray, target); - - emitCommonEnums(OS, i); - - OS << "static const llvm::EDInstInfo instInfo" - << target.getName() << "[] = "; - infoArray.emit(OS, i); - OS << ";" << "\n"; -} - -} // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 5cabcad..0c3017f 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -15,8 +15,6 @@ #define DEBUG_TYPE "decoder-emitter" #include "CodeGenTarget.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -28,11 +26,12 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" - -#include <vector> #include <map> #include <string> +#include <vector> using namespace llvm; @@ -1867,7 +1866,7 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) { << " if (numBits == sizeof(InsnType)*8)\n" << " fieldMask = (InsnType)(-1LL);\n" << " else\n" - << " fieldMask = ((1 << numBits) - 1) << startBit;\n" + << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" << " return (insn & fieldMask) >> startBit;\n" << "}\n\n"; } diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index 48d41d7..d6020a8 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -16,8 +16,8 @@ #include "CodeGenDAGPatterns.h" #include "CodeGenSchedule.h" #include "CodeGenTarget.h" -#include "TableGenBackends.h" #include "SequenceToOffsetTable.h" +#include "TableGenBackends.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -271,7 +271,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { std::string ClassName = TargetName + "GenInstrInfo"; OS << "namespace llvm {\n"; - OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n" + OS << "struct " << ClassName << " : public TargetInstrInfo {\n" << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" << "};\n"; OS << "} // End llvm namespace \n"; @@ -286,7 +286,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; OS << "extern const char " << TargetName << "InstrNameData[];\n"; OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" - << " : TargetInstrInfoImpl(SO, DO) {\n" + << " : TargetInstrInfo(SO, DO) {\n" << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n"; diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index fe55242..df4d847 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -221,27 +221,28 @@ enum IIT_Info { IIT_I16 = 3, IIT_I32 = 4, IIT_I64 = 5, - IIT_F32 = 6, - IIT_F64 = 7, - IIT_V2 = 8, - IIT_V4 = 9, - IIT_V8 = 10, - IIT_V16 = 11, - IIT_V32 = 12, - IIT_MMX = 13, + IIT_F16 = 6, + IIT_F32 = 7, + IIT_F64 = 8, + IIT_V2 = 9, + IIT_V4 = 10, + IIT_V8 = 11, + IIT_V16 = 12, + IIT_V32 = 13, IIT_PTR = 14, IIT_ARG = 15, - + // Values from 16+ are only encodable with the inefficient encoding. - IIT_METADATA = 16, - IIT_EMPTYSTRUCT = 17, - IIT_STRUCT2 = 18, - IIT_STRUCT3 = 19, - IIT_STRUCT4 = 20, - IIT_STRUCT5 = 21, - IIT_EXTEND_VEC_ARG = 22, - IIT_TRUNC_VEC_ARG = 23, - IIT_ANYPTR = 24 + IIT_MMX = 16, + IIT_METADATA = 17, + IIT_EMPTYSTRUCT = 18, + IIT_STRUCT2 = 19, + IIT_STRUCT3 = 20, + IIT_STRUCT4 = 21, + IIT_STRUCT5 = 22, + IIT_EXTEND_VEC_ARG = 23, + IIT_TRUNC_VEC_ARG = 24, + IIT_ANYPTR = 25 }; @@ -261,6 +262,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, switch (VT) { default: PrintFatalError("unhandled MVT in intrinsic!"); + case MVT::f16: return Sig.push_back(IIT_F16); case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); case MVT::Metadata: return Sig.push_back(IIT_METADATA); @@ -511,10 +513,10 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << "// Add parameter attributes that are not common to all intrinsics.\n"; OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; if (TargetOnly) - OS << "static AttrListPtr getAttributes(LLVMContext &C, " << TargetPrefix + OS << "static AttributeSet getAttributes(LLVMContext &C, " << TargetPrefix << "Intrinsic::ID id) {\n"; else - OS << "AttrListPtr Intrinsic::getAttributes(LLVMContext &C, ID id) {\n"; + OS << "AttributeSet Intrinsic::getAttributes(LLVMContext &C, ID id) {\n"; // Compute the maximum number of attribute arguments and the map typedef std::map<const CodeGenIntrinsic*, unsigned, @@ -532,9 +534,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { N = ++AttrNum; } - // Emit an array of AttributeWithIndex. Most intrinsics will have - // at least one entry, for the function itself (index ~1), which is - // usually nounwind. + // Emit an array of AttributeSet. Most intrinsics will have at least one + // entry, for the function itself (index ~1), which is usually nounwind. OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { @@ -545,10 +546,10 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { } OS << " };\n\n"; - OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; + OS << " AttributeSet AS[" << maxArgAttrs+1 << "];\n"; OS << " unsigned NumAttrs = 0;\n"; OS << " if (id != 0) {\n"; - OS << " SmallVector<Attributes::AttrVal, 8> AttrVec;\n"; + OS << " SmallVector<Attribute::AttrKind, 8> AttrVec;\n"; OS << " switch(IntrinsicsToAttributesMap[id - "; if (TargetOnly) OS << "Intrinsic::num_intrinsics"; @@ -576,14 +577,14 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { do { switch (intrinsic.ArgumentAttributes[ai].second) { case CodeGenIntrinsic::NoCapture: - OS << " AttrVec.push_back(Attributes::NoCapture);\n"; + OS << " AttrVec.push_back(Attribute::NoCapture);\n"; break; } ++ai; } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(C, " + OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " << argNo+1 << ", AttrVec);\n"; } } @@ -594,34 +595,34 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " AttrVec.clear();\n"; if (!intrinsic.canThrow) - OS << " AttrVec.push_back(Attributes::NoUnwind);\n"; + OS << " AttrVec.push_back(Attribute::NoUnwind);\n"; if (intrinsic.isNoReturn) - OS << " AttrVec.push_back(Attributes::NoReturn);\n"; + OS << " AttrVec.push_back(Attribute::NoReturn);\n"; switch (modRef) { case MRK_none: break; case MRK_readonly: - OS << " AttrVec.push_back(Attributes::ReadOnly);\n"; + OS << " AttrVec.push_back(Attribute::ReadOnly);\n"; break; case MRK_readnone: - OS << " AttrVec.push_back(Attributes::ReadNone);\n"; + OS << " AttrVec.push_back(Attribute::ReadNone);\n"; break; } - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(C, " - << "AttrListPtr::FunctionIndex, AttrVec);\n"; + OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " + << "AttributeSet::FunctionIndex, AttrVec);\n"; } if (numAttrs) { OS << " NumAttrs = " << numAttrs << ";\n"; OS << " break;\n"; } else { - OS << " return AttrListPtr();\n"; + OS << " return AttributeSet();\n"; } } OS << " }\n"; OS << " }\n"; - OS << " return AttrListPtr::get(C, ArrayRef<AttributeWithIndex>(AWI, " + OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " "NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp new file mode 100644 index 0000000..0c1f623 --- /dev/null +++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp @@ -0,0 +1,266 @@ +//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Error.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <map> + +using namespace llvm; + +static int StrCmpOptionName(const char *A, const char *B) { + char a = *A, b = *B; + while (a == b) { + if (a == '\0') + return 0; + + a = *++A; + b = *++B; + } + + if (a == '\0') // A is a prefix of B. + return 1; + if (b == '\0') // B is a prefix of A. + return -1; + + // Otherwise lexicographic. + return (a < b) ? -1 : 1; +} + +static int CompareOptionRecords(const void *Av, const void *Bv) { + const Record *A = *(const Record*const*) Av; + const Record *B = *(const Record*const*) Bv; + + // Sentinel options precede all others and are only ordered by precedence. + bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); + bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); + if (ASent != BSent) + return ASent ? -1 : 1; + + // Compare options by name, unless they are sentinels. + if (!ASent) + if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(), + B->getValueAsString("Name").c_str())) + return Cmp; + + if (!ASent) { + std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes"); + std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes"); + + for (std::vector<std::string>::const_iterator APre = APrefixes.begin(), + AEPre = APrefixes.end(), + BPre = BPrefixes.begin(), + BEPre = BPrefixes.end(); + APre != AEPre && + BPre != BEPre; + ++APre, ++BPre) { + if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str())) + return Cmp; + } + } + + // Then by the kind precedence; + int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); + int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); + if (APrec == BPrec && + A->getValueAsListOfStrings("Prefixes") == + B->getValueAsListOfStrings("Prefixes")) { + PrintError(A->getLoc(), Twine("Option is equivilent to")); + PrintError(B->getLoc(), Twine("Other defined here")); + PrintFatalError("Equivalent Options found."); + } + return APrec < BPrec ? -1 : 1; +} + +static const std::string getOptionName(const Record &R) { + // Use the record name unless EnumName is defined. + if (isa<UnsetInit>(R.getValueInit("EnumName"))) + return R.getName(); + + return R.getValueAsString("EnumName"); +} + +static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { + OS << '"'; + OS.write_escaped(Str); + OS << '"'; + return OS; +} + +/// OptParserEmitter - This tablegen backend takes an input .td file +/// describing a list of options and emits a data structure for parsing and +/// working with those options when given an input command line. +namespace llvm { +void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { + // Get the option groups and options. + const std::vector<Record*> &Groups = + Records.getAllDerivedDefinitions("OptionGroup"); + std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); + + emitSourceFileHeader("Option Parsing Definitions", OS); + + array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); + // Generate prefix groups. + typedef SmallVector<SmallString<2>, 2> PrefixKeyT; + typedef std::map<PrefixKeyT, std::string> PrefixesT; + PrefixesT Prefixes; + Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); + unsigned CurPrefix = 0; + for (unsigned i = 0, e = Opts.size(); i != e; ++i) { + const Record &R = *Opts[i]; + std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); + PrefixKeyT prfkey(prf.begin(), prf.end()); + unsigned NewPrefix = CurPrefix + 1; + if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + + Twine(NewPrefix)).str())).second) + CurPrefix = NewPrefix; + } + + // Dump prefixes. + + OS << "/////////\n"; + OS << "// Prefixes\n\n"; + OS << "#ifdef PREFIX\n"; + OS << "#define COMMA ,\n"; + for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); + I != E; ++I) { + OS << "PREFIX("; + + // Prefix name. + OS << I->second; + + // Prefix values. + OS << ", {"; + for (PrefixKeyT::const_iterator PI = I->first.begin(), + PE = I->first.end(); PI != PE; ++PI) { + OS << "\"" << *PI << "\" COMMA "; + } + OS << "0})\n"; + } + OS << "#undef COMMA\n"; + OS << "#endif\n\n"; + + OS << "/////////\n"; + OS << "// Groups\n\n"; + OS << "#ifdef OPTION\n"; + for (unsigned i = 0, e = Groups.size(); i != e; ++i) { + const Record &R = *Groups[i]; + + // Start a single option entry. + OS << "OPTION("; + + // The option prefix; + OS << "0"; + + // The option string. + OS << ", \"" << R.getValueAsString("Name") << '"'; + + // The option identifier name. + OS << ", "<< getOptionName(R); + + // The option kind. + OS << ", Group"; + + // The containing option group (if any). + OS << ", "; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) + OS << getOptionName(*DI->getDef()); + else + OS << "INVALID"; + + // The other option arguments (unused for groups). + OS << ", INVALID, 0, 0"; + + // The option help text. + if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { + OS << ",\n"; + OS << " "; + write_cstring(OS, R.getValueAsString("HelpText")); + } else + OS << ", 0"; + + // The option meta-variable name (unused). + OS << ", 0)\n"; + } + OS << "\n"; + + OS << "//////////\n"; + OS << "// Options\n\n"; + for (unsigned i = 0, e = Opts.size(); i != e; ++i) { + const Record &R = *Opts[i]; + + // Start a single option entry. + OS << "OPTION("; + + // The option prefix; + std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); + OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; + + // The option string. + write_cstring(OS, R.getValueAsString("Name")); + + // The option identifier name. + OS << ", "<< getOptionName(R); + + // The option kind. + OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); + + // The containing option group (if any). + OS << ", "; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) + OS << getOptionName(*DI->getDef()); + else + OS << "INVALID"; + + // The option alias (if any). + OS << ", "; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias"))) + OS << getOptionName(*DI->getDef()); + else + OS << "INVALID"; + + // The option flags. + 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(); + } + } + + // The option parameter field. + OS << ", " << R.getValueAsInt("NumArgs"); + + // The option help text. + if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { + OS << ",\n"; + OS << " "; + write_cstring(OS, R.getValueAsString("HelpText")); + } else + OS << ", 0"; + + // The option meta-variable name. + OS << ", "; + if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) + write_cstring(OS, R.getValueAsString("MetaVarName")); + else + OS << "0"; + + OS << ")\n"; + } + OS << "#endif\n"; +} +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp index 64aaee7..1ea6f79 100644 --- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -252,6 +252,7 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { MIOpNo += Dest.Operands[OpNo].MINumOperands; } if (Dest.Operands.isVariadic) { + MIOpNo = Source.Operands.size() + 1; o << " // variable_ops\n"; o << " for (unsigned i = " << MIOpNo << ", e = MI->getNumOperands(); i != e; ++i)\n" diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 95b6267..1b5d90b 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -185,6 +185,36 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << " return RCWeightTable[RC->getID()];\n" << "}\n\n"; + // Reasonable targets (not ARMv7) have unit weight for all units, so don't + // bother generating a table. + bool RegUnitsHaveUnitWeight = true; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + if (RegBank.getRegUnit(UnitIdx).Weight > 1) + RegUnitsHaveUnitWeight = false; + } + OS << "/// Get the weight in units of pressure for this register unit.\n" + << "unsigned " << ClassName << "::\n" + << "getRegUnitWeight(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + if (!RegUnitsHaveUnitWeight) { + OS << " static const uint8_t RUWeightTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + const RegUnit &RU = RegBank.getRegUnit(UnitIdx); + assert(RU.Weight < 256 && "RegUnit too heavy"); + OS << RU.Weight << ", "; + } + OS << "0 };\n" + << " return RUWeightTable[RegUnit];\n"; + } + else { + OS << " // All register units have unit weight.\n" + << " return 1;\n"; + } + OS << "}\n\n"; + OS << "\n" << "// Get the number of dimensions of register pressure.\n" << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" @@ -215,14 +245,13 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << " return PressureLimitTable[Idx];\n" << "}\n\n"; - OS << "/// Get the dimensions of register pressure " - << "impacted by this register class.\n" - << "/// Returns a -1 terminated array of pressure set IDs\n" - << "const int* " << ClassName << "::\n" - << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n" - << " static const int RCSetsTable[] = {\n "; - std::vector<unsigned> RCSetStarts(NumRCs); - for (unsigned i = 0, StartIdx = 0, e = NumRCs; i != e; ++i) { + // This table may be larger than NumRCs if some register units needed a list + // of unit sets that did not correspond to a register class. + unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); + OS << "/// Table of pressure sets per register class or unit.\n" + << "static const int RCSetsTable[] = {\n "; + std::vector<unsigned> RCSetStarts(NumRCUnitSets); + for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) { RCSetStarts[i] = StartIdx; ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), @@ -230,10 +259,26 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, OS << *PSetI << ", "; ++StartIdx; } - OS << "-1, \t// " << RegBank.getRegClasses()[i]->getName() << "\n "; + OS << "-1, \t// #" << RCSetStarts[i] << " "; + if (i < NumRCs) + OS << RegBank.getRegClasses()[i]->getName(); + else { + OS << "inferred"; + for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), + PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { + OS << "~" << RegBank.getRegPressureSet(*PSetI).Name; + } + } + OS << "\n "; ++StartIdx; } - OS << "-1 };\n"; + OS << "-1 };\n\n"; + + OS << "/// Get the dimensions of register pressure impacted by this " + << "register class.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; OS << " static const unsigned RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { OS << RCSetStarts[i] << ","; @@ -242,6 +287,23 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" << " return &RCSetsTable[SetListStart];\n" << "}\n\n"; + + OS << "/// Get the dimensions of register pressure impacted by this " + << "register unit.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegUnitPressureSets(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + OS << " static const unsigned RUSetStartTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ","; + } + OS << "0 };\n" + << " unsigned SetListStart = RUSetStartTable[RegUnit];\n" + << " return &RCSetsTable[SetListStart];\n" + << "}\n\n"; } void @@ -729,7 +791,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, const std::string &TargetName = Target.getName(); // Emit the shared table of differential lists. - OS << "extern const uint16_t " << TargetName << "RegDiffLists[] = {\n"; + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n"; DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; @@ -859,9 +921,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n" + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " + << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " << RegBank.getNumNativeRegUnits() << ", " @@ -896,7 +958,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n" + << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n" << " virtual bool needsStackRealignment(const MachineFunction &) const\n" << " { return false; }\n"; if (!RegBank.getSubRegIndices().empty()) { @@ -907,11 +969,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, } OS << " virtual const RegClassWeight &getRegClassWeight(" << "const TargetRegisterClass *RC) const;\n" + << " virtual unsigned getRegUnitWeight(unsigned RegUnit) const;\n" << " virtual unsigned getNumRegPressureSets() const;\n" << " virtual const char *getRegPressureSetName(unsigned Idx) const;\n" << " virtual unsigned getRegPressureSetLimit(unsigned Idx) const;\n" << " virtual const int *getRegClassPressureSets(" << "const TargetRegisterClass *RC) const;\n" + << " virtual const int *getRegUnitPressureSets(unsigned RegUnit) const;\n" << "};\n\n"; ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); @@ -967,7 +1031,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } // Build a shared array of value types. - SequenceToOffsetTable<std::vector<MVT::SimpleValueType> > VTSeqs; + SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > VTSeqs; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) VTSeqs.add(RegisterClasses[rc]->VTs); VTSeqs.layout(); @@ -1074,12 +1138,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect << "}\n\n" - << "static ArrayRef<uint16_t> " << RC.getName() + << "static ArrayRef<MCPhysReg> " << RC.getName() << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { ArrayRef<Record*> Elems = RC.getOrder(oi); if (!Elems.empty()) { - OS << " static const uint16_t AltOrder" << oi << "[] = {"; + OS << " static const MCPhysReg AltOrder" << oi << "[] = {"; for (unsigned elem = 0; elem != Elems.size(); ++elem) OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); OS << " };\n"; @@ -1087,11 +1151,11 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << " const MCRegisterClass &MCR = " << Target.getName() << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" - << " const ArrayRef<uint16_t> Order[] = {\n" + << " const ArrayRef<MCPhysReg> Order[] = {\n" << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) if (RC.getOrder(oi).empty()) - OS << "),\n ArrayRef<uint16_t>("; + OS << "),\n ArrayRef<MCPhysReg>("; else OS << "),\n makeArrayRef(AltOrder" << oi; OS << ")\n };\n const unsigned Select = " << RC.getName() @@ -1194,7 +1258,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; - OS << "extern const uint16_t " << TargetName << "RegDiffLists[];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; @@ -1203,12 +1267,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, EmitRegMappingTables(OS, Regs, true); OS << ClassName << "::\n" << ClassName - << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" + << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexNameTable, SubRegIndexLaneMaskTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA,\n " << TargetName + << Regs.size()+1 << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" @@ -1232,7 +1296,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, assert(Regs && "Cannot expand CalleeSavedRegs instance"); // Emit the *_SaveList list of callee-saved registers. - OS << "static const uint16_t " << CSRSet->getName() + OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { "; for (unsigned r = 0, re = Regs->size(); r != re; ++r) OS << getQualifiedName((*Regs)[r]) << ", "; diff --git a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h index d4db152..fcda233 100644 --- a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h +++ b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h @@ -17,11 +17,11 @@ #define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H #include "llvm/Support/raw_ostream.h" -#include <functional> #include <algorithm> -#include <vector> #include <cassert> #include <cctype> +#include <functional> +#include <vector> namespace llvm { diff --git a/contrib/llvm/utils/TableGen/SetTheory.cpp b/contrib/llvm/utils/TableGen/SetTheory.cpp index 0dd9853..3e5c38c 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.cpp +++ b/contrib/llvm/utils/TableGen/SetTheory.cpp @@ -13,9 +13,9 @@ //===----------------------------------------------------------------------===// #include "SetTheory.h" +#include "llvm/Support/Format.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include "llvm/Support/Format.h" using namespace llvm; diff --git a/contrib/llvm/utils/TableGen/SetTheory.h b/contrib/llvm/utils/TableGen/SetTheory.h index 122372a..5baed79 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.h +++ b/contrib/llvm/utils/TableGen/SetTheory.h @@ -47,8 +47,8 @@ #ifndef SETTHEORY_H #define SETTHEORY_H -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/SourceMgr.h" #include <map> #include <vector> diff --git a/contrib/llvm/utils/TableGen/StringToOffsetTable.h b/contrib/llvm/utils/TableGen/StringToOffsetTable.h index a098d7d..d94d3a2 100644 --- a/contrib/llvm/utils/TableGen/StringToOffsetTable.h +++ b/contrib/llvm/utils/TableGen/StringToOffsetTable.h @@ -11,8 +11,8 @@ #define TBLGEN_STRING_TO_OFFSET_TABLE_H #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/raw_ostream.h" #include <cctype> diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index f1a06bb..98892e1 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -15,14 +15,14 @@ #include "CodeGenTarget.h" #include "CodeGenSchedule.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" #include <algorithm> #include <map> #include <string> @@ -87,6 +87,8 @@ class SubtargetEmitter { const CodeGenProcModel &ProcModel); Record *FindReadAdvance(const CodeGenSchedRW &SchedRead, const CodeGenProcModel &ProcModel); + void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles, + const CodeGenProcModel &ProcModel); void GenSchedClassTables(const CodeGenProcModel &ProcModel, SchedClassTables &SchedTables); void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS); @@ -445,17 +447,15 @@ EmitStageAndOperandCycleData(raw_ostream &OS, // If this processor defines no itineraries, then leave the itinerary list // empty. std::vector<InstrItinerary> &ItinList = ProcItinLists.back(); - if (ProcModel.ItinDefList.empty()) + if (!ProcModel.hasItineraries()) continue; - // Reserve index==0 for NoItinerary. - ItinList.resize(SchedModels.numItineraryClasses()+1); - const std::string &Name = ProcModel.ItinsDef->getName(); - // For each itinerary data - for (unsigned SchedClassIdx = 0, - SchedClassEnd = ProcModel.ItinDefList.size(); + ItinList.resize(SchedModels.numInstrSchedClasses()); + assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins"); + + for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size(); SchedClassIdx < SchedClassEnd; ++SchedClassIdx) { // Next itinerary data @@ -631,13 +631,31 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { Record *PRDef = ProcModel.ProcResourceDefs[i]; - // Find the SuperIdx - unsigned SuperIdx = 0; Record *SuperDef = 0; - if (PRDef->getValueInit("Super")->isComplete()) { - SuperDef = - SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel); - SuperIdx = ProcModel.getProcResourceIdx(SuperDef); + unsigned SuperIdx = 0; + unsigned NumUnits = 0; + bool IsBuffered = true; + if (PRDef->isSubClassOf("ProcResGroup")) { + RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources"); + for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end(); + RUI != RUE; ++RUI) { + if (!NumUnits) + IsBuffered = (*RUI)->getValueAsBit("Buffered"); + else if(IsBuffered != (*RUI)->getValueAsBit("Buffered")) + PrintFatalError(PRDef->getLoc(), + "Mixing buffered and unbuffered resources."); + NumUnits += (*RUI)->getValueAsInt("NumUnits"); + } + } + else { + // Find the SuperIdx + if (PRDef->getValueInit("Super")->isComplete()) { + SuperDef = SchedModels.findProcResUnits( + PRDef->getValueAsDef("Super"), ProcModel); + SuperIdx = ProcModel.getProcResourceIdx(SuperDef); + } + NumUnits = PRDef->getValueAsInt("NumUnits"); + IsBuffered = PRDef->getValueAsBit("Buffered"); } // Emit the ProcResourceDesc if (i+1 == e) @@ -645,8 +663,8 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, OS << " {DBGFIELD(\"" << PRDef->getName() << "\") "; if (PRDef->getName().size() < 15) OS.indent(15 - PRDef->getName().size()); - OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx << ", " - << PRDef->getValueAsBit("Buffered") << "}" << Sep << " // #" << i+1; + OS << NumUnits << ", " << SuperIdx << ", " + << IsBuffered << "}" << Sep << " // #" << i+1; if (SuperDef) OS << ", Super=" << SuperDef->getName(); OS << "\n"; @@ -763,6 +781,51 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return ResDef; } +// Expand an explicit list of processor resources into a full list of implied +// resource groups that cover them. +// +// FIXME: Effectively consider a super-resource a group that include all of its +// subresources to allow mixing and matching super-resources and groups. +// +// FIXME: Warn if two overlapping groups don't have a common supergroup. +void SubtargetEmitter::ExpandProcResources(RecVec &PRVec, + std::vector<int64_t> &Cycles, + const CodeGenProcModel &ProcModel) { + // Default to 1 resource cycle. + Cycles.resize(PRVec.size(), 1); + for (unsigned i = 0, e = PRVec.size(); i != e; ++i) { + RecVec SubResources; + if (PRVec[i]->isSubClassOf("ProcResGroup")) { + SubResources = PRVec[i]->getValueAsListOfDefs("Resources"); + std::sort(SubResources.begin(), SubResources.end(), LessRecord()); + } + else { + SubResources.push_back(PRVec[i]); + } + for (RecIter PRI = ProcModel.ProcResourceDefs.begin(), + PRE = ProcModel.ProcResourceDefs.end(); + PRI != PRE; ++PRI) { + if (*PRI == PRVec[i] || !(*PRI)->isSubClassOf("ProcResGroup")) + continue; + RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources"); + std::sort(SuperResources.begin(), SuperResources.end(), LessRecord()); + RecIter SubI = SubResources.begin(), SubE = SubResources.end(); + RecIter SuperI = SuperResources.begin(), SuperE = SuperResources.end(); + for ( ; SubI != SubE && SuperI != SuperE; ++SuperI) { + if (*SubI < *SuperI) + break; + else if (*SuperI < *SubI) + continue; + ++SubI; + } + if (SubI == SubE) { + PRVec.push_back(*PRI); + Cycles.push_back(Cycles[i]); + } + } + } +} + // Generate the SchedClass table for this processor and update global // tables. Must be called for each processor in order. void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, @@ -787,7 +850,22 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, SCDesc.ReadAdvanceIdx = 0; // A Variant SchedClass has no resources of its own. - if (!SCI->Transitions.empty()) { + bool HasVariants = false; + for (std::vector<CodeGenSchedTransition>::const_iterator + TI = SCI->Transitions.begin(), TE = SCI->Transitions.end(); + TI != TE; ++TI) { + if (TI->ProcIndices[0] == 0) { + HasVariants = true; + break; + } + IdxIter PIPos = std::find(TI->ProcIndices.begin(), + TI->ProcIndices.end(), ProcModel.Index); + if (PIPos != TI->ProcIndices.end()) { + HasVariants = true; + break; + } + } + if (HasVariants) { SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps; continue; } @@ -804,27 +882,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, } IdxVec Writes = SCI->Writes; IdxVec Reads = SCI->Reads; - if (SCI->ItinClassDef) { - assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs"); - // Check this processor's itinerary class resources. - for (RecIter II = ProcModel.ItinRWDefs.begin(), - IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) { - RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); - if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef) - != Matched.end()) { - SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), - Writes, Reads); - break; - } - } - if (Writes.empty()) { - DEBUG(dbgs() << ProcModel.ItinsDef->getName() - << " does not have resources for itinerary class " - << SCI->ItinClassDef->getName() << '\n'); - } - } - else if (!SCI->InstRWs.empty()) { - // This class may have a default ReadWrite list which can be overriden by + if (!SCI->InstRWs.empty()) { + // This class has a default ReadWrite list which can be overriden by // InstRW definitions. Record *RWDef = 0; for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); @@ -842,6 +901,23 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, Writes, Reads); } } + if (Writes.empty()) { + // Check this processor's itinerary class resources. + for (RecIter II = ProcModel.ItinRWDefs.begin(), + IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) { + RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); + if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef) + != Matched.end()) { + SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); + break; + } + } + if (Writes.empty()) { + DEBUG(dbgs() << ProcModel.ModelName + << " does not have resources for class " << SCI->Name << '\n'); + } + } // Sum resources across all operand writes. std::vector<MCWriteProcResEntry> WriteProcResources; std::vector<MCWriteLatencyEntry> WriteLatencies; @@ -859,7 +935,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name); // If this Write is not referenced by a ReadAdvance, don't distinguish it // from other WriteLatency entries. - if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) { + if (!SchedModels.hasReadOfWrite( + SchedModels.getSchedWrite(WriteID).TheDef)) { WriteID = 0; } WLEntry.WriteResourceID = WriteID; @@ -884,16 +961,29 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources"); std::vector<int64_t> Cycles = WriteRes->getValueAsListOfInts("ResourceCycles"); + + ExpandProcResources(PRVec, Cycles, ProcModel); + for (unsigned PRIdx = 0, PREnd = PRVec.size(); PRIdx != PREnd; ++PRIdx) { MCWriteProcResEntry WPREntry; WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]); assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx"); - if (Cycles.size() > PRIdx) - WPREntry.Cycles = Cycles[PRIdx]; - else - WPREntry.Cycles = 1; - WriteProcResources.push_back(WPREntry); + WPREntry.Cycles = Cycles[PRIdx]; + // If this resource is already used in this sequence, add the current + // entry's cycles so that the same resource appears to be used + // serially, rather than multiple parallel uses. This is important for + // in-order machine where the resource consumption is a hazard. + unsigned WPRIdx = 0, WPREnd = WriteProcResources.size(); + for( ; WPRIdx != WPREnd; ++WPRIdx) { + if (WriteProcResources[WPRIdx].ProcResourceIdx + == WPREntry.ProcResourceIdx) { + WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles; + break; + } + } + if (WPRIdx == WPREnd) + WriteProcResources.push_back(WPREntry); } } WriteLatencies.push_back(WLEntry); @@ -1062,7 +1152,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables, // The first class is always invalid. We no way to distinguish it except by // name and position. - assert(SchedModels.getSchedClass(0).Name == "NoItinerary" + assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" && "invalid class not first"); OS << " {DBGFIELD(\"InvalidSchedClass\") " << MCSchedClassDesc::InvalidNumMicroOps @@ -1108,6 +1198,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); + EmitProcessorProp(OS, PI->ModelDef, "ILPWindow", ','); EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); OS << " " << PI->Index << ", // Processor ID\n"; if (PI->hasInstrSchedModel()) @@ -1118,7 +1209,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraryClasses()) + if (SchedModels.hasItineraries()) OS << " " << PI->ItinsDef->getName() << ");\n"; else OS << " 0); // No Itinerary\n"; @@ -1175,7 +1266,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { << "#define DBGFIELD(x)\n" << "#endif\n"; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { std::vector<std::vector<InstrItinerary> > ProcItinLists; // Emit the stage data EmitStageAndOperandCycleData(OS, ProcItinLists); @@ -1216,7 +1307,7 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) { if (SCI->Transitions.empty()) continue; - VariantClasses.push_back(SCI - SchedModels.schedClassBegin()); + VariantClasses.push_back(SCI->Index); } if (!VariantClasses.empty()) { OS << " switch (SchedClass) {\n"; @@ -1263,13 +1354,8 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, if (*PI == 0) break; } - unsigned SCIdx = 0; - if (SC.ItinClassDef) - SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef); - else - SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads); - if (SCIdx != *VCI) - OS << " return " << SCIdx << ";\n"; + if (SC.isInferred()) + OS << " return " << SC.Index << ";\n"; OS << " break;\n"; } OS << " };\n"; @@ -1375,7 +1461,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << '\n'; OS.indent(22); OS << Target << "Stages, " << Target << "OperandCycles, " @@ -1432,7 +1518,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "extern const llvm::MCReadAdvanceEntry " << Target << "ReadAdvanceTable[];\n"; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; OS << "extern const unsigned " << Target << "OperandCycles[];\n"; OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; @@ -1456,7 +1542,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; OS << '\n'; OS.indent(22); - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << Target << "Stages, " << Target << "OperandCycles, " << Target << "ForwardingPaths, "; diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index 49efe7e..b5c3ca7 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "TableGenBackends.h" // Declares all backends. - #include "SetTheory.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" @@ -39,9 +38,10 @@ enum ActionType { GenSubtarget, GenIntrinsic, GenTgtIntrinsic, - GenEDInfo, PrintEnums, - PrintSets + PrintSets, + GenOptParserDefs, + GenCTags }; namespace { @@ -77,12 +77,14 @@ namespace { "Generate intrinsic information"), clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", "Generate target intrinsic information"), - clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", - "Generate enhanced disassembly info"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValN(PrintSets, "print-sets", "Print expanded sets for testing DAG exprs"), + clEnumValN(GenOptParserDefs, "gen-opt-parser-defs", + "Generate option definitions"), + clEnumValN(GenCTags, "gen-ctags", + "Generate ctags-compatible index"), clEnumValEnd)); cl::opt<std::string> @@ -136,8 +138,8 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenTgtIntrinsic: EmitIntrinsics(Records, OS, true); break; - case GenEDInfo: - EmitEnhancedDisassemblerInfo(Records, OS); + case GenOptParserDefs: + EmitOptParser(Records, OS); break; case PrintEnums: { @@ -162,6 +164,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { } break; } + case GenCTags: + EmitCTags(Records, OS); + break; } return false; diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h index f0d25d8..28b626e 100644 --- a/contrib/llvm/utils/TableGen/TableGenBackends.h +++ b/contrib/llvm/utils/TableGen/TableGenBackends.h @@ -68,12 +68,13 @@ void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS); void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS); void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS); void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS); -void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS); void EmitFastISel(RecordKeeper &RK, raw_ostream &OS); void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS); void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS); void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS); void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS); void EmitMapTable(RecordKeeper &RK, raw_ostream &OS); +void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); +void EmitCTags(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h index c13a0cc..3ff922b 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h +++ b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h @@ -10,8 +10,8 @@ #ifndef X86DISASSEMBLERSHARED_H #define X86DISASSEMBLERSHARED_H -#include <string> #include <string.h> +#include <string> #define INSTRUCTION_SPECIFIER_FIELDS \ struct OperandSpecifier operands[X86_MAX_OPERANDS]; \ diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp index 468a1f8..40a0c1b 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -14,13 +14,12 @@ // //===----------------------------------------------------------------------===// -#include "X86DisassemblerShared.h" #include "X86DisassemblerTables.h" - -#include "llvm/TableGen/TableGenBackend.h" +#include "X86DisassemblerShared.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/TableGen/TableGenBackend.h" #include <map> using namespace llvm; diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h index ea006c0..01aeaaf 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h @@ -19,9 +19,7 @@ #include "X86DisassemblerShared.h" #include "X86ModRMFilters.h" - #include "llvm/Support/raw_ostream.h" - #include <vector> namespace llvm { diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index d6ed2fe..61b9813 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -14,12 +14,10 @@ // //===----------------------------------------------------------------------===// -#include "X86DisassemblerShared.h" #include "X86RecognizableInstr.h" +#include "X86DisassemblerShared.h" #include "X86ModRMFilters.h" - #include "llvm/Support/ErrorHandling.h" - #include <string> using namespace llvm; @@ -39,14 +37,15 @@ using namespace llvm; MAP(D1, 46) \ MAP(D4, 47) \ MAP(D5, 48) \ - MAP(D8, 49) \ - MAP(D9, 50) \ - MAP(DA, 51) \ - MAP(DB, 52) \ - MAP(DC, 53) \ - MAP(DD, 54) \ - MAP(DE, 55) \ - MAP(DF, 56) + MAP(D6, 49) \ + MAP(D8, 50) \ + MAP(D9, 51) \ + MAP(DA, 52) \ + MAP(DB, 53) \ + MAP(DC, 54) \ + MAP(DD, 55) \ + MAP(DE, 56) \ + MAP(DF, 57) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -121,6 +120,7 @@ namespace X86Local { #define TWO_BYTE_EXTENSION_TABLES \ EXTENSION_TABLE(00) \ EXTENSION_TABLE(01) \ + EXTENSION_TABLE(0d) \ EXTENSION_TABLE(18) \ EXTENSION_TABLE(71) \ EXTENSION_TABLE(72) \ @@ -765,6 +765,17 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(immediate) HANDLE_OPERAND(immediate) break; + case X86Local::MRM_F8: + if (Opcode == 0xc6) { + assert(numPhysicalOperands == 1 && + "Unexpected number of operands for X86Local::MRM_F8"); + HANDLE_OPERAND(immediate) + } else if (Opcode == 0xc7) { + assert(numPhysicalOperands == 1 && + "Unexpected number of operands for X86Local::MRM_F8"); + HANDLE_OPERAND(relocation) + } + break; case X86Local::MRMInitReg: // Ignored. break; diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h index 9feb3c3..9ec36a3 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -17,13 +17,11 @@ #ifndef X86RECOGNIZABLEINSTR_H #define X86RECOGNIZABLEINSTR_H -#include "X86DisassemblerTables.h" - #include "CodeGenTarget.h" - -#include "llvm/TableGen/Record.h" -#include "llvm/Support/DataTypes.h" +#include "X86DisassemblerTables.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/TableGen/Record.h" namespace llvm { |